xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 678453a8)
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>
30*678453a8Sspeer #include <sys/nxge/nxge_hio.h>
3144961713Sgirish 
3298ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3398ecde52Stm #define	LM_WAIT_MULTIPLIER	8
3498ecde52Stm 
35321febdeSsbehera #define	SERDES_RDY_WT_INTERVAL	50
36321febdeSsbehera #define	MAX_SERDES_RDY_RETRIES	10
37321febdeSsbehera 
3844961713Sgirish extern uint32_t nxge_no_link_notify;
3959ac0c16Sdavemq extern boolean_t nxge_no_msg;
4044961713Sgirish extern uint32_t nxge_lb_dbg;
4144961713Sgirish extern boolean_t nxge_jumbo_enable;
424202ea4bSsbehera extern uint32_t nxge_jumbo_mtu;
4344961713Sgirish 
44*678453a8Sspeer 	/* The following functions may be found in nxge_main.c */
45*678453a8Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot,
46*678453a8Sspeer 	boolean_t factory);
47*678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
48*678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
49*678453a8Sspeer 
5098ecde52Stm typedef enum {
5198ecde52Stm 	CHECK_LINK_RESCHEDULE,
5298ecde52Stm 	CHECK_LINK_STOP
5398ecde52Stm } check_link_state_t;
5498ecde52Stm 
5598ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
5698ecde52Stm 
5744961713Sgirish /*
5844961713Sgirish  * Ethernet broadcast address definition.
5944961713Sgirish  */
6044961713Sgirish static ether_addr_st etherbroadcastaddr =
6144961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
6259ac0c16Sdavemq /*
6359ac0c16Sdavemq  * Ethernet zero address definition.
6459ac0c16Sdavemq  */
6556d930aeSspeer static ether_addr_st etherzeroaddr =
6656d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
6759ac0c16Sdavemq /*
6859ac0c16Sdavemq  * Supported chip types
6959ac0c16Sdavemq  */
702d17280bSsbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID};
7159a835ddSjoycey static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID, BCM5482_PHY_ID};
7259ac0c16Sdavemq 
7359ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
7459ac0c16Sdavemq 				sizeof (uint32_t))
7559ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
7659ac0c16Sdavemq 				sizeof (uint32_t))
7759ac0c16Sdavemq /*
7859ac0c16Sdavemq  * static functions
7959ac0c16Sdavemq  */
802e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
812e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
822e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
8359ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
842d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
8559ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
8659ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
8759ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
8859ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
8959ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
9059ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
9159ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
9259ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
9359ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
9459ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
9559ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
9659ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
972d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
982d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
9959ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
10059ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
10159ac0c16Sdavemq 
10259ac0c16Sdavemq /*
10359ac0c16Sdavemq  * xcvr tables for supported transceivers
10459ac0c16Sdavemq  */
10559ac0c16Sdavemq 
1062e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
10759ac0c16Sdavemq 	nxge_n2_serdes_init,
10859ac0c16Sdavemq 	nxge_10G_xcvr_init,
10959ac0c16Sdavemq 	nxge_10G_link_intr_stop,
11059ac0c16Sdavemq 	nxge_10G_link_intr_start,
11159ac0c16Sdavemq 	nxge_check_10g_link,
1122d17280bSsbehera 	PCS_XCVR
11359ac0c16Sdavemq };
11459ac0c16Sdavemq 
1152e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1162e59129aSraghus 	nxge_n2_serdes_init,
1172e59129aSraghus 	nxge_1G_xcvr_init,
1182e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1192e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1202e59129aSraghus 	nxge_check_mii_link,
1212d17280bSsbehera 	PCS_XCVR
1222e59129aSraghus };
1232e59129aSraghus 
12459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
12559ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
12659ac0c16Sdavemq 	nxge_10G_xcvr_init,
12759ac0c16Sdavemq 	nxge_10G_link_intr_stop,
12859ac0c16Sdavemq 	nxge_10G_link_intr_start,
12959ac0c16Sdavemq 	nxge_check_10g_link,
1302d17280bSsbehera 	PCS_XCVR
13159ac0c16Sdavemq };
13259ac0c16Sdavemq 
13359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
13459ac0c16Sdavemq 	NULL,
13559ac0c16Sdavemq 	nxge_1G_xcvr_init,
13659ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
13759ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
13859ac0c16Sdavemq 	nxge_check_mii_link,
1392d17280bSsbehera 	INT_MII_XCVR
14059ac0c16Sdavemq };
14159ac0c16Sdavemq 
14259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
14359ac0c16Sdavemq 	nxge_1G_serdes_init,
14459ac0c16Sdavemq 	nxge_1G_xcvr_init,
14559ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
14659ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
14759ac0c16Sdavemq 	nxge_check_mii_link,
1482d17280bSsbehera 	PCS_XCVR
14959ac0c16Sdavemq };
15059ac0c16Sdavemq 
15159ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
15259ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
15359ac0c16Sdavemq 	NULL,
15459ac0c16Sdavemq 	NULL,
15559ac0c16Sdavemq 	NULL,
1562e59129aSraghus 	NULL,
1572d17280bSsbehera 	PCS_XCVR
15859ac0c16Sdavemq };
15944961713Sgirish 
16044961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t);
16144961713Sgirish 
162d81011f0Ssbehera #ifdef NXGE_DEBUG
163d81011f0Ssbehera static void nxge_mii_dump(p_nxge_t);
164d81011f0Ssbehera #endif
165d81011f0Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
166d81011f0Ssbehera 
1672e59129aSraghus nxge_status_t
1682e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
1692e59129aSraghus {
1702e59129aSraghus 	nxge_status_t status = NXGE_OK;
1712e59129aSraghus 	char *phy_type;
1722e59129aSraghus 	char *prop_val;
1732e59129aSraghus 
1742e59129aSraghus 	nxgep->mac.portmode = 0;
1752d17280bSsbehera 	nxgep->xcvr_addr = 0;
1762e59129aSraghus 
1772d17280bSsbehera 	/*
1782d17280bSsbehera 	 * First check for hot swappable phy property.
1792d17280bSsbehera 	 */
1802d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
1812d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1822d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1832d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
1842d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
1852d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1862d17280bSsbehera 	    "hot-swappable-phy") == 1) {
1872d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1882d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1892d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
1902d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
1912d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
1922d17280bSsbehera 	    "hot-swappable-phy") == 1) {
1932d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1942d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1952d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
1962d17280bSsbehera 	}
1972d17280bSsbehera 
1982d17280bSsbehera 	/*
1992d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
2002d17280bSsbehera 	 */
2012d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
2022d17280bSsbehera 
2032d17280bSsbehera 		uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2042d17280bSsbehera 
2052d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
2062d17280bSsbehera 		/*
2072d17280bSsbehera 		 * If this is the 2nd NIU port, then check 2 addresses
2082d17280bSsbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
2092d17280bSsbehera 		 * (in the eval board) or 20 (in the P0 board).
2102d17280bSsbehera 		 */
2112d17280bSsbehera 		if (portn == 1) {
2122d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
2132d17280bSsbehera 			    BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID,
2142d17280bSsbehera 			    BCM_PHY_ID_MASK)) {
2152d17280bSsbehera 				nxgep->xcvr_addr =
2162d17280bSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR;
2172d17280bSsbehera 				goto found_phy;
2182d17280bSsbehera 			}
2192d17280bSsbehera 		}
2202d17280bSsbehera 		if (nxge_is_phy_present(nxgep,
221*678453a8Sspeer 		    BCM8706_GOA_PORT_ADDR_BASE + portn,
2222d17280bSsbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
223*678453a8Sspeer 			nxgep->xcvr_addr = BCM8706_GOA_PORT_ADDR_BASE +
2242d17280bSsbehera 			    portn;
2252d17280bSsbehera 			goto found_phy;
2262d17280bSsbehera 		}
2272d17280bSsbehera 
2282d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
2292d17280bSsbehera 		goto check_phy_done;
2302d17280bSsbehera found_phy:
2312d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2322d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
2332d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
2342d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
2352d17280bSsbehera 		    "found for hot swappable phy"));
2362d17280bSsbehera check_phy_done:
2372d17280bSsbehera 		return (status);
2382d17280bSsbehera 	}
2392d17280bSsbehera 
2402d17280bSsbehera 	/* Get phy-type property from the driver conf. file */
2412e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
2422e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2432e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
2442e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2452e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
2462e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
2472e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2482e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
2492e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2502e59129aSraghus 			    "found: 10G Serdes"));
2512e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
2522e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2532e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
2542e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
2552e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
2562e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
2572e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
2582e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
2592e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
2602e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2612e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
2622e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
263321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
264321febdeSsbehera 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
265321febdeSsbehera 			nxgep->mac.portmode = PORT_10G_FIBER;
266321febdeSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr"));
2672e59129aSraghus 		}
2682e59129aSraghus 
2692e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
2702e59129aSraghus 		    "phy-type", prop_val);
2712e59129aSraghus 		ddi_prop_free(prop_val);
2722e59129aSraghus 
2732e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
2742e59129aSraghus 		    "Got phy type [0x%x] from conf file",
2752e59129aSraghus 		    nxgep->mac.portmode));
2762e59129aSraghus 
2772e59129aSraghus 		return (NXGE_OK);
2782e59129aSraghus 	}
2792d17280bSsbehera 
2802d17280bSsbehera 	/* Get phy-type property from OBP */
2812e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
2822e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
2832e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
2842e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
2852e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2862e59129aSraghus 				    XPCS_XCVR;
2872e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
2882e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2892e59129aSraghus 				    "10G Fiber Xcvr"));
2902e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
2912e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2922e59129aSraghus 				    INT_MII_XCVR;
2932e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
2942e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2952e59129aSraghus 				    "1G Copper Xcvr"));
2962e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
2972e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2982e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
2992e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3002e59129aSraghus 				    "1G Fiber Xcvr"));
3012e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
3022e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
3032e59129aSraghus 				    XPCS_XCVR;
3042e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
3052e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3062e59129aSraghus 				    "10G Copper Xcvr"));
3072e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
3082e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3092e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
3102e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3112e59129aSraghus 				    "OBP: 10G Serdes"));
3122e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
3132e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3142e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
3152e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3162e59129aSraghus 				    "OBP: 1G Serdes"));
3172e59129aSraghus 			} else {
3182e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3192e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
3202e59129aSraghus 				ddi_prop_free(prop_val);
3212e59129aSraghus 				return (NXGE_ERROR);
3222e59129aSraghus 			}
3232e59129aSraghus 			status = NXGE_OK;
3242e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3252e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
3262e59129aSraghus 			ddi_prop_free(prop_val);
3272e59129aSraghus 
3282e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3292e59129aSraghus 			    "Got phy type [0x%x] from OBP",
3302e59129aSraghus 			    nxgep->mac.portmode));
3312e59129aSraghus 
3322e59129aSraghus 			return (status);
3332e59129aSraghus 		} else {
3342e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3352e59129aSraghus 			    "Exiting...phy-type property not found"));
3362e59129aSraghus 			return (NXGE_ERROR);
3372e59129aSraghus 		}
3382e59129aSraghus 	}
3392e59129aSraghus 
3402e59129aSraghus 
3412e59129aSraghus 	if (!nxgep->vpd_info.present) {
3422e59129aSraghus 		return (NXGE_OK);
3432e59129aSraghus 	}
3442e59129aSraghus 
3452e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
3462e59129aSraghus 		goto read_seeprom;
3472e59129aSraghus 	}
3482e59129aSraghus 
3492e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3502e59129aSraghus 	    "Reading phy type from expansion ROM"));
3512e59129aSraghus 	/*
3522e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
3532e59129aSraghus 	 * expansion ROM.
3542e59129aSraghus 	 */
3552e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
3562e59129aSraghus 
357d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
3582e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
3592e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
360d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
3612e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
3622e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
363d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
3642e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
3652e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
366d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
3672e59129aSraghus 		nxgep->mac.portmode = PORT_10G_COPPER;
3682e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
369d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
370d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
371d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
372d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
373d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
374d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3752e59129aSraghus 	} else {
376d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3772e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
3782e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
3792e59129aSraghus 		goto read_seeprom;
3802e59129aSraghus 	}
3812e59129aSraghus 
3822e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3832e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
3842e59129aSraghus 
3852e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
3862e59129aSraghus 	return (status);
3872e59129aSraghus 
3882e59129aSraghus read_seeprom:
3892e59129aSraghus 	/*
3902e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
3912e59129aSraghus 	 */
3922e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
3932e59129aSraghus 	if (status != NXGE_OK) {
3942e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3952e59129aSraghus 		    "Failed to get phy type"));
3962e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3972e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
3982e59129aSraghus 	}
3992e59129aSraghus 
4002e59129aSraghus 	return (status);
4012e59129aSraghus 
4022e59129aSraghus }
4032e59129aSraghus 
40459ac0c16Sdavemq /* Set up the PHY specific values. */
40559ac0c16Sdavemq 
40659ac0c16Sdavemq nxge_status_t
40759ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
40859ac0c16Sdavemq {
40959ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
41059ac0c16Sdavemq 	uint32_t	port_type;
41159ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4122e59129aSraghus 	uint32_t	pcs_id = 0;
4132e59129aSraghus 	uint32_t	pma_pmd_id = 0;
4142e59129aSraghus 	uint32_t	phy_id = 0;
4152d17280bSsbehera 	uint16_t	chip_id = 0;
41659ac0c16Sdavemq 
41759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
41859ac0c16Sdavemq 	    portn));
41959ac0c16Sdavemq 
4202e59129aSraghus 	switch (nxgep->niu_type) {
4212e59129aSraghus 	case N2_NIU:
4222e59129aSraghus 		switch (nxgep->mac.portmode) {
4232e59129aSraghus 		case PORT_1G_FIBER:
4242e59129aSraghus 		case PORT_1G_SERDES:
4252e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
4262d17280bSsbehera 			nxgep->xcvr_addr = portn;
4272e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
4282e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
4292e59129aSraghus 			    "Serdes"));
4302e59129aSraghus 			break;
4312e59129aSraghus 		case PORT_10G_FIBER:
4322e59129aSraghus 		case PORT_10G_SERDES:
4332e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
4342d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
4352d17280bSsbehera 				nxgep->xcvr_addr =
4362d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
4372d17280bSsbehera 			}
4382e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
4392e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
4402e59129aSraghus 			    "Serdes"));
4412e59129aSraghus 			break;
4422d17280bSsbehera 		case PORT_HSP_MODE:
4432d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
4442d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
4452d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
4462d17280bSsbehera 			    "Swappable Xcvr (not present)"));
4472d17280bSsbehera 			break;
4482e59129aSraghus 		default:
4492e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4502e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
4512e59129aSraghus 			    "Unable to determine NIU portmode"));
4522e59129aSraghus 			return (NXGE_ERROR);
4532e59129aSraghus 		}
4542e59129aSraghus 		break;
4552e59129aSraghus 	default:
4562e59129aSraghus 		if (nxgep->mac.portmode == 0) {
4572e59129aSraghus 			/*
4582e59129aSraghus 			 * Would be the case for platforms like Maramba
4592e59129aSraghus 			 * in which the phy type could not be got from conf
4602e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
4612e59129aSraghus 			 */
4622e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4632e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4642e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
4652e59129aSraghus 				    " Invalid Neptune type [0x%x]",
4662e59129aSraghus 				    nxgep->niu_type));
4672e59129aSraghus 				return (NXGE_ERROR);
4682e59129aSraghus 			}
4692e59129aSraghus 
4702e59129aSraghus 			port_type = nxgep->niu_type >>
4712e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
4722e59129aSraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
4732e59129aSraghus 
4742e59129aSraghus 			switch (port_type) {
4752e59129aSraghus 
4762e59129aSraghus 			case NXGE_PORT_1G_COPPER:
4772e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4782e59129aSraghus 				break;
4792e59129aSraghus 			case NXGE_PORT_10G_COPPER:
4802e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
4812e59129aSraghus 				break;
4822e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
4832e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4842e59129aSraghus 				break;
4852e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
4862e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
4872e59129aSraghus 				break;
4882e59129aSraghus 			case NXGE_PORT_1G_SERDES:
4892e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4902e59129aSraghus 				break;
4912e59129aSraghus 			case NXGE_PORT_10G_SERDES:
4922e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4932e59129aSraghus 				break;
4942e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
4952e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
4962e59129aSraghus 				break;
4972e59129aSraghus 			default:
4982e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4992e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
5002e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
5012e59129aSraghus 				return (NXGE_ERROR);
5022e59129aSraghus 			}
5032e59129aSraghus 		}
5042e59129aSraghus 
5052e59129aSraghus 		switch (nxgep->mac.portmode) {
5062e59129aSraghus 		case PORT_1G_COPPER:
5072e59129aSraghus 		case PORT_1G_RGMII_FIBER:
50859ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
5092d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
51059ac0c16Sdavemq 			/*
51159ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
51259ac0c16Sdavemq 			 * swapped with ethernet port number. This is
5132e59129aSraghus 			 * designed for better signal integrity in
5142e59129aSraghus 			 * routing. This is also the case for the
5152e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
5162e59129aSraghus 			 * platform.
51759ac0c16Sdavemq 			 */
5182e59129aSraghus 			switch (nxgep->platform_type) {
5192e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
5202e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
5212e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
5222e59129aSraghus 				switch (portn) {
5232e59129aSraghus 				case 0:
5242d17280bSsbehera 					nxgep->xcvr_addr += 3;
5252e59129aSraghus 					break;
5262e59129aSraghus 				case 1:
5272d17280bSsbehera 					nxgep->xcvr_addr += 1;
5282e59129aSraghus 					break;
5292e59129aSraghus 				case 2:
5302d17280bSsbehera 					nxgep->xcvr_addr -= 1;
5312e59129aSraghus 					break;
5322e59129aSraghus 				case 3:
5332d17280bSsbehera 					nxgep->xcvr_addr -= 3;
5342e59129aSraghus 					break;
5352e59129aSraghus 				default:
5362e59129aSraghus 					return (NXGE_ERROR);
5372e59129aSraghus 				}
53859ac0c16Sdavemq 				break;
53959ac0c16Sdavemq 			default:
5402e59129aSraghus 				break;
54159ac0c16Sdavemq 			}
542d81011f0Ssbehera 
5432e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5442e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
5452e59129aSraghus 			    "Copper" : "RGMII Fiber"));
54659ac0c16Sdavemq 			break;
5472e59129aSraghus 		case PORT_10G_COPPER:
54859ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
54959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
55059ac0c16Sdavemq 			break;
5512e59129aSraghus 		case PORT_1G_FIBER:
5522e59129aSraghus 		case PORT_1G_SERDES:
55359ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
5542d17280bSsbehera 			nxgep->xcvr_addr = portn;
5552e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5562e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
5572e59129aSraghus 			    "Fiber" : "Serdes"));
55859ac0c16Sdavemq 			break;
5592e59129aSraghus 		case PORT_10G_FIBER:
5602e59129aSraghus 		case PORT_10G_SERDES:
56159ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
5622d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
5632d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
5642d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
5652d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
5662d17280bSsbehera 			    nxgep->xcvr_addr));
5672d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5682d17280bSsbehera 				nxgep->xcvr_addr =
5692d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5702d17280bSsbehera 			}
5712e59129aSraghus 			switch (nxgep->platform_type) {
5722e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
5732e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
57459ac0c16Sdavemq 				/*
57559ac0c16Sdavemq 				 * Switch off LED for corresponding copper
57659ac0c16Sdavemq 				 * port
57759ac0c16Sdavemq 				 */
57859ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
5792e59129aSraghus 				break;
5802e59129aSraghus 			default:
5812e59129aSraghus 				break;
58259ac0c16Sdavemq 			}
5832e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
5842e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
5852e59129aSraghus 			    "Fiber" : "Serdes"));
58659ac0c16Sdavemq 			break;
5872d17280bSsbehera 
5882d17280bSsbehera 		case PORT_HSP_MODE:
5892d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
5902d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
5912d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
5922d17280bSsbehera 			    "Swappable Xcvr (not present)"));
5932d17280bSsbehera 			break;
59459ac0c16Sdavemq 		default:
59559ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
59659ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
59759ac0c16Sdavemq 			return (NXGE_ERROR);
59859ac0c16Sdavemq 		}
59959ac0c16Sdavemq 	}
60059ac0c16Sdavemq 
6012d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
6022d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6032d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
6042d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
6052d17280bSsbehera 
6062d17280bSsbehera 			switch (chip_id) {
6072d17280bSsbehera 			case BCM8704_CHIP_ID:
6082d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6092d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6102d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
6112d17280bSsbehera 				    chip_id));
6122d17280bSsbehera 				break;
6132d17280bSsbehera 			case BCM8706_CHIP_ID:
6142d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6152d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6162d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
6172d17280bSsbehera 				    chip_id));
6182d17280bSsbehera 				break;
6192d17280bSsbehera 			default:
6202d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6212d17280bSsbehera 				    "nxge_setup_xcvr_table: "
6222d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
6232d17280bSsbehera 				    chip_id));
6242d17280bSsbehera 				break;
6252d17280bSsbehera 			}
6262d17280bSsbehera 		}
6272d17280bSsbehera 	}
6282d17280bSsbehera 
62959ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
6302d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
6312d17280bSsbehera 	nxgep->chip_id = chip_id;
6322e59129aSraghus 
6332e59129aSraghus 	/*
6342e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
6352e59129aSraghus 	 */
6362e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
6372e59129aSraghus 
6382d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
6392e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
6402e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
6412e59129aSraghus 	} else {
6422d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
6432e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
6442e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
6452e59129aSraghus 		} else {
6462e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
6472d17280bSsbehera 			    nxgep->xcvr_addr);
6482e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
6492e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
6502e59129aSraghus 			}
6512e59129aSraghus 		}
6522e59129aSraghus 	}
6532e59129aSraghus 
65459ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
65559ac0c16Sdavemq 
6562e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
6572d17280bSsbehera 	    "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type,
6582d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
6592e59129aSraghus 
66059ac0c16Sdavemq 	return (status);
66159ac0c16Sdavemq }
66259ac0c16Sdavemq 
66344961713Sgirish /* Initialize the entire MAC and physical layer */
66444961713Sgirish 
66544961713Sgirish nxge_status_t
66644961713Sgirish nxge_mac_init(p_nxge_t nxgep)
66744961713Sgirish {
66844961713Sgirish 	uint8_t			portn;
66944961713Sgirish 	nxge_status_t		status = NXGE_OK;
67044961713Sgirish 
67144961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
67244961713Sgirish 
67344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
67444961713Sgirish 
67544961713Sgirish 	nxgep->mac.portnum = portn;
67644961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
67744961713Sgirish 
67844961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
67944961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
68044961713Sgirish 
68144961713Sgirish 	/* Initialize XIF to configure a network mode */
68244961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
68344961713Sgirish 		goto fail;
68444961713Sgirish 	}
68544961713Sgirish 
68644961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
68744961713Sgirish 		goto fail;
68844961713Sgirish 	}
68944961713Sgirish 
69044961713Sgirish 	/* Initialize TX and RX MACs */
69144961713Sgirish 	/*
69244961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
69344961713Sgirish 	 */
69444961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
69544961713Sgirish 		goto fail;
69644961713Sgirish 
69744961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
69844961713Sgirish 		goto fail;
69944961713Sgirish 
70044961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
70144961713Sgirish 		goto fail;
70244961713Sgirish 
70344961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
70444961713Sgirish 		goto fail;
70544961713Sgirish 
70644961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
70744961713Sgirish 		goto fail;
70844961713Sgirish 
70944961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
71044961713Sgirish 		goto fail;
71144961713Sgirish 
712cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
713cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
714cb9d3ae6Smisaki 		goto fail;
715cb9d3ae6Smisaki 	}
716cb9d3ae6Smisaki 
71744961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
71844961713Sgirish 
719d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
720d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
721d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
722d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
723d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
724d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
725d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
726d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
727d81011f0Ssbehera 			goto fail;
728d81011f0Ssbehera 		}
729d81011f0Ssbehera 	}
730d81011f0Ssbehera 
7312e59129aSraghus 
73244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
73344961713Sgirish 
73444961713Sgirish 	return (NXGE_OK);
73544961713Sgirish fail:
73644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
73744961713Sgirish 			"nxge_mac_init: failed to initialize MAC port<%d>",
73844961713Sgirish 			portn));
73944961713Sgirish 	return (status);
74044961713Sgirish }
74144961713Sgirish 
74244961713Sgirish /* Initialize the Ethernet Link */
74344961713Sgirish 
74444961713Sgirish nxge_status_t
74544961713Sgirish nxge_link_init(p_nxge_t nxgep)
74644961713Sgirish {
74744961713Sgirish 	nxge_status_t		status = NXGE_OK;
7482e59129aSraghus 	nxge_port_mode_t	portmode;
74944961713Sgirish #ifdef	NXGE_DEBUG
75044961713Sgirish 	uint8_t			portn;
75144961713Sgirish 
75244961713Sgirish 	portn = nxgep->mac.portnum;
75344961713Sgirish 
75444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
75544961713Sgirish #endif
7562d17280bSsbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
7572d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
7582d17280bSsbehera 		    "Phy not present, cannot initialize link"));
7592d17280bSsbehera 		return (status);
7602d17280bSsbehera 	}
76144961713Sgirish 
7622e59129aSraghus 	portmode = nxgep->mac.portmode;
7632d17280bSsbehera 
7642e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
7652e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
76644961713Sgirish 		/* Workaround to get link up in both NIU ports */
7672e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
76844961713Sgirish 			goto fail;
7692e59129aSraghus 		}
77044961713Sgirish 	}
77144961713Sgirish 	NXGE_DELAY(200000);
77244961713Sgirish 	/* Initialize internal serdes */
77344961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
77444961713Sgirish 		goto fail;
77544961713Sgirish 	NXGE_DELAY(200000);
77644961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
77744961713Sgirish 		goto fail;
77844961713Sgirish 
77944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
78044961713Sgirish 
78144961713Sgirish 	return (NXGE_OK);
78244961713Sgirish 
78344961713Sgirish fail:
78444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
78544961713Sgirish 		"nxge_link_init: ",
78644961713Sgirish 		"failed to initialize Ethernet link on port<%d>",
78744961713Sgirish 		portn));
78844961713Sgirish 
78944961713Sgirish 	return (status);
79044961713Sgirish }
79144961713Sgirish 
79244961713Sgirish 
79344961713Sgirish /* Initialize the XIF sub-block within the MAC */
79444961713Sgirish 
79544961713Sgirish nxge_status_t
79644961713Sgirish nxge_xif_init(p_nxge_t nxgep)
79744961713Sgirish {
79844961713Sgirish 	uint32_t		xif_cfg = 0;
79944961713Sgirish 	npi_attr_t		ap;
80044961713Sgirish 	uint8_t			portn;
80144961713Sgirish 	nxge_port_t		portt;
80244961713Sgirish 	nxge_port_mode_t	portmode;
80344961713Sgirish 	p_nxge_stats_t		statsp;
80444961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
80544961713Sgirish 	npi_handle_t		handle;
80644961713Sgirish 
80744961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
80844961713Sgirish 
80944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
81044961713Sgirish 
81144961713Sgirish 	handle = nxgep->npi_handle;
81244961713Sgirish 	portmode = nxgep->mac.portmode;
81344961713Sgirish 	portt = nxgep->mac.porttype;
81444961713Sgirish 	statsp = nxgep->statsp;
81544961713Sgirish 
816d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
817d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
818d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
819d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
820d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
821d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
822d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
823d81011f0Ssbehera 	}
824d81011f0Ssbehera 
82544961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
82644961713Sgirish 
82744961713Sgirish 		/* Setup XIF Configuration for XMAC */
82844961713Sgirish 
82944961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
8302e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
8312e59129aSraghus 		    (portmode == PORT_10G_SERDES))
83244961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
83344961713Sgirish 
83444961713Sgirish 		if (portmode == PORT_1G_COPPER) {
83544961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
83644961713Sgirish 		}
83744961713Sgirish 
83844961713Sgirish 		/* Set MAC Internal Loopback if necessary */
83944961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
84044961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
84144961713Sgirish 
84244961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
84344961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
84444961713Sgirish 
84544961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
84644961713Sgirish 
8472e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
8482e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
84944961713Sgirish 			if (statsp->mac_stats.link_up) {
85044961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
85144961713Sgirish 			} else {
85244961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
85344961713Sgirish 			}
85444961713Sgirish 		}
85544961713Sgirish 
85644961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
85744961713Sgirish 		if (rs != NPI_SUCCESS)
85844961713Sgirish 			goto fail;
85944961713Sgirish 
86044961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
86144961713Sgirish 
86244961713Sgirish 		/* Set Port Mode */
86344961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
8642e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
8652e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
86644961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
86744961713Sgirish 						MAC_XGMII_MODE, rs);
86844961713Sgirish 			if (rs != NPI_SUCCESS)
86944961713Sgirish 				goto fail;
87044961713Sgirish 			if (statsp->mac_stats.link_up) {
87144961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
87244961713Sgirish 					goto fail;
87344961713Sgirish 			} else {
87444961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
87544961713Sgirish 					goto fail;
87644961713Sgirish 			}
87744961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
8782e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
879d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
880d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
881d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
882d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
883d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
88444961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
88544961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
88644961713Sgirish 							MAC_GMII_MODE, rs);
88744961713Sgirish 			} else {
88844961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
88944961713Sgirish 							MAC_MII_MODE, rs);
89044961713Sgirish 			}
89144961713Sgirish 			if (rs != NPI_SUCCESS)
89244961713Sgirish 				goto fail;
89344961713Sgirish 		} else {
89444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
89544961713Sgirish 					"nxge_xif_init: Unknown port mode (%d)"
89644961713Sgirish 					" for port<%d>", portmode, portn));
89744961713Sgirish 			goto fail;
89844961713Sgirish 		}
89944961713Sgirish 
900d81011f0Ssbehera 		/* Enable ATCA mode */
901d81011f0Ssbehera 
90244961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
90344961713Sgirish 
90444961713Sgirish 		/* Setup XIF Configuration for BMAC */
90544961713Sgirish 
906d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
907d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
90844961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
90944961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
91044961713Sgirish 		}
91144961713Sgirish 
91244961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
91344961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
91444961713Sgirish 
91544961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
91644961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
91744961713Sgirish 
91844961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
91944961713Sgirish 
92044961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
92144961713Sgirish 		if (rs != NPI_SUCCESS)
92244961713Sgirish 			goto fail;
92344961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
92444961713Sgirish 	}
92544961713Sgirish 
92644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
92744961713Sgirish 	return (NXGE_OK);
92844961713Sgirish fail:
92944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
93044961713Sgirish 			"nxge_xif_init: Failed to initialize XIF port<%d>",
93144961713Sgirish 			portn));
93244961713Sgirish 	return (NXGE_ERROR | rs);
93344961713Sgirish }
93444961713Sgirish 
93544961713Sgirish /* Initialize the PCS sub-block in the MAC */
93644961713Sgirish 
93744961713Sgirish nxge_status_t
93844961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
93944961713Sgirish {
94044961713Sgirish 	pcs_cfg_t		pcs_cfg;
94144961713Sgirish 	uint32_t		val;
94244961713Sgirish 	uint8_t			portn;
94344961713Sgirish 	nxge_port_mode_t	portmode;
94444961713Sgirish 	npi_handle_t		handle;
94544961713Sgirish 	p_nxge_stats_t		statsp;
94644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
94744961713Sgirish 
94844961713Sgirish 	handle = nxgep->npi_handle;
94944961713Sgirish 	portmode = nxgep->mac.portmode;
95044961713Sgirish 	portn = nxgep->mac.portnum;
95144961713Sgirish 	statsp = nxgep->statsp;
95244961713Sgirish 
95344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
95444961713Sgirish 
9552e59129aSraghus 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
9562e59129aSraghus 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
9572e59129aSraghus 			goto fail;
9582e59129aSraghus 		}
9592e59129aSraghus 
96044961713Sgirish 		/* Initialize port's PCS */
96144961713Sgirish 		pcs_cfg.value = 0;
96244961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
96344961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
96444961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
96544961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
96644961713Sgirish 
9672e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9682e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
9692e59129aSraghus 		    portn, pcs_cfg.value));
97044961713Sgirish 	} else if ((portmode == PORT_10G_FIBER) ||
9712e59129aSraghus 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
97244961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
97344961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
97444961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
97544961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
97644961713Sgirish 
97744961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
97844961713Sgirish 			goto fail;
97944961713Sgirish 
98044961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
98144961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
98244961713Sgirish 						XPCS_REG_CONTROL1, &val))
98344961713Sgirish 						!= NPI_SUCCESS)
98444961713Sgirish 			goto fail;
98544961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
98644961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
98744961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
98844961713Sgirish 		else
98944961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
99044961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
99144961713Sgirish 						XPCS_REG_CONTROL1, val))
99244961713Sgirish 						!= NPI_SUCCESS)
99344961713Sgirish 			goto fail;
99444961713Sgirish 
99544961713Sgirish 		/* Clear descw errors */
99644961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
99744961713Sgirish 						XPCS_REG_DESCWERR_COUNTER, 0))
99844961713Sgirish 						!= NPI_SUCCESS)
99944961713Sgirish 			goto fail;
100044961713Sgirish 		/* Clear symbol errors */
100144961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
100244961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
100344961713Sgirish 					!= NPI_SUCCESS)
100444961713Sgirish 			goto fail;
100544961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
100644961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
100744961713Sgirish 					!= NPI_SUCCESS)
100844961713Sgirish 			goto fail;
100944961713Sgirish 
1010d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1011d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1012d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1013d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
101444961713Sgirish 		if (portn < 4) {
101544961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
101644961713Sgirish 					PCS_DATAPATH_MODE_MII);
101744961713Sgirish 		}
101844961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
101944961713Sgirish 			goto fail;
102044961713Sgirish 
102144961713Sgirish 	} else {
102244961713Sgirish 		goto fail;
102344961713Sgirish 	}
102444961713Sgirish pass:
102544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
102644961713Sgirish 	return (NXGE_OK);
102744961713Sgirish fail:
102844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
102944961713Sgirish 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
103044961713Sgirish 			portn));
103144961713Sgirish 	return (NXGE_ERROR | rs);
103244961713Sgirish }
103344961713Sgirish 
1034cb9d3ae6Smisaki /*
1035cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1036cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1037cb9d3ae6Smisaki  */
1038cb9d3ae6Smisaki nxge_status_t
1039cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1040cb9d3ae6Smisaki {
1041cb9d3ae6Smisaki 	uint8_t			portn;
1042cb9d3ae6Smisaki 	nxge_port_t		portt;
1043cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1044cb9d3ae6Smisaki 	npi_handle_t		handle;
1045cb9d3ae6Smisaki 	uint32_t		val;
1046cb9d3ae6Smisaki 
1047cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1048cb9d3ae6Smisaki 
1049cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1050cb9d3ae6Smisaki 	    portn));
1051cb9d3ae6Smisaki 
1052cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1053cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1054cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1055cb9d3ae6Smisaki 
1056cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
1057cb9d3ae6Smisaki 		/* Readin the current XMAC Config Register for XMAC */
1058cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1059cb9d3ae6Smisaki 
1060cb9d3ae6Smisaki 		/*
1061cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1062cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1063cb9d3ae6Smisaki 		 */
1064cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1065cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1066cb9d3ae6Smisaki 				/*
1067cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1068cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1069cb9d3ae6Smisaki 				 */
1070cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1071cb9d3ae6Smisaki 			} else {
1072cb9d3ae6Smisaki 				/*
1073cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1074cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1075cb9d3ae6Smisaki 				 * not supported.
1076cb9d3ae6Smisaki 				 */
1077cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1078cb9d3ae6Smisaki 			}
1079cb9d3ae6Smisaki 		} else {
10801bd6825cSml 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10811bd6825cSml 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
10821bd6825cSml 			    portn));
1083cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
10841bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10851bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
10861bd6825cSml 				    "enable pause", portn));
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 				 */
10981bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10991bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
11001bd6825cSml 				    "disable pause", portn));
1101cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1102cb9d3ae6Smisaki 			}
1103cb9d3ae6Smisaki 		}
1104cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1105cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
1106cb9d3ae6Smisaki 		/* Readin the current MAC CTRL Config Register for BMAC */
1107cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1108cb9d3ae6Smisaki 
1109cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1110cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1111cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1112cb9d3ae6Smisaki 				/*
1113cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1114cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1115cb9d3ae6Smisaki 				 * is not supported
1116cb9d3ae6Smisaki 				 */
1117cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1118cb9d3ae6Smisaki 			} else {
1119cb9d3ae6Smisaki 				/*
1120cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1121cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1122cb9d3ae6Smisaki 				 * send pause.
1123cb9d3ae6Smisaki 				 */
1124cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1125cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1126cb9d3ae6Smisaki 			}
1127cb9d3ae6Smisaki 		} else {
1128cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1129cb9d3ae6Smisaki 				/*
1130cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1131cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1132cb9d3ae6Smisaki 				 * not supported.
1133cb9d3ae6Smisaki 				 */
1134cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1135cb9d3ae6Smisaki 			} else {
1136cb9d3ae6Smisaki 				/*
1137cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1138cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1139cb9d3ae6Smisaki 				 * either direction.
1140cb9d3ae6Smisaki 				 */
1141cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1142cb9d3ae6Smisaki 					~MAC_CTRL_CFG_RECV_PAUSE_EN);
1143cb9d3ae6Smisaki 			}
1144cb9d3ae6Smisaki 		}
1145cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1146cb9d3ae6Smisaki 	}
1147cb9d3ae6Smisaki 
1148cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1149cb9d3ae6Smisaki 	    portn));
1150cb9d3ae6Smisaki 
1151cb9d3ae6Smisaki 	return (NXGE_OK);
1152cb9d3ae6Smisaki }
1153cb9d3ae6Smisaki 
115444961713Sgirish /* Initialize the Internal Serdes */
115544961713Sgirish 
115644961713Sgirish nxge_status_t
115744961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
115844961713Sgirish {
115944961713Sgirish 	p_nxge_stats_t		statsp;
116044961713Sgirish #ifdef	NXGE_DEBUG
116144961713Sgirish 	uint8_t			portn;
116244961713Sgirish #endif
116344961713Sgirish 	nxge_status_t		status = NXGE_OK;
116444961713Sgirish 
116544961713Sgirish #ifdef	NXGE_DEBUG
116644961713Sgirish 	portn = nxgep->mac.portnum;
116744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
116859ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
116944961713Sgirish #endif
117044961713Sgirish 
117159ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
117259ac0c16Sdavemq 		statsp = nxgep->statsp;
117359ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
117459ac0c16Sdavemq 		if (status != NXGE_OK)
117544961713Sgirish 			goto fail;
117659ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
117744961713Sgirish 	}
117844961713Sgirish 
117944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
118059ac0c16Sdavemq 	    portn));
118144961713Sgirish 
118244961713Sgirish 	return (NXGE_OK);
118344961713Sgirish 
118444961713Sgirish fail:
118544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
118659ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
118759ac0c16Sdavemq 	    portn));
118844961713Sgirish 
118944961713Sgirish 	return (status);
119044961713Sgirish }
119144961713Sgirish 
119244961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
119344961713Sgirish 
119459ac0c16Sdavemq static nxge_status_t
119544961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
119644961713Sgirish {
119744961713Sgirish 	uint8_t portn;
119844961713Sgirish 	int chan;
119944961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
12002e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
120144961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
120244961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
120344961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
120444961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
12052e59129aSraghus #ifdef NXGE_DEBUG
12062e59129aSraghus 	esr_ti_testcfg_t cfg;
12072e59129aSraghus #endif
120844961713Sgirish 	esr_ti_testcfg_t test_cfg;
120944961713Sgirish 	nxge_status_t status = NXGE_OK;
121044961713Sgirish 
121144961713Sgirish 	portn = nxgep->mac.portnum;
121244961713Sgirish 
121344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
121444961713Sgirish 			portn));
121544961713Sgirish 
121644961713Sgirish 	tx_cfg_l.value = 0;
121744961713Sgirish 	tx_cfg_h.value = 0;
121844961713Sgirish 	rx_cfg_l.value = 0;
121944961713Sgirish 	rx_cfg_h.value = 0;
122044961713Sgirish 	pll_cfg_l.value = 0;
12212e59129aSraghus 	pll_sts_l.value = 0;
122244961713Sgirish 	test_cfg.value = 0;
122344961713Sgirish 
12242e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
12252e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
122644961713Sgirish 		/* 0x0E01 */
122744961713Sgirish 		tx_cfg_l.bits.entx = 1;
122844961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
122944961713Sgirish 
123044961713Sgirish 		/* 0x9101 */
123144961713Sgirish 		rx_cfg_l.bits.enrx = 1;
123244961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
123344961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
123444961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
123544961713Sgirish 
123644961713Sgirish 		/* 0x0008 */
123744961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
123844961713Sgirish 
123944961713Sgirish 		/* Set loopback mode if necessary */
124044961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
124144961713Sgirish 			tx_cfg_l.bits.entest = 1;
124244961713Sgirish 			rx_cfg_l.bits.entest = 1;
124344961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
124444961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
124544961713Sgirish 				ESR_N2_DEV_ADDR,
124644961713Sgirish 				ESR_N2_TEST_CFG_REG, test_cfg.value))
124744961713Sgirish 				!= NXGE_OK)
124844961713Sgirish 			goto fail;
124944961713Sgirish 		}
125044961713Sgirish 
125144961713Sgirish 		/* Use default PLL value */
125244961713Sgirish 
12532e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
12542e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
125544961713Sgirish 
125644961713Sgirish 		/* 0x0E21 */
125744961713Sgirish 		tx_cfg_l.bits.entx = 1;
125844961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
125944961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
126044961713Sgirish 
126144961713Sgirish 		/* 0x9121 */
126244961713Sgirish 		rx_cfg_l.bits.enrx = 1;
126344961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
126444961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
126544961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
126644961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
126744961713Sgirish 
12682e59129aSraghus 		if (portn == 0) {
12692e59129aSraghus 			/* 0x8 */
12702e59129aSraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12712e59129aSraghus 		}
127244961713Sgirish 
127344961713Sgirish 		/* MPY = 0x100 */
127444961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
127544961713Sgirish 
127644961713Sgirish 		/* Set PLL */
127744961713Sgirish 		pll_cfg_l.bits.enpll = 1;
12782e59129aSraghus 		pll_sts_l.bits.enpll = 1;
127944961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
128044961713Sgirish 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
128144961713Sgirish 				!= NXGE_OK)
128244961713Sgirish 			goto fail;
12832e59129aSraghus 
12842e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
12852e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
12862e59129aSraghus 			goto fail;
12872e59129aSraghus 
12882e59129aSraghus #ifdef  NXGE_DEBUG
12892e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12902e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
12912e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12922e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
12932e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
12942e59129aSraghus 
12952e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12962e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
12972e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12982e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
12992e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
13002e59129aSraghus #endif
13012e59129aSraghus 
13022e59129aSraghus 		/* Set loopback mode if necessary */
13032e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
13042e59129aSraghus 			tx_cfg_l.bits.entest = 1;
13052e59129aSraghus 			rx_cfg_l.bits.entest = 1;
13062e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
13072e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13082e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
13092e59129aSraghus 			    portn, test_cfg.value));
13102e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
13112e59129aSraghus 			    ESR_N2_DEV_ADDR,
13122e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
13132e59129aSraghus 				goto fail;
13142e59129aSraghus 			}
13152e59129aSraghus 		}
131644961713Sgirish 	} else {
131744961713Sgirish 		goto fail;
131844961713Sgirish 	}
131944961713Sgirish 
132044961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
132144961713Sgirish 
132244961713Sgirish 	NXGE_DELAY(20);
132344961713Sgirish 
132444961713Sgirish 	/* init TX channels */
132544961713Sgirish 	for (chan = 0; chan < 4; chan++) {
132644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
132744961713Sgirish 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
132844961713Sgirish 				!= NXGE_OK)
132944961713Sgirish 			goto fail;
133044961713Sgirish 
133144961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
133244961713Sgirish 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
133344961713Sgirish 				!= NXGE_OK)
133444961713Sgirish 			goto fail;
13352e59129aSraghus 
13362e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13372e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
13382e59129aSraghus 		    portn, chan, tx_cfg_l.value));
13392e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13402e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
13412e59129aSraghus 		    portn, chan, tx_cfg_h.value));
134244961713Sgirish 	}
134344961713Sgirish 
134444961713Sgirish 	/* init RX channels */
134544961713Sgirish 	for (chan = 0; chan < 4; chan++) {
134644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
134744961713Sgirish 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
134844961713Sgirish 				!= NXGE_OK)
134944961713Sgirish 			goto fail;
135044961713Sgirish 
135144961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
135244961713Sgirish 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
135344961713Sgirish 				!= NXGE_OK)
135444961713Sgirish 			goto fail;
13552e59129aSraghus 
13562e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13572e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
13582e59129aSraghus 		    portn, chan, rx_cfg_l.value));
13592e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13602e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
13612e59129aSraghus 		    portn, chan, rx_cfg_h.value));
136244961713Sgirish 	}
136344961713Sgirish 
136444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
136544961713Sgirish 			portn));
136644961713Sgirish 
136744961713Sgirish 	return (NXGE_OK);
136844961713Sgirish fail:
13692d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13702d17280bSsbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
13712d17280bSsbehera 	    portn));
137244961713Sgirish 
137344961713Sgirish 	return (status);
137444961713Sgirish }
137544961713Sgirish 
137659ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
137744961713Sgirish 
137859ac0c16Sdavemq static nxge_status_t
137959ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
138044961713Sgirish {
138144961713Sgirish 	npi_handle_t		handle;
138244961713Sgirish 	uint8_t			portn;
1383321febdeSsbehera 	int			chan, i;
138444961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
138544961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
138644961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
138744961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
138844961713Sgirish 	uint64_t		val;
138944961713Sgirish 	uint16_t		val16l;
139044961713Sgirish 	uint16_t		val16h;
139144961713Sgirish 	nxge_status_t		status = NXGE_OK;
139244961713Sgirish 
139344961713Sgirish 	portn = nxgep->mac.portnum;
139444961713Sgirish 
139544961713Sgirish 	if ((portn != 0) && (portn != 1))
139644961713Sgirish 		return (NXGE_OK);
139744961713Sgirish 
139859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
139959ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
140044961713Sgirish 
140144961713Sgirish 	handle = nxgep->npi_handle;
140259ac0c16Sdavemq 	switch (portn) {
140359ac0c16Sdavemq 	case 0:
14044202ea4bSsbehera 		/* Reset Serdes */
14054202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
14064202ea4bSsbehera 		NXGE_DELAY(20);
14074202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14084202ea4bSsbehera 		NXGE_DELAY(2000);
14094202ea4bSsbehera 
14104202ea4bSsbehera 		/* Configure Serdes to 10G mode */
14114202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
14124202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
14134202ea4bSsbehera 
141459ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
141559ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
141659ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
141759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
141859ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
141959ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
142059ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
142159ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
142259ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
142359ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
142459ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
142559ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
142659ac0c16Sdavemq 
142759ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
142859ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
142959ac0c16Sdavemq 			ESR_REG_WR(handle,
143059ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
143159ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
143259ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
143359ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
143459ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
143559ac0c16Sdavemq 		} else {
143659ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
143744961713Sgirish 		}
143859ac0c16Sdavemq 		break;
143959ac0c16Sdavemq 	case 1:
14404202ea4bSsbehera 		/* Reset Serdes */
14414202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
14424202ea4bSsbehera 		NXGE_DELAY(20);
14434202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14444202ea4bSsbehera 		NXGE_DELAY(2000);
14454202ea4bSsbehera 
14464202ea4bSsbehera 		/* Configure Serdes to 10G mode */
14474202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
14484202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
14494202ea4bSsbehera 
145059ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
145159ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
145259ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
145359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
145459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
145559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
145659ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
145759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
145859ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
145959ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
146059ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
146159ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
146259ac0c16Sdavemq 
146359ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
146459ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
146559ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
146659ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
146759ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
146859ac0c16Sdavemq 		} else {
146959ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
147044961713Sgirish 		}
147159ac0c16Sdavemq 		break;
147259ac0c16Sdavemq 	default:
147359ac0c16Sdavemq 		/* Nothing to do here */
147459ac0c16Sdavemq 		goto done;
147559ac0c16Sdavemq 	}
147644961713Sgirish 
147759ac0c16Sdavemq 	/* init TX RX channels */
147859ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
147959ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148059ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
148159ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
148244961713Sgirish 			goto fail;
148359ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148459ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
148559ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
148644961713Sgirish 			goto fail;
148759ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
148859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
148959ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
149059ac0c16Sdavemq 			goto fail;
149159ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
149259ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
149359ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
149459ac0c16Sdavemq 			goto fail;
149559ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
149659ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
149759ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
149859ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
149959ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
150059ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
150159ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
150244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
150359ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
150459ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
150544961713Sgirish 			goto fail;
150644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
150759ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
150859ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
150944961713Sgirish 			goto fail;
151059ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
151159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
151259ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
151344961713Sgirish 			goto fail;
151459ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
151559ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
151659ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
151744961713Sgirish 			goto fail;
151844961713Sgirish 		}
151944961713Sgirish 
152059ac0c16Sdavemq 	/* Apply Tx core reset */
152159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
152259ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
152359ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
152459ac0c16Sdavemq 		goto fail;
152559ac0c16Sdavemq 
152659ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
152759ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
152859ac0c16Sdavemq 	    NXGE_OK)
152959ac0c16Sdavemq 		goto fail;
153059ac0c16Sdavemq 
153159ac0c16Sdavemq 	NXGE_DELAY(200);
153259ac0c16Sdavemq 
153359ac0c16Sdavemq 	/* Apply Rx core reset */
153459ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
153559ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
153659ac0c16Sdavemq 	    NXGE_OK)
153759ac0c16Sdavemq 		goto fail;
153859ac0c16Sdavemq 
153959ac0c16Sdavemq 	NXGE_DELAY(200);
154059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
154159ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
154259ac0c16Sdavemq 		goto fail;
154359ac0c16Sdavemq 
154459ac0c16Sdavemq 	NXGE_DELAY(200);
154559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
154659ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
154759ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
154859ac0c16Sdavemq 		goto fail;
154959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
155059ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
155159ac0c16Sdavemq 		goto fail;
155259ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
155359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1554d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1555d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
1556d81011f0Ssbehera 		    portn, val16l, val16h));
155759ac0c16Sdavemq 	}
155859ac0c16Sdavemq 
155959ac0c16Sdavemq 	if (portn == 0) {
1560321febdeSsbehera 		/* Wait for serdes to be ready */
1561321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1562321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1563321febdeSsbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
1564321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1565321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P0 |
1566321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH3 |
1567321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH2 |
1568321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH1 |
1569321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
1570321febdeSsbehera 
1571321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1572321febdeSsbehera 			else
1573321febdeSsbehera 				break;
1574321febdeSsbehera 		}
1575321febdeSsbehera 
1576321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1577321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1578321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1579321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
1580321febdeSsbehera 				goto fail;
158159ac0c16Sdavemq 		}
158259ac0c16Sdavemq 	} else if (portn == 1) {
1583321febdeSsbehera 		/* Wait for serdes to be ready */
1584321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1585321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1586321febdeSsbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
1587321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1588321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P1 |
1589321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH3 |
1590321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH2 |
1591321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH1 |
1592321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
1593321febdeSsbehera 
1594321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1595321febdeSsbehera 			else
1596321febdeSsbehera 				break;
1597321febdeSsbehera 		}
1598321febdeSsbehera 
1599321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1600321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1601321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1602321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
1603321febdeSsbehera 				goto fail;
160444961713Sgirish 		}
160544961713Sgirish 	}
160644961713Sgirish 
160744961713Sgirish done:
160859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
160959ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
161059ac0c16Sdavemq 
161144961713Sgirish 	return (NXGE_OK);
161244961713Sgirish fail:
16132d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
161459ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
161559ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
161644961713Sgirish 
161744961713Sgirish 	return (status);
161844961713Sgirish }
161944961713Sgirish 
162059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
162144961713Sgirish 
162259ac0c16Sdavemq static nxge_status_t
162359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
162444961713Sgirish {
162559ac0c16Sdavemq 	npi_handle_t		handle;
162659ac0c16Sdavemq 	uint8_t			portn;
1627d81011f0Ssbehera 	int			chan;
1628d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1629d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1630d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1631d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
163259ac0c16Sdavemq 	uint64_t		val;
1633d81011f0Ssbehera 	uint16_t		val16l;
1634d81011f0Ssbehera 	uint16_t		val16h;
1635d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
163644961713Sgirish 
163744961713Sgirish 	portn = nxgep->mac.portnum;
163844961713Sgirish 
163959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
164059ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
164144961713Sgirish 
164259ac0c16Sdavemq 	handle = nxgep->npi_handle;
164344961713Sgirish 
164459ac0c16Sdavemq 	switch (portn) {
164559ac0c16Sdavemq 	case 0:
1646d81011f0Ssbehera 		/* Assert the reset register */
1647d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1648d81011f0Ssbehera 		val |= ESR_RESET_0;
1649d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1650d81011f0Ssbehera 
1651d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
1652d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1653d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1654d81011f0Ssbehera 
1655d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1656d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
1657d81011f0Ssbehera 
1658d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
1659d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1660d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
1661d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
1662d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1663d81011f0Ssbehera 		} else {
1664d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1665d81011f0Ssbehera 		}
1666d81011f0Ssbehera 
1667d81011f0Ssbehera 		/* Deassert the reset register */
1668d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1669d81011f0Ssbehera 		val &= ~ESR_RESET_0;
1670d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
167159ac0c16Sdavemq 		break;
1672d81011f0Ssbehera 
167359ac0c16Sdavemq 	case 1:
1674d81011f0Ssbehera 		/* Assert the reset register */
1675d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1676d81011f0Ssbehera 		val |= ESR_RESET_1;
1677d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1678d81011f0Ssbehera 
1679d81011f0Ssbehera 		/* Set PLL register to 0x79 */
1680d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1681d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1682d81011f0Ssbehera 
1683d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1684d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
1685d81011f0Ssbehera 
1686d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
1687d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1688d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
1689d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
1690d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1691d81011f0Ssbehera 		} else {
1692d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
1693d81011f0Ssbehera 		}
1694d81011f0Ssbehera 
1695d81011f0Ssbehera 		/* Deassert the reset register */
1696d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1697d81011f0Ssbehera 		val &= ~ESR_RESET_1;
1698d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
169959ac0c16Sdavemq 		break;
1700d81011f0Ssbehera 
170159ac0c16Sdavemq 	default:
1702d81011f0Ssbehera 		/* Nothing to do here */
1703d81011f0Ssbehera 		goto done;
1704d81011f0Ssbehera 	}
1705d81011f0Ssbehera 
1706d81011f0Ssbehera 	/* init TX RX channels */
1707d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
1708d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1709d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1710d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
1711d81011f0Ssbehera 			goto fail;
1712d81011f0Ssbehera 		}
1713d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1714d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1715d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
1716d81011f0Ssbehera 			goto fail;
1717d81011f0Ssbehera 		}
1718d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1719d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1720d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
1721d81011f0Ssbehera 			goto fail;
1722d81011f0Ssbehera 		}
1723d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
1724d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1725d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
1726d81011f0Ssbehera 			goto fail;
1727d81011f0Ssbehera 		}
1728d81011f0Ssbehera 
1729d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
1730d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
1731d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
1732d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
1733d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
1734d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
1735d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
1736d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1737d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1738d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
1739d81011f0Ssbehera 			goto fail;
1740d81011f0Ssbehera 		}
1741d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1742d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1743d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
1744d81011f0Ssbehera 			goto fail;
1745d81011f0Ssbehera 		}
1746d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1747d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1748d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
1749d81011f0Ssbehera 			goto fail;
1750d81011f0Ssbehera 		}
1751d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
1752d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1753d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
1754d81011f0Ssbehera 			goto fail;
1755d81011f0Ssbehera 		}
1756d81011f0Ssbehera 	}
1757d81011f0Ssbehera 
1758d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1759d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
1760d81011f0Ssbehera 		goto fail;
1761d81011f0Ssbehera 	}
1762d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1763d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
1764d81011f0Ssbehera 		goto fail;
1765d81011f0Ssbehera 	}
1766d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1767d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
1768d81011f0Ssbehera 		goto fail;
1769d81011f0Ssbehera 	}
1770d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1771d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
177259ac0c16Sdavemq 		goto fail;
177344961713Sgirish 	}
177444961713Sgirish 
1775d81011f0Ssbehera 	/* Apply Tx core reset */
1776d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1777d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
1778d81011f0Ssbehera 		goto fail;
1779d81011f0Ssbehera 	}
1780d81011f0Ssbehera 
1781d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1782d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
1783d81011f0Ssbehera 	    NXGE_OK) {
1784d81011f0Ssbehera 		goto fail;
1785d81011f0Ssbehera 	}
1786d81011f0Ssbehera 
1787d81011f0Ssbehera 	NXGE_DELAY(200);
1788d81011f0Ssbehera 
1789d81011f0Ssbehera 	/* Apply Rx core reset */
1790d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1791d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
1792d81011f0Ssbehera 	    NXGE_OK) {
1793d81011f0Ssbehera 		goto fail;
1794d81011f0Ssbehera 	}
1795d81011f0Ssbehera 
1796d81011f0Ssbehera 	NXGE_DELAY(200);
1797d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1798d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
1799d81011f0Ssbehera 		goto fail;
1800d81011f0Ssbehera 	}
1801d81011f0Ssbehera 
1802d81011f0Ssbehera 	NXGE_DELAY(200);
1803d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1804d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
1805d81011f0Ssbehera 		goto fail;
1806d81011f0Ssbehera 	}
1807d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1808d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
1809d81011f0Ssbehera 		goto fail;
1810d81011f0Ssbehera 	}
1811d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
1812d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1813d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1814d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
1815d81011f0Ssbehera 		status = NXGE_ERROR;
1816d81011f0Ssbehera 		goto fail;
1817d81011f0Ssbehera 	}
1818d81011f0Ssbehera 
1819d81011f0Ssbehera 	NXGE_DELAY(200);
1820d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1821d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1822d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
1823d81011f0Ssbehera 	    "val 0x%x", portn, val));
1824d81011f0Ssbehera 	if (portn == 0) {
1825d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
1826d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
1827d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1828d81011f0Ssbehera 			    "nxge_neptune_serdes_init: "
1829d81011f0Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
1830d81011f0Ssbehera 			    portn, (val & ESR_SIG_P0_BITS_MASK)));
1831d81011f0Ssbehera 			status = NXGE_ERROR;
1832d81011f0Ssbehera 			goto fail;
1833d81011f0Ssbehera 		}
1834d81011f0Ssbehera 	} else if (portn == 1) {
1835d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
1836d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
1837d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1838d81011f0Ssbehera 			    "nxge_neptune_serdes_init: "
1839d81011f0Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
1840d81011f0Ssbehera 			    portn, (val & ESR_SIG_P1_BITS_MASK)));
1841d81011f0Ssbehera 			status = NXGE_ERROR;
1842d81011f0Ssbehera 			goto fail;
1843d81011f0Ssbehera 		}
1844d81011f0Ssbehera 	}
1845d81011f0Ssbehera done:
184659ac0c16Sdavemq 
184759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
184859ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
184944961713Sgirish 	return (NXGE_OK);
185059ac0c16Sdavemq fail:
1851d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
185259ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
185359ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
185459ac0c16Sdavemq 	    portn));
185559ac0c16Sdavemq 
1856d81011f0Ssbehera 	return (status);
185744961713Sgirish }
185844961713Sgirish 
18592d17280bSsbehera /* Initialize the BCM 8704 xcvr */
186044961713Sgirish 
186159ac0c16Sdavemq static nxge_status_t
18622d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
186344961713Sgirish {
186444961713Sgirish 	uint16_t		val;
186544961713Sgirish #ifdef	NXGE_DEBUG
186614ea4bb7Ssd 	uint8_t			portn;
186744961713Sgirish 	uint16_t		val1;
186844961713Sgirish #endif
186944961713Sgirish 	uint8_t			phy_port_addr;
187044961713Sgirish 	pmd_tx_control_t	tx_ctl;
187144961713Sgirish 	control_t		ctl;
187244961713Sgirish 	phyxs_control_t		phyxs_ctl;
187344961713Sgirish 	pcs_control_t		pcs_ctl;
187444961713Sgirish 	uint32_t		delay = 0;
187544961713Sgirish 	optics_dcntr_t		op_ctr;
187644961713Sgirish 	nxge_status_t		status = NXGE_OK;
187714ea4bb7Ssd #ifdef	NXGE_DEBUG
187844961713Sgirish 	portn = nxgep->mac.portnum;
187914ea4bb7Ssd #endif
18802d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
188159ac0c16Sdavemq 	    portn));
188244961713Sgirish 
188359ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
188459ac0c16Sdavemq 
188559ac0c16Sdavemq 	/* Reset the transceiver */
188659ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
188759ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
188859ac0c16Sdavemq 		goto fail;
188959ac0c16Sdavemq 
189059ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
189159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
189259ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
189359ac0c16Sdavemq 		goto fail;
189459ac0c16Sdavemq 
189559ac0c16Sdavemq 	do {
189659ac0c16Sdavemq 		drv_usecwait(500);
189759ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
189859ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
189959ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
190059ac0c16Sdavemq 			goto fail;
190159ac0c16Sdavemq 		delay++;
190259ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
190359ac0c16Sdavemq 	if (delay == 100) {
190459ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
190559ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
190659ac0c16Sdavemq 		status = NXGE_ERROR;
190759ac0c16Sdavemq 		goto fail;
190859ac0c16Sdavemq 	}
190944961713Sgirish 
191059ac0c16Sdavemq 	/* Set to 0x7FBF */
191159ac0c16Sdavemq 	ctl.value = 0;
191259ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
191359ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
191459ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
191559ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
191659ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
191759ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
191859ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
191959ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
192059ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
192159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
192259ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
192359ac0c16Sdavemq 	    != NXGE_OK)
192459ac0c16Sdavemq 		goto fail;
192559ac0c16Sdavemq 
192659ac0c16Sdavemq 	/* Set to 0x164 */
192759ac0c16Sdavemq 	tx_ctl.value = 0;
192859ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
192959ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
193059ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
193159ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
193259ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
193359ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
193459ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
193559ac0c16Sdavemq 		goto fail;
193644961713Sgirish 	/*
193759ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
193859ac0c16Sdavemq 	 * back these registers twice after written.
193944961713Sgirish 	 */
194059ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
194159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
194259ac0c16Sdavemq 	    != NXGE_OK)
194359ac0c16Sdavemq 		goto fail;
194444961713Sgirish 
194559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
194659ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
194759ac0c16Sdavemq 	    != NXGE_OK)
194859ac0c16Sdavemq 		goto fail;
194944961713Sgirish 
195059ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
195159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
195259ac0c16Sdavemq 	    != NXGE_OK)
195359ac0c16Sdavemq 		goto fail;
195444961713Sgirish 
195559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
195659ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
195759ac0c16Sdavemq 	    != NXGE_OK)
195859ac0c16Sdavemq 		goto fail;
195944961713Sgirish 
196059ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
196159ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
196259ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
196359ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
196459ac0c16Sdavemq 		goto fail;
1965cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
1966cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
1967cb9d3ae6Smisaki 	} else {
1968cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x3;
1969cb9d3ae6Smisaki 	}
197059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
197159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
197259ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
197359ac0c16Sdavemq 		goto fail;
197444961713Sgirish 
197559ac0c16Sdavemq 	NXGE_DELAY(1000000);
197644961713Sgirish 
197759ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
197859ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
197959ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
198059ac0c16Sdavemq 	    != NXGE_OK)
198159ac0c16Sdavemq 		goto fail;
198259ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
198359ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
198459ac0c16Sdavemq 	else
198559ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
198659ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
198759ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
198859ac0c16Sdavemq 	    != NXGE_OK)
198959ac0c16Sdavemq 		goto fail;
199044961713Sgirish 
199159ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
199259ac0c16Sdavemq 	if (status != NXGE_OK)
199359ac0c16Sdavemq 		goto fail;
199459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
199559ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
199659ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
199759ac0c16Sdavemq 	if (status != NXGE_OK)
199859ac0c16Sdavemq 		goto fail;
199959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
200059ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
200159ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
200259ac0c16Sdavemq 	if (status != NXGE_OK)
200359ac0c16Sdavemq 		goto fail;
200459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
200559ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
200644961713Sgirish 
200759ac0c16Sdavemq #ifdef	NXGE_DEBUG
200859ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
200959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
201059ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
201159ac0c16Sdavemq 	    &val);
201259ac0c16Sdavemq 	if (status != NXGE_OK)
201359ac0c16Sdavemq 		goto fail;
201444961713Sgirish 
201559ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
201644961713Sgirish 				BCM8704_USER_DEV3_ADDR,
201759ac0c16Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
201859ac0c16Sdavemq 				&val);
201959ac0c16Sdavemq 	if (status != NXGE_OK)
202059ac0c16Sdavemq 		goto fail;
202144961713Sgirish 
202259ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
202344961713Sgirish 				BCM8704_USER_DEV3_ADDR,
202459ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
202559ac0c16Sdavemq 				&val1);
202659ac0c16Sdavemq 	if (status != NXGE_OK)
202759ac0c16Sdavemq 		goto fail;
202844961713Sgirish 
202959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
203044961713Sgirish 				BCM8704_USER_DEV3_ADDR,
203159ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
203259ac0c16Sdavemq 				&val1);
203359ac0c16Sdavemq 	if (status != NXGE_OK)
203459ac0c16Sdavemq 		goto fail;
203544961713Sgirish 
203659ac0c16Sdavemq 	if (val != 0x3FC) {
203759ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
203859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
203959ac0c16Sdavemq 			    "Cable not connected to peer or bad"
204059ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
204159ac0c16Sdavemq 		} else if (val == 0x639C) {
204259ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
204359ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
204459ac0c16Sdavemq 			    " on port<%d>\n", portn));
204559ac0c16Sdavemq 		}
204659ac0c16Sdavemq 	}
204759ac0c16Sdavemq #endif
204844961713Sgirish 
20492d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
20502d17280bSsbehera 	    portn));
20512d17280bSsbehera 	return (NXGE_OK);
20522d17280bSsbehera 
20532d17280bSsbehera fail:
20542d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20552d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
20562d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
20572d17280bSsbehera 	return (NXGE_ERROR);
20582d17280bSsbehera }
20592d17280bSsbehera 
20602d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
20612d17280bSsbehera 
20622d17280bSsbehera static nxge_status_t
20632d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
20642d17280bSsbehera {
20652d17280bSsbehera 	uint8_t			phy_port_addr;
20662d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
20672d17280bSsbehera 	pcs_control_t		pcs_ctl;
20682d17280bSsbehera 	uint32_t		delay = 0;
20692d17280bSsbehera 	optics_dcntr_t		op_ctr;
20702d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
20712d17280bSsbehera #ifdef	NXGE_DEBUG
20722d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
20732d17280bSsbehera #endif
20742d17280bSsbehera 
20752d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
20762d17280bSsbehera 	    portn));
20772d17280bSsbehera 
20782d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
20792d17280bSsbehera 
20802d17280bSsbehera 	/* Reset the transceiver */
20812d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20822d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
20832d17280bSsbehera 		goto fail;
20842d17280bSsbehera 
20852d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
20862d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20872d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
20882d17280bSsbehera 		goto fail;
20892d17280bSsbehera 	do {
20902d17280bSsbehera 		drv_usecwait(500);
20912d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20922d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
20932d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
20942d17280bSsbehera 			goto fail;
20952d17280bSsbehera 		delay++;
20962d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
20972d17280bSsbehera 
20982d17280bSsbehera 	if (delay == 100) {
20992d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21002d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
21012d17280bSsbehera 		status = NXGE_ERROR;
21022d17280bSsbehera 		goto fail;
21032d17280bSsbehera 	}
21042d17280bSsbehera 
21052d17280bSsbehera 	NXGE_DELAY(1000000);
21062d17280bSsbehera 
21072d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
21082d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21092d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
21102d17280bSsbehera 	    != NXGE_OK)
21112d17280bSsbehera 		goto fail;
21122d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
21132d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
21142d17280bSsbehera 	else
21152d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
21162d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21172d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
21182d17280bSsbehera 	    != NXGE_OK)
21192d17280bSsbehera 		goto fail;
21202d17280bSsbehera 
21212d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
21222d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21232d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21242d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
21252d17280bSsbehera 		goto fail;
21262d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
21272d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
21282d17280bSsbehera 
21292d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21302d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21312d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
21322d17280bSsbehera 		goto fail;
21332d17280bSsbehera 
21342d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
21352d17280bSsbehera 	    portn));
21362d17280bSsbehera 	return (NXGE_OK);
21372d17280bSsbehera 
21382d17280bSsbehera fail:
21392d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21402d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
21412d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
21422d17280bSsbehera 	return (status);
21432d17280bSsbehera }
21442d17280bSsbehera 
21452d17280bSsbehera /* Initialize the 10G Transceiver */
21462d17280bSsbehera 
21472d17280bSsbehera static nxge_status_t
21482d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
21492d17280bSsbehera {
21502d17280bSsbehera 	p_nxge_stats_t		statsp;
21511bd6825cSml 	p_nxge_param_t		param_arr = nxgep->param_arr;
21522d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
21532d17280bSsbehera #ifdef	NXGE_DEBUG
21542d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
21552d17280bSsbehera #endif
21562d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
21572d17280bSsbehera 	    portn));
21582d17280bSsbehera 
21592d17280bSsbehera 	statsp = nxgep->statsp;
21602d17280bSsbehera 
21612d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
21622d17280bSsbehera 		goto done;
21632d17280bSsbehera 	}
21642d17280bSsbehera 
21652d17280bSsbehera 	/* Disable Link LEDs */
21662d17280bSsbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
21672d17280bSsbehera 		goto fail;
21682d17280bSsbehera 
21692d17280bSsbehera 	/* Set Clause 45 */
21702d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
21712d17280bSsbehera 
21722d17280bSsbehera 	switch (nxgep->chip_id) {
21732d17280bSsbehera 	case BCM8704_CHIP_ID:
21742d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21752d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
21762d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
21772d17280bSsbehera 		break;
21782d17280bSsbehera 	case BCM8706_CHIP_ID:
21792d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21802d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
21812d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
21822d17280bSsbehera 		break;
21832d17280bSsbehera 	default:
21842d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
21852d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
21862d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
21872d17280bSsbehera 		goto fail;
21882d17280bSsbehera 	}
21892d17280bSsbehera 
21902d17280bSsbehera 	if (status != NXGE_OK) {
21912d17280bSsbehera 		goto fail;
21922d17280bSsbehera 	}
21932e59129aSraghus done:
219459ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
219559ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
21961bd6825cSml 	statsp->mac_stats.adv_cap_asmpause =
21971bd6825cSml 	    param_arr[param_anar_asmpause].value;
21981bd6825cSml 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
219944961713Sgirish 
220059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
220159ac0c16Sdavemq 	    portn));
220259ac0c16Sdavemq 	return (NXGE_OK);
220344961713Sgirish 
220459ac0c16Sdavemq fail:
22052d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
220659ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
22072d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
22082d17280bSsbehera 	return (NXGE_ERROR);
220959ac0c16Sdavemq }
221044961713Sgirish 
221159ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
221244961713Sgirish 
221359ac0c16Sdavemq static nxge_status_t
221459ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
221559ac0c16Sdavemq {
221659ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
221759ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
221859ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
221944961713Sgirish 
22202e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
22212e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
22222e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
22232e59129aSraghus 		goto done;
22242e59129aSraghus 	}
22252e59129aSraghus 
222659ac0c16Sdavemq 	/* Set Clause 22 */
222759ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
222844961713Sgirish 
222959ac0c16Sdavemq 	/* Set capability flags */
223059ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
22312e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
22322e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
22332e59129aSraghus 		statsp->mac_stats.cap_100fdx =
22342e59129aSraghus 		    param_arr[param_anar_100fdx].value;
22352e59129aSraghus 		statsp->mac_stats.cap_10fdx =
22362e59129aSraghus 		    param_arr[param_anar_10fdx].value;
22372e59129aSraghus 	}
223844961713Sgirish 
223959ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
22402e59129aSraghus done:
224159ac0c16Sdavemq 	return (status);
224259ac0c16Sdavemq }
224359ac0c16Sdavemq 
224459ac0c16Sdavemq /* Initialize transceiver */
224559ac0c16Sdavemq 
224659ac0c16Sdavemq nxge_status_t
224759ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
224859ac0c16Sdavemq {
224959ac0c16Sdavemq 	p_nxge_stats_t		statsp;
225059ac0c16Sdavemq #ifdef	NXGE_DEBUG
225159ac0c16Sdavemq 	uint8_t			portn;
225244961713Sgirish #endif
225344961713Sgirish 
225459ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
225559ac0c16Sdavemq #ifdef	NXGE_DEBUG
225659ac0c16Sdavemq 	portn = nxgep->mac.portnum;
225759ac0c16Sdavemq #endif
225859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
225959ac0c16Sdavemq 	statsp = nxgep->statsp;
226044961713Sgirish 
226159ac0c16Sdavemq 	/*
226259ac0c16Sdavemq 	 * Initialize the xcvr statistics.
226359ac0c16Sdavemq 	 */
226459ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
226559ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
226659ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
226759ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
226859ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
226959ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
227059ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
227159ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
227259ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
227359ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
227459ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
227559ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
227659ac0c16Sdavemq 
227759ac0c16Sdavemq 	/*
227859ac0c16Sdavemq 	 * Initialize the link statistics.
227959ac0c16Sdavemq 	 */
228059ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
228159ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
228259ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
228344961713Sgirish 
228459ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
228559ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
228659ac0c16Sdavemq 		if (status != NXGE_OK)
228744961713Sgirish 			goto fail;
228859ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
228944961713Sgirish 	}
229044961713Sgirish 
229159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
229259ac0c16Sdavemq 	    portn));
229344961713Sgirish 	return (NXGE_OK);
229444961713Sgirish 
229544961713Sgirish fail:
229644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
229759ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
229859ac0c16Sdavemq 	    portn));
229944961713Sgirish 	return (status);
230044961713Sgirish }
230144961713Sgirish 
23022e59129aSraghus /* Look for transceiver type */
23032e59129aSraghus 
23042e59129aSraghus nxge_status_t
23052e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
23062e59129aSraghus {
2307d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
2308d81011f0Ssbehera 	    nxgep->mac.portnum));
23092e59129aSraghus 
23102e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
23112e59129aSraghus 		return (NXGE_ERROR);
23122e59129aSraghus 
23132e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
23142e59129aSraghus 		return (NXGE_ERROR);
23152e59129aSraghus 
23162e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
23172e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
23182e59129aSraghus 	return (NXGE_OK);
23192e59129aSraghus }
232044961713Sgirish 
232144961713Sgirish /* Initialize the TxMAC sub-block */
232244961713Sgirish 
232344961713Sgirish nxge_status_t
232444961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
232544961713Sgirish {
232644961713Sgirish 	npi_attr_t		ap;
232744961713Sgirish 	uint8_t			portn;
232844961713Sgirish 	nxge_port_mode_t	portmode;
232944961713Sgirish 	nxge_port_t		portt;
233044961713Sgirish 	npi_handle_t		handle;
233144961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
233244961713Sgirish 
233344961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
233444961713Sgirish 	portt    = nxgep->mac.porttype;
233544961713Sgirish 	handle   = nxgep->npi_handle;
233644961713Sgirish 	portmode = nxgep->mac.portmode;
233744961713Sgirish 
233844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
233944961713Sgirish 			portn));
234044961713Sgirish 	/* Set Max and Min Frame Size */
23411bd6825cSml 	/*
23421bd6825cSml 	 * Use maxframesize to configure the hardware maxframe size
23431bd6825cSml 	 * and minframesize to configure the hardwae minframe size.
23441bd6825cSml 	 */
23451bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23461bd6825cSml 	    "==> nxge_tx_mac_init: port<%d> "
23471bd6825cSml 	    "min framesize %d max framesize %d ",
23481bd6825cSml 	    nxgep->mac.minframesize,
23491bd6825cSml 	    nxgep->mac.maxframesize,
23501bd6825cSml 	    portn));
235144961713Sgirish 
23521bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
23531bd6825cSml 	    MAC_PORT_FRAME_SIZE,
23541bd6825cSml 	    nxgep->mac.minframesize,
23551bd6825cSml 	    nxgep->mac.maxframesize,
23561bd6825cSml 	    rs);
235744961713Sgirish 	if (rs != NPI_SUCCESS)
235844961713Sgirish 		goto fail;
235944961713Sgirish 
236044961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
236144961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
236244961713Sgirish 				0)) != NPI_SUCCESS)
236344961713Sgirish 			goto fail;
236444961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
236544961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
23662e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
23672e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
236844961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
236944961713Sgirish 					XGMII_IPG_12_15, rs);
237044961713Sgirish 			if (rs != NPI_SUCCESS)
237144961713Sgirish 				goto fail;
237244961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
237344961713Sgirish 		} else {
237444961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
237544961713Sgirish 					MII_GMII_IPG_12, rs);
237644961713Sgirish 			if (rs != NPI_SUCCESS)
237744961713Sgirish 				goto fail;
237844961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
237944961713Sgirish 		}
238044961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
238144961713Sgirish 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
238244961713Sgirish 			goto fail;
238344961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
238444961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
238544961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
238644961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
238744961713Sgirish 
238844961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
238944961713Sgirish 							!= NPI_SUCCESS)
239044961713Sgirish 			goto fail;
239144961713Sgirish 
239244961713Sgirish 	} else {
239344961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
239444961713Sgirish 				0)) != NPI_SUCCESS)
239544961713Sgirish 			goto fail;
239644961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
239744961713Sgirish 
239844961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
239944961713Sgirish 				rs);
240044961713Sgirish 		if (rs != NPI_SUCCESS)
240144961713Sgirish 			goto fail;
240244961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
240344961713Sgirish 
240444961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
240544961713Sgirish 		if (rs != NPI_SUCCESS)
240644961713Sgirish 			goto fail;
240744961713Sgirish 		nxgep->mac.pa_size = 0x7;
240844961713Sgirish 
240944961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
241044961713Sgirish 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
241144961713Sgirish 			goto fail;
241244961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
241344961713Sgirish 	}
241444961713Sgirish 
241544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
241644961713Sgirish 			portn));
241744961713Sgirish 
241844961713Sgirish 	return (NXGE_OK);
241944961713Sgirish fail:
242044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
242144961713Sgirish 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
242244961713Sgirish 					portn));
242344961713Sgirish 
242444961713Sgirish 	return (NXGE_ERROR | rs);
242544961713Sgirish }
242644961713Sgirish 
2427*678453a8Sspeer int
2428*678453a8Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep)
2429*678453a8Sspeer {
2430*678453a8Sspeer 	int rdc_tbl;
2431*678453a8Sspeer 
2432*678453a8Sspeer 	/*
2433*678453a8Sspeer 	 * Get an RDC table (version 0).
2434*678453a8Sspeer 	 */
2435*678453a8Sspeer 	if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) {
2436*678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, OBP_CTL,
2437*678453a8Sspeer 		    "nxge_hio_hostinfo_get_rdc_table: "
2438*678453a8Sspeer 		    "there are no free RDC tables!"));
2439*678453a8Sspeer 		return (EBUSY);
2440*678453a8Sspeer 	}
2441*678453a8Sspeer 
2442*678453a8Sspeer 	return (rdc_tbl);
2443*678453a8Sspeer }
2444*678453a8Sspeer 
2445*678453a8Sspeer /*
2446*678453a8Sspeer  * nxge_hio_hostinfo_init
2447*678453a8Sspeer  *
2448*678453a8Sspeer  *	Initialize an alternate MAC address, and bind a macrdctbln to it.
2449*678453a8Sspeer  *
2450*678453a8Sspeer  * Arguments:
2451*678453a8Sspeer  * 	nxge
2452*678453a8Sspeer  * 	vr	The Virtualization Region
2453*678453a8Sspeer  * 	macaddr	The alternate MAC address
2454*678453a8Sspeer  *
2455*678453a8Sspeer  * Notes:
2456*678453a8Sspeer  *	1. Find & bind an RDC table to <nxge>.
2457*678453a8Sspeer  *	2. Program an alternate MAC address (<macaddr>).
2458*678453a8Sspeer  *	3. Bind the RDC table to <macaddr>.
2459*678453a8Sspeer  *
2460*678453a8Sspeer  * Context:
2461*678453a8Sspeer  *	Service domain
2462*678453a8Sspeer  *
2463*678453a8Sspeer  * Side Effects:
2464*678453a8Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
2465*678453a8Sspeer  *	vr->slot & vr->altmac
2466*678453a8Sspeer  *
2467*678453a8Sspeer  */
2468*678453a8Sspeer int
2469*678453a8Sspeer nxge_hio_hostinfo_init(
2470*678453a8Sspeer 	nxge_t *nxge,
2471*678453a8Sspeer 	nxge_hio_vr_t *vr,	/* Virtualization Region */
2472*678453a8Sspeer 	ether_addr_t *macaddr)	/* The alternate MAC address */
2473*678453a8Sspeer {
2474*678453a8Sspeer 	int rdc_tbl, slot;
2475*678453a8Sspeer 
2476*678453a8Sspeer 	nxge_class_pt_cfg_t *class;
2477*678453a8Sspeer 	hostinfo_t mac_rdc;
2478*678453a8Sspeer 	npi_mac_addr_t altmac;
2479*678453a8Sspeer 	nxge_mmac_t *mmac_info;
2480*678453a8Sspeer 	nxge_rdc_grp_t	*group;
2481*678453a8Sspeer 	uint8_t *addr = (uint8_t *)macaddr;
2482*678453a8Sspeer 
2483*678453a8Sspeer 	mutex_enter(nxge->genlock);
2484*678453a8Sspeer 
2485*678453a8Sspeer 	rdc_tbl = vr->rdc_tbl;
2486*678453a8Sspeer 
2487*678453a8Sspeer 	/* Initialize the NXGE RDC table data structure. */
2488*678453a8Sspeer 	group = &nxge->pt_config.rdc_grps[rdc_tbl];
2489*678453a8Sspeer 	group->port = NXGE_GET_PORT_NUM(nxge->function_num);
2490*678453a8Sspeer 	group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
2491*678453a8Sspeer 	group->flag = 1;	/* This group has been configured. */
2492*678453a8Sspeer 
2493*678453a8Sspeer 	mmac_info = &nxge->nxge_mmac_info;
2494*678453a8Sspeer 
2495*678453a8Sspeer 	/*
2496*678453a8Sspeer 	 * Are there free slots.
2497*678453a8Sspeer 	 */
2498*678453a8Sspeer 	if (mmac_info->naddrfree == 0) {
2499*678453a8Sspeer 		mutex_exit(nxge->genlock);
2500*678453a8Sspeer 		return (ENOSPC);
2501*678453a8Sspeer 	}
2502*678453a8Sspeer 
2503*678453a8Sspeer 	/*
2504*678453a8Sspeer 	 * The vswitch has already added this MAC address.
2505*678453a8Sspeer 	 * Find its assigned slot.
2506*678453a8Sspeer 	 */
2507*678453a8Sspeer 	if (mmac_info->num_factory_mmac < mmac_info->num_mmac) {
2508*678453a8Sspeer 		for (slot = mmac_info->num_factory_mmac + 1;
2509*678453a8Sspeer 		    slot <= mmac_info->num_mmac; slot++) {
2510*678453a8Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
2511*678453a8Sspeer 				break;
2512*678453a8Sspeer 		}
2513*678453a8Sspeer 		if (slot > mmac_info->num_mmac) {
2514*678453a8Sspeer 			for (slot = 1; slot <= mmac_info->num_factory_mmac;
2515*678453a8Sspeer 			    slot++) {
2516*678453a8Sspeer 				if (!(mmac_info->mac_pool[slot].flags
2517*678453a8Sspeer 				    & MMAC_SLOT_USED))
2518*678453a8Sspeer 					break;
2519*678453a8Sspeer 			}
2520*678453a8Sspeer 		}
2521*678453a8Sspeer 	} else {
2522*678453a8Sspeer 		for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
2523*678453a8Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
2524*678453a8Sspeer 				break;
2525*678453a8Sspeer 		}
2526*678453a8Sspeer 	}
2527*678453a8Sspeer 
2528*678453a8Sspeer 	ASSERT(slot <= mmac_info->num_mmac);
2529*678453a8Sspeer 	vr->slot = slot;
2530*678453a8Sspeer 	slot = vr->slot - 1;
2531*678453a8Sspeer 
2532*678453a8Sspeer 	/*
2533*678453a8Sspeer 	 * Programm the mac address.
2534*678453a8Sspeer 	 */
2535*678453a8Sspeer 	altmac.w2 = (((uint16_t)addr[0]) << 8) |
2536*678453a8Sspeer 	    (((uint16_t)addr[1]) & 0x0ff);
2537*678453a8Sspeer 	altmac.w1 = (((uint16_t)addr[2]) << 8) |
2538*678453a8Sspeer 	    (((uint16_t)addr[3]) & 0x0ff);
2539*678453a8Sspeer 	altmac.w0 = (((uint16_t)addr[4]) << 8) |
2540*678453a8Sspeer 	    (((uint16_t)addr[5]) & 0x0ff);
2541*678453a8Sspeer 
2542*678453a8Sspeer 	if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET,
2543*678453a8Sspeer 	    nxge->function_num, slot, &altmac) != NPI_SUCCESS) {
2544*678453a8Sspeer 		mutex_exit(nxge->genlock);
2545*678453a8Sspeer 		return (EIO);
2546*678453a8Sspeer 	}
2547*678453a8Sspeer 
2548*678453a8Sspeer 	/*
2549*678453a8Sspeer 	 * Associate <rdc_tbl> with this MAC address slot.
2550*678453a8Sspeer 	 */
2551*678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2552*678453a8Sspeer 
2553*678453a8Sspeer 	/* Update this variable. */
2554*678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2555*678453a8Sspeer 	class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl;
2556*678453a8Sspeer 
2557*678453a8Sspeer 	mac_rdc.value = 0;
2558*678453a8Sspeer 	mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl;
2559*678453a8Sspeer 	mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr;
2560*678453a8Sspeer 	/* <mpr_npr> had better be 1! */
2561*678453a8Sspeer 
2562*678453a8Sspeer 	/* Program the RDC table. */
2563*678453a8Sspeer 	if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET,
2564*678453a8Sspeer 		nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) {
2565*678453a8Sspeer 		mutex_exit(nxge->genlock);
2566*678453a8Sspeer 		(void) nxge_m_mmac_remove(nxge, vr->slot);
2567*678453a8Sspeer 		return (EIO);
2568*678453a8Sspeer 	}
2569*678453a8Sspeer 
2570*678453a8Sspeer 	if (nxge->mac.portnum != XMAC_PORT_0 &&
2571*678453a8Sspeer 	    nxge->mac.portnum != XMAC_PORT_1)
2572*678453a8Sspeer 		slot++;
2573*678453a8Sspeer 
2574*678453a8Sspeer 	/* (Re-)enable the MAC address. */
2575*678453a8Sspeer 	(void) npi_mac_altaddr_enable(
2576*678453a8Sspeer 		nxge->npi_handle, nxge->mac.portnum, slot);
2577*678453a8Sspeer 
2578*678453a8Sspeer 	bcopy(macaddr, vr->altmac, sizeof (vr->altmac));
2579*678453a8Sspeer 
2580*678453a8Sspeer 	/*
2581*678453a8Sspeer 	 * Update mmac
2582*678453a8Sspeer 	 */
2583*678453a8Sspeer 	bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL);
2584*678453a8Sspeer 	mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED;
2585*678453a8Sspeer 	mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR;
2586*678453a8Sspeer 	mmac_info->naddrfree--;
2587*678453a8Sspeer 	nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE);
2588*678453a8Sspeer 
2589*678453a8Sspeer 	mutex_exit(nxge->genlock);
2590*678453a8Sspeer 	return (0);
2591*678453a8Sspeer }
2592*678453a8Sspeer 
2593*678453a8Sspeer /*
2594*678453a8Sspeer  * nxge_hio_hostinfo_uninit
2595*678453a8Sspeer  *
2596*678453a8Sspeer  *	Uninitialize an alternate MAC address.
2597*678453a8Sspeer  *
2598*678453a8Sspeer  * Arguments:
2599*678453a8Sspeer  * 	nxge
2600*678453a8Sspeer  * 	vr	The Virtualization Region
2601*678453a8Sspeer  *
2602*678453a8Sspeer  * Notes:
2603*678453a8Sspeer  *	1. Remove the VR's alternate MAC address.
2604*678453a8Sspeer  *	1. Free (unbind) the RDC table allocated to this VR.
2605*678453a8Sspeer  *
2606*678453a8Sspeer  * Context:
2607*678453a8Sspeer  *	Service domain
2608*678453a8Sspeer  *
2609*678453a8Sspeer  * Side Effects:
2610*678453a8Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
2611*678453a8Sspeer  *
2612*678453a8Sspeer  */
2613*678453a8Sspeer void
2614*678453a8Sspeer nxge_hio_hostinfo_uninit(
2615*678453a8Sspeer 	nxge_t *nxge,
2616*678453a8Sspeer 	nxge_hio_vr_t *vr)
2617*678453a8Sspeer {
2618*678453a8Sspeer 	nxge_class_pt_cfg_t *class;
2619*678453a8Sspeer 
2620*678453a8Sspeer 	(void) npi_mac_altaddr_disable(
2621*678453a8Sspeer 		nxge->npi_handle, nxge->mac.portnum, vr->slot);
2622*678453a8Sspeer 
2623*678453a8Sspeer 	/* Set this variable to its default. */
2624*678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2625*678453a8Sspeer 	class->mac_host_info[vr->slot].rdctbl =
2626*678453a8Sspeer 	    nxge->pt_config.hw_config.def_mac_rxdma_grpid;
2627*678453a8Sspeer 
2628*678453a8Sspeer 	(void) nxge_m_mmac_remove(nxge, vr->slot);
2629*678453a8Sspeer 	vr->slot = -1;
2630*678453a8Sspeer 
2631*678453a8Sspeer 	(void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl);
2632*678453a8Sspeer 	vr->rdc_tbl = -1;
2633*678453a8Sspeer }
2634*678453a8Sspeer 
263544961713Sgirish /* Initialize the RxMAC sub-block */
263644961713Sgirish 
263744961713Sgirish nxge_status_t
263844961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
263944961713Sgirish {
264044961713Sgirish 	npi_attr_t		ap;
264144961713Sgirish 	uint32_t		i;
264244961713Sgirish 	uint16_t		hashtab_e;
264344961713Sgirish 	p_hash_filter_t		hash_filter;
264444961713Sgirish 	nxge_port_t		portt;
264544961713Sgirish 	uint8_t			portn;
264644961713Sgirish 	npi_handle_t		handle;
264744961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
264844961713Sgirish 	uint16_t 		*addr16p;
264944961713Sgirish 	uint16_t 		addr0, addr1, addr2;
265044961713Sgirish 	xmac_rx_config_t	xconfig;
265144961713Sgirish 	bmac_rx_config_t	bconfig;
265244961713Sgirish 
265344961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
265444961713Sgirish 
265544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
265644961713Sgirish 			portn));
265744961713Sgirish 	handle = nxgep->npi_handle;
265844961713Sgirish 	portt = nxgep->mac.porttype;
265944961713Sgirish 
266044961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
266144961713Sgirish 	addr0 = ntohs(addr16p[2]);
266244961713Sgirish 	addr1 = ntohs(addr16p[1]);
266344961713Sgirish 	addr2 = ntohs(addr16p[0]);
266444961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
266544961713Sgirish 		rs);
266644961713Sgirish 
266744961713Sgirish 	if (rs != NPI_SUCCESS)
266844961713Sgirish 		goto fail;
266944961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
267044961713Sgirish 	if (rs != NPI_SUCCESS)
267144961713Sgirish 		goto fail;
267244961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
267344961713Sgirish 	if (rs != NPI_SUCCESS)
267444961713Sgirish 		goto fail;
267544961713Sgirish 
267644961713Sgirish 	/*
267744961713Sgirish 	 * Load the multicast hash filter bits.
267844961713Sgirish 	 */
267944961713Sgirish 	hash_filter = nxgep->hash_filter;
268044961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
268144961713Sgirish 		if (hash_filter != NULL) {
268244961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
268344961713Sgirish 				(NMCFILTER_REGS - 1) - i];
268444961713Sgirish 		} else {
268544961713Sgirish 			hashtab_e = 0;
268644961713Sgirish 		}
268744961713Sgirish 
268844961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
268944961713Sgirish 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
269044961713Sgirish 			goto fail;
269144961713Sgirish 	}
269244961713Sgirish 
269344961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
269444961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
269544961713Sgirish 				0)) != NPI_SUCCESS)
269644961713Sgirish 			goto fail;
269744961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
269844961713Sgirish 
269944961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
270044961713Sgirish 
270144961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
2702a3c5bd6dSspeer 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
2703a3c5bd6dSspeer 			~CFG_XMAC_RX_STRIP_CRC;
270444961713Sgirish 
270544961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
270644961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
270744961713Sgirish 
270844961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
270944961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
271044961713Sgirish 
271144961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
271244961713Sgirish 
271344961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
271444961713Sgirish 					xconfig)) != NPI_SUCCESS)
271544961713Sgirish 			goto fail;
271644961713Sgirish 		nxgep->mac.rx_config = xconfig;
271744961713Sgirish 
271844961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
271944961713Sgirish 
272044961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
272144961713Sgirish 							!= NPI_SUCCESS)
272244961713Sgirish 			goto fail;
272344961713Sgirish 	} else {
272444961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
272544961713Sgirish 
272644961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
272744961713Sgirish 					0) != NPI_SUCCESS)
272844961713Sgirish 			goto fail;
272944961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
273044961713Sgirish 
2731a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
2732a3c5bd6dSspeer 			~CFG_BMAC_RX_STRIP_CRC;
273344961713Sgirish 
273444961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
273544961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
273644961713Sgirish 
273744961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
273844961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
273944961713Sgirish 
274044961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
274144961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
274244961713Sgirish 					bconfig)) != NPI_SUCCESS)
274344961713Sgirish 			goto fail;
274444961713Sgirish 		nxgep->mac.rx_config = bconfig;
274544961713Sgirish 
274644961713Sgirish 		/* Always enable comparison of mac unique address */
274744961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
274844961713Sgirish 					!= NPI_SUCCESS)
274944961713Sgirish 			goto fail;
275044961713Sgirish 	}
275144961713Sgirish 
275244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
275344961713Sgirish 			portn));
275444961713Sgirish 
275544961713Sgirish 	return (NXGE_OK);
275644961713Sgirish 
275744961713Sgirish fail:
275844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
275944961713Sgirish 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
276044961713Sgirish 				portn));
276144961713Sgirish 
276244961713Sgirish 	return (NXGE_ERROR | rs);
276344961713Sgirish }
276444961713Sgirish 
276544961713Sgirish /* Enable TXMAC */
276644961713Sgirish 
276744961713Sgirish nxge_status_t
276844961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
276944961713Sgirish {
277044961713Sgirish 	npi_handle_t	handle;
277144961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
277244961713Sgirish 	nxge_status_t	status = NXGE_OK;
277344961713Sgirish 
277444961713Sgirish 	handle = nxgep->npi_handle;
277544961713Sgirish 
277644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
277744961713Sgirish 			nxgep->mac.portnum));
277844961713Sgirish 
277944961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
278044961713Sgirish 		goto fail;
278144961713Sgirish 
278244961713Sgirish 	/* based on speed */
278344961713Sgirish 	nxgep->msg_min = ETHERMIN;
278444961713Sgirish 
278544961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
278644961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
278744961713Sgirish 						CFG_XMAC_TX)) != NPI_SUCCESS)
278844961713Sgirish 			goto fail;
278944961713Sgirish 	} else {
279044961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
279144961713Sgirish 						CFG_BMAC_TX)) != NPI_SUCCESS)
279244961713Sgirish 			goto fail;
279344961713Sgirish 	}
279444961713Sgirish 
279544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
279644961713Sgirish 			nxgep->mac.portnum));
279744961713Sgirish 
279844961713Sgirish 	return (NXGE_OK);
279944961713Sgirish fail:
280044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
280144961713Sgirish 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
280244961713Sgirish 			nxgep->mac.portnum));
280344961713Sgirish 	if (rs != NPI_SUCCESS)
280444961713Sgirish 		return (NXGE_ERROR | rs);
280544961713Sgirish 	else
280644961713Sgirish 		return (status);
280744961713Sgirish }
280844961713Sgirish 
280944961713Sgirish /* Disable TXMAC */
281044961713Sgirish 
281144961713Sgirish nxge_status_t
281244961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
281344961713Sgirish {
281444961713Sgirish 	npi_handle_t	handle;
281544961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
281644961713Sgirish 
2817*678453a8Sspeer 	if (isLDOMguest(nxgep))
2818*678453a8Sspeer 		return (NXGE_OK);
2819*678453a8Sspeer 
282044961713Sgirish 	handle = nxgep->npi_handle;
282144961713Sgirish 
282244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
282344961713Sgirish 			nxgep->mac.portnum));
282444961713Sgirish 
282544961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
282644961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
282744961713Sgirish 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
282844961713Sgirish 			goto fail;
282944961713Sgirish 	} else {
283044961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
283144961713Sgirish 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
283244961713Sgirish 			goto fail;
283344961713Sgirish 	}
283444961713Sgirish 
283544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
283644961713Sgirish 			nxgep->mac.portnum));
283744961713Sgirish 	return (NXGE_OK);
283844961713Sgirish fail:
283944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
284044961713Sgirish 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
284144961713Sgirish 			nxgep->mac.portnum));
284244961713Sgirish 	return (NXGE_ERROR | rs);
284344961713Sgirish }
284444961713Sgirish 
284544961713Sgirish /* Enable RXMAC */
284644961713Sgirish 
284744961713Sgirish nxge_status_t
284844961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
284944961713Sgirish {
285044961713Sgirish 	npi_handle_t	handle;
285144961713Sgirish 	uint8_t 	portn;
285244961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
285344961713Sgirish 	nxge_status_t	status = NXGE_OK;
285444961713Sgirish 
2855*678453a8Sspeer 	/* This is a service-domain-only activity. */
2856*678453a8Sspeer 	if (isLDOMguest(nxgep))
2857*678453a8Sspeer 		return (status);
2858*678453a8Sspeer 
285944961713Sgirish 	handle = nxgep->npi_handle;
286044961713Sgirish 	portn = nxgep->mac.portnum;
286144961713Sgirish 
286244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
286344961713Sgirish 			portn));
286444961713Sgirish 
286544961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
286644961713Sgirish 		goto fail;
286744961713Sgirish 
286844961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
286944961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
2870*678453a8Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
287144961713Sgirish 			goto fail;
287244961713Sgirish 	} else {
287344961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
2874*678453a8Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
287544961713Sgirish 			goto fail;
287644961713Sgirish 	}
287744961713Sgirish 
2878*678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2879*678453a8Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
288044961713Sgirish 
288144961713Sgirish 	return (NXGE_OK);
288244961713Sgirish fail:
288344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2884*678453a8Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
288544961713Sgirish 
288644961713Sgirish 	if (rs != NPI_SUCCESS)
288744961713Sgirish 		return (NXGE_ERROR | rs);
288844961713Sgirish 	else
288944961713Sgirish 		return (status);
289044961713Sgirish }
289144961713Sgirish 
289244961713Sgirish /* Disable RXMAC */
289344961713Sgirish 
289444961713Sgirish nxge_status_t
289544961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
289644961713Sgirish {
289744961713Sgirish 	npi_handle_t	handle;
289844961713Sgirish 	uint8_t		portn;
289944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
290044961713Sgirish 
2901*678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
2902*678453a8Sspeer 	if (isLDOMguest(nxgep))
2903*678453a8Sspeer 		return (NXGE_OK);
2904*678453a8Sspeer 
290544961713Sgirish 	handle = nxgep->npi_handle;
290644961713Sgirish 	portn = nxgep->mac.portnum;
290744961713Sgirish 
290844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
290944961713Sgirish 			portn));
291044961713Sgirish 
291144961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
291244961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
291344961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
291444961713Sgirish 			goto fail;
291544961713Sgirish 	} else {
291644961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
291744961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
291844961713Sgirish 			goto fail;
291944961713Sgirish 	}
292044961713Sgirish 
292144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
292244961713Sgirish 			portn));
292344961713Sgirish 	return (NXGE_OK);
292444961713Sgirish fail:
292544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
292644961713Sgirish 			"nxgep_rx_mac_disable: ",
292744961713Sgirish 			"Failed to disable port<%d> RxMAC",
292844961713Sgirish 			portn));
292944961713Sgirish 
293044961713Sgirish 	return (NXGE_ERROR | rs);
293144961713Sgirish }
293244961713Sgirish 
293344961713Sgirish /* Reset TXMAC */
293444961713Sgirish 
293544961713Sgirish nxge_status_t
293644961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
293744961713Sgirish {
293844961713Sgirish 	npi_handle_t	handle;
293944961713Sgirish 	uint8_t		portn;
294044961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
294144961713Sgirish 
294244961713Sgirish 	handle = nxgep->npi_handle;
294344961713Sgirish 	portn = nxgep->mac.portnum;
294444961713Sgirish 
294544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
294644961713Sgirish 			portn));
294744961713Sgirish 
294844961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
294944961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
295044961713Sgirish 		    != NPI_SUCCESS)
295144961713Sgirish 			goto fail;
295244961713Sgirish 	} else {
295344961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
295444961713Sgirish 					!= NPI_SUCCESS)
295544961713Sgirish 			goto fail;
295644961713Sgirish 	}
295744961713Sgirish 
295844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
295944961713Sgirish 			portn));
296044961713Sgirish 
296144961713Sgirish 	return (NXGE_OK);
296244961713Sgirish fail:
296344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
296444961713Sgirish 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
296544961713Sgirish 			portn));
296644961713Sgirish 
296744961713Sgirish 	return (NXGE_ERROR | rs);
296844961713Sgirish }
296944961713Sgirish 
297044961713Sgirish /* Reset RXMAC */
297144961713Sgirish 
297244961713Sgirish nxge_status_t
297344961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
297444961713Sgirish {
297544961713Sgirish 	npi_handle_t	handle;
297644961713Sgirish 	uint8_t		portn;
297744961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
297844961713Sgirish 
297944961713Sgirish 	handle = nxgep->npi_handle;
298044961713Sgirish 	portn = nxgep->mac.portnum;
298144961713Sgirish 
298244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
298344961713Sgirish 			portn));
298444961713Sgirish 
298544961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
298644961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
298744961713Sgirish 		    != NPI_SUCCESS)
298844961713Sgirish 		goto fail;
298944961713Sgirish 	} else {
299044961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
299144961713Sgirish 					!= NPI_SUCCESS)
299244961713Sgirish 		goto fail;
299344961713Sgirish 	}
299444961713Sgirish 
299544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
299644961713Sgirish 			portn));
299744961713Sgirish 
299859ac0c16Sdavemq 	return (NXGE_OK);
299959ac0c16Sdavemq fail:
300059ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
300159ac0c16Sdavemq 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
300259ac0c16Sdavemq 			portn));
300359ac0c16Sdavemq 	return (NXGE_ERROR | rs);
300459ac0c16Sdavemq }
300559ac0c16Sdavemq 
300659ac0c16Sdavemq /* 10G fiber link interrupt start routine */
300759ac0c16Sdavemq 
300859ac0c16Sdavemq static nxge_status_t
300959ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
301059ac0c16Sdavemq {
301159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
301259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
301359ac0c16Sdavemq 
301459ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
301559ac0c16Sdavemq 
301659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
301759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
301859ac0c16Sdavemq 	else
301959ac0c16Sdavemq 		return (NXGE_OK);
302059ac0c16Sdavemq }
302159ac0c16Sdavemq 
302259ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
302359ac0c16Sdavemq 
302459ac0c16Sdavemq static nxge_status_t
302559ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
302659ac0c16Sdavemq {
302759ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
302859ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
302959ac0c16Sdavemq 
303059ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
303159ac0c16Sdavemq 
303259ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
303359ac0c16Sdavemq 		return (NXGE_ERROR | rs);
303459ac0c16Sdavemq 	else
303559ac0c16Sdavemq 		return (NXGE_OK);
303659ac0c16Sdavemq }
303759ac0c16Sdavemq 
303859ac0c16Sdavemq /* 1G fiber link interrupt start routine */
303959ac0c16Sdavemq 
304059ac0c16Sdavemq static nxge_status_t
304159ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
304259ac0c16Sdavemq {
304359ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
304459ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
304559ac0c16Sdavemq 
304659ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
304759ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
304859ac0c16Sdavemq 		return (NXGE_ERROR | rs);
304959ac0c16Sdavemq 	else
305059ac0c16Sdavemq 		return (NXGE_OK);
305159ac0c16Sdavemq }
305259ac0c16Sdavemq 
305359ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
305459ac0c16Sdavemq 
305559ac0c16Sdavemq static nxge_status_t
305659ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
305759ac0c16Sdavemq {
305859ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
305959ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
306059ac0c16Sdavemq 
306159ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
306259ac0c16Sdavemq 
306359ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
306459ac0c16Sdavemq 		return (NXGE_ERROR | rs);
306559ac0c16Sdavemq 	else
306659ac0c16Sdavemq 		return (NXGE_OK);
306759ac0c16Sdavemq }
306859ac0c16Sdavemq 
306959ac0c16Sdavemq /* 1G copper link interrupt start routine */
307059ac0c16Sdavemq 
307159ac0c16Sdavemq static nxge_status_t
307259ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
307359ac0c16Sdavemq {
307459ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
307559ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
307659ac0c16Sdavemq 
307759ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
30786b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
307959ac0c16Sdavemq 
308059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
308159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
308259ac0c16Sdavemq 	else
308359ac0c16Sdavemq 		return (NXGE_OK);
308444961713Sgirish }
308544961713Sgirish 
308659ac0c16Sdavemq /* 1G copper link interrupt stop routine */
308759ac0c16Sdavemq 
308859ac0c16Sdavemq static nxge_status_t
308959ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
309059ac0c16Sdavemq {
309159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
309259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
309359ac0c16Sdavemq 
309459ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
309559ac0c16Sdavemq 
309659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
309759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
309859ac0c16Sdavemq 	else
309959ac0c16Sdavemq 		return (NXGE_OK);
310059ac0c16Sdavemq }
310144961713Sgirish 
310259ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
310344961713Sgirish 
310444961713Sgirish nxge_status_t
310544961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
310644961713Sgirish {
310759ac0c16Sdavemq 	uint8_t		portn;
310859ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
310944961713Sgirish 
311044961713Sgirish 	portn = nxgep->mac.portnum;
311144961713Sgirish 
311244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
311359ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
311459ac0c16Sdavemq 		return (NXGE_OK);
311544961713Sgirish 
311659ac0c16Sdavemq 	if (enable == LINK_INTR_START)
311759ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
311859ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
311959ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
312059ac0c16Sdavemq 	if (status != NXGE_OK)
312159ac0c16Sdavemq 		goto fail;
312244961713Sgirish 
312344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
312444961713Sgirish 
312544961713Sgirish 	return (NXGE_OK);
312644961713Sgirish fail:
312744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
312844961713Sgirish 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
312944961713Sgirish 			portn));
313044961713Sgirish 
313159ac0c16Sdavemq 	return (status);
313244961713Sgirish }
313344961713Sgirish 
313444961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
313544961713Sgirish 
313644961713Sgirish nxge_status_t
313744961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
313844961713Sgirish {
313944961713Sgirish 	p_nxge_param_t	param_arr;
314044961713Sgirish 	p_nxge_stats_t	statsp;
314144961713Sgirish 	uint8_t		xcvr_portn;
314244961713Sgirish 	p_mii_regs_t	mii_regs;
314344961713Sgirish 	mii_bmcr_t	bmcr;
314444961713Sgirish 	mii_bmsr_t	bmsr;
314544961713Sgirish 	mii_anar_t	anar;
314644961713Sgirish 	mii_gcr_t	gcr;
314744961713Sgirish 	mii_esr_t	esr;
314844961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
314944961713Sgirish 	int		status = NXGE_OK;
315044961713Sgirish 
315144961713Sgirish 	uint_t delay;
315244961713Sgirish 
315344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
315444961713Sgirish 
315544961713Sgirish 	param_arr = nxgep->param_arr;
315644961713Sgirish 	statsp = nxgep->statsp;
315744961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
315844961713Sgirish 
315944961713Sgirish 	mii_regs = NULL;
316044961713Sgirish 
316144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
316244961713Sgirish 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
316344961713Sgirish 
3164d81011f0Ssbehera 	/*
3165d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
3166d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
3167d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
3168d81011f0Ssbehera 	 */
3169d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
3170d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3171d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
3172d81011f0Ssbehera 	}
3173d81011f0Ssbehera 
317444961713Sgirish 	/*
317544961713Sgirish 	 * Reset the transceiver.
317644961713Sgirish 	 */
317744961713Sgirish 	delay = 0;
317844961713Sgirish 	bmcr.value = 0;
317944961713Sgirish 	bmcr.bits.reset = 1;
318044961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3181adfcba55Sjoycey #if defined(__i386)
3182adfcba55Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3183adfcba55Sjoycey #else
318444961713Sgirish 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3185adfcba55Sjoycey #endif
318644961713Sgirish 		goto fail;
318744961713Sgirish 	do {
318844961713Sgirish 		drv_usecwait(500);
318944961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3190adfcba55Sjoycey #if defined(__i386)
3191adfcba55Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
3192adfcba55Sjoycey #else
319344961713Sgirish 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
3194adfcba55Sjoycey #endif
319544961713Sgirish 				!= NXGE_OK)
319644961713Sgirish 			goto fail;
319744961713Sgirish 		delay++;
319844961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
319944961713Sgirish 	if (delay == 1000) {
320044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
320144961713Sgirish 		goto fail;
320244961713Sgirish 	}
320344961713Sgirish 
320444961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3205adfcba55Sjoycey #if defined(__i386)
3206adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
3207adfcba55Sjoycey #else
320844961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
3209adfcba55Sjoycey #endif
321044961713Sgirish 			&bmsr.value)) != NXGE_OK)
321144961713Sgirish 		goto fail;
321244961713Sgirish 
321344961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
321444961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
321544961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
321644961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
321744961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
321844961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
321944961713Sgirish 
322044961713Sgirish 	/*
322158324dfcSspeer 	 * Initialize the xcvr statistics.
322244961713Sgirish 	 */
322344961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
322444961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
322544961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
322644961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
322744961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
322844961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
322944961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
323044961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
323144961713Sgirish 
323244961713Sgirish 	/*
323344961713Sgirish 	 * Initialise the xcvr advertised capability statistics.
323444961713Sgirish 	 */
323544961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
323644961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
323744961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
323844961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
323944961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
324044961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
324144961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
324244961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
324344961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
324444961713Sgirish 					param_arr[param_anar_asmpause].value;
324544961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
324644961713Sgirish 
324744961713Sgirish 
324844961713Sgirish 	/*
324944961713Sgirish 	 * Check for extended status just in case we're
325044961713Sgirish 	 * running a Gigibit phy.
325144961713Sgirish 	 */
325244961713Sgirish 	if (bmsr.bits.extend_status) {
325344961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3254adfcba55Sjoycey #if defined(__i386)
3255adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
3256adfcba55Sjoycey #else
325744961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
3258adfcba55Sjoycey #endif
325944961713Sgirish 				!= NXGE_OK)
326044961713Sgirish 			goto fail;
326144961713Sgirish 		param_arr[param_anar_1000fdx].value &=
326244961713Sgirish 					esr.bits.link_1000fdx;
326344961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
326444961713Sgirish 
326544961713Sgirish 		statsp->mac_stats.cap_1000fdx =
326644961713Sgirish 			(esr.bits.link_1000Xfdx ||
326744961713Sgirish 				esr.bits.link_1000fdx);
326844961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
326944961713Sgirish 	} else {
327044961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
327144961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
327244961713Sgirish 	}
327344961713Sgirish 
327444961713Sgirish 	/*
327544961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
327644961713Sgirish 	 */
327744961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
327844961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
327944961713Sgirish 
328044961713Sgirish 	/*
328144961713Sgirish 	 * Initialise the link statistics.
328244961713Sgirish 	 */
328344961713Sgirish 	statsp->mac_stats.link_T4 = 0;
328444961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
328544961713Sgirish 	statsp->mac_stats.link_pause = 0;
328644961713Sgirish 	statsp->mac_stats.link_speed = 0;
328744961713Sgirish 	statsp->mac_stats.link_duplex = 0;
328844961713Sgirish 	statsp->mac_stats.link_up = 0;
328944961713Sgirish 
329044961713Sgirish 	/*
329144961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
329244961713Sgirish 	 */
329344961713Sgirish 	bmcr.value = 0;
329444961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3295adfcba55Sjoycey #if defined(__i386)
3296adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3297adfcba55Sjoycey #else
329844961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3299adfcba55Sjoycey #endif
330044961713Sgirish 		goto fail;
330144961713Sgirish 
330244961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
330344961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
330444961713Sgirish 		bmcr.bits.loopback = 1;
330544961713Sgirish 		bmcr.bits.enable_autoneg = 0;
330644961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
330744961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
330844961713Sgirish 		bmcr.bits.duplex_mode = 1;
330944961713Sgirish 		param_arr[param_autoneg].value = 0;
331044961713Sgirish 	} else {
331144961713Sgirish 		bmcr.bits.loopback = 0;
331244961713Sgirish 	}
331344961713Sgirish 
331444961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
331544961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
331644961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
331744961713Sgirish 		param_arr[param_autoneg].value = 0;
331844961713Sgirish 		bcm5464r_aux.value = 0;
331944961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
332044961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
332144961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
332244961713Sgirish 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
332344961713Sgirish 				!= NXGE_OK)
332444961713Sgirish 			goto fail;
332544961713Sgirish 	}
332644961713Sgirish 
332744961713Sgirish 	if (param_arr[param_autoneg].value) {
332844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
332944961713Sgirish 				"Restarting Auto-negotiation."));
333044961713Sgirish 		/*
333144961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
333244961713Sgirish 		 */
333344961713Sgirish 		anar.value = 0;
333444961713Sgirish 		anar.bits.selector = 1;
333544961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
333644961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
333744961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
333844961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
333944961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
334044961713Sgirish 		anar.bits.cap_asmpause = 0;
334144961713Sgirish 		anar.bits.cap_pause = 0;
334244961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
334344961713Sgirish 			param_arr[param_anar_100fdx].value ||
334444961713Sgirish 			param_arr[param_anar_10fdx].value) {
334544961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
334644961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
334744961713Sgirish 		}
334844961713Sgirish 
334944961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3350adfcba55Sjoycey #if defined(__i386)
3351adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
3352adfcba55Sjoycey #else
335344961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
3354adfcba55Sjoycey #endif
335544961713Sgirish 				!= NXGE_OK)
335644961713Sgirish 			goto fail;
335744961713Sgirish 		if (bmsr.bits.extend_status) {
335844961713Sgirish 			gcr.value = 0;
335944961713Sgirish 			gcr.bits.ms_mode_en =
336044961713Sgirish 				param_arr[param_master_cfg_enable].value;
336144961713Sgirish 			gcr.bits.master =
336244961713Sgirish 				param_arr[param_master_cfg_value].value;
336344961713Sgirish 			gcr.bits.link_1000fdx =
336444961713Sgirish 				param_arr[param_anar_1000fdx].value;
336544961713Sgirish 			gcr.bits.link_1000hdx =
336644961713Sgirish 				param_arr[param_anar_1000hdx].value;
336744961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3368adfcba55Sjoycey #if defined(__i386)
3369adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
3370adfcba55Sjoycey #else
337144961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
3372adfcba55Sjoycey #endif
337344961713Sgirish 				!= NXGE_OK)
337444961713Sgirish 				goto fail;
337544961713Sgirish 		}
337644961713Sgirish 
337744961713Sgirish 		bmcr.bits.enable_autoneg = 1;
337844961713Sgirish 		bmcr.bits.restart_autoneg = 1;
337944961713Sgirish 
338044961713Sgirish 	} else {
338144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
338244961713Sgirish 		bmcr.bits.speed_1000_sel =
338344961713Sgirish 			param_arr[param_anar_1000fdx].value |
338444961713Sgirish 				param_arr[param_anar_1000hdx].value;
338544961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
338644961713Sgirish 			(param_arr[param_anar_100fdx].value |
338744961713Sgirish 				param_arr[param_anar_100hdx].value);
338844961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
338944961713Sgirish 			statsp->mac_stats.link_speed = 1000;
339044961713Sgirish 			gcr.value = 0;
339144961713Sgirish 			gcr.bits.ms_mode_en =
339244961713Sgirish 				param_arr[param_master_cfg_enable].value;
339344961713Sgirish 			gcr.bits.master =
339444961713Sgirish 				param_arr[param_master_cfg_value].value;
339544961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3396adfcba55Sjoycey #if defined(__i386)
3397adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
3398adfcba55Sjoycey #else
339944961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr),
3400adfcba55Sjoycey #endif
340144961713Sgirish 				gcr.value))
340244961713Sgirish 				!= NXGE_OK)
340344961713Sgirish 				goto fail;
340444961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
340544961713Sgirish 				bmcr.bits.duplex_mode = 1;
340644961713Sgirish 				statsp->mac_stats.link_duplex = 2;
340744961713Sgirish 			} else
340844961713Sgirish 				statsp->mac_stats.link_duplex = 1;
340944961713Sgirish 		} else if (bmcr.bits.speed_sel) {
341044961713Sgirish 			statsp->mac_stats.link_speed = 100;
341144961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
341244961713Sgirish 				bmcr.bits.duplex_mode = 1;
341344961713Sgirish 				statsp->mac_stats.link_duplex = 2;
341444961713Sgirish 			} else
341544961713Sgirish 				statsp->mac_stats.link_duplex = 1;
341644961713Sgirish 		} else {
341744961713Sgirish 			statsp->mac_stats.link_speed = 10;
341844961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
341944961713Sgirish 				bmcr.bits.duplex_mode = 1;
342044961713Sgirish 				statsp->mac_stats.link_duplex = 2;
342144961713Sgirish 			} else
342244961713Sgirish 				statsp->mac_stats.link_duplex = 1;
342344961713Sgirish 		}
342444961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
342544961713Sgirish 			statsp->mac_stats.link_asmpause =
342644961713Sgirish 						statsp->mac_stats.cap_asmpause;
342744961713Sgirish 			statsp->mac_stats.link_pause =
342844961713Sgirish 						statsp->mac_stats.cap_pause;
342944961713Sgirish 		}
343044961713Sgirish 
343144961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
343244961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
343344961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
343444961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
343544961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
343644961713Sgirish 				gcr.value = 0;
343744961713Sgirish 				gcr.bits.ms_mode_en = 1;
343844961713Sgirish 				gcr.bits.master = 1;
343944961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
3440adfcba55Sjoycey #if defined(__i386)
3441adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
3442adfcba55Sjoycey #else
344344961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gcr),
3444adfcba55Sjoycey #endif
344544961713Sgirish 					gcr.value))
344644961713Sgirish 					!= NXGE_OK)
344744961713Sgirish 					goto fail;
344844961713Sgirish 				bmcr.value = 0;
344944961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
345044961713Sgirish 				statsp->mac_stats.link_speed = 1000;
345144961713Sgirish 			} else if (statsp->port_stats.lb_mode
345244961713Sgirish 			    == nxge_lb_ext100) {
345344961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
345444961713Sgirish 				bmcr.value = 0;
345544961713Sgirish 				bmcr.bits.speed_sel = 1;
345644961713Sgirish 				bmcr.bits.duplex_mode = 1;
345744961713Sgirish 				statsp->mac_stats.link_speed = 100;
345844961713Sgirish 			} else if (statsp->port_stats.lb_mode
345944961713Sgirish 			    == nxge_lb_ext10) {
346044961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
346144961713Sgirish 				bmcr.value = 0;
346244961713Sgirish 				bmcr.bits.duplex_mode = 1;
346344961713Sgirish 				statsp->mac_stats.link_speed = 10;
346444961713Sgirish 			}
346544961713Sgirish 		}
346644961713Sgirish 	}
346744961713Sgirish 
346844961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3469adfcba55Sjoycey #if defined(__i386)
3470adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
3471adfcba55Sjoycey #else
347244961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
3473adfcba55Sjoycey #endif
347444961713Sgirish 			bmcr.value)) != NXGE_OK)
347544961713Sgirish 		goto fail;
347644961713Sgirish 
347744961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3478adfcba55Sjoycey #if defined(__i386)
3479adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3480adfcba55Sjoycey #else
348144961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3482adfcba55Sjoycey #endif
348344961713Sgirish 		goto fail;
348444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
348544961713Sgirish 
348644961713Sgirish 	/*
348744961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
348844961713Sgirish 	 */
348944961713Sgirish 	nxgep->soft_bmsr.value = 0;
349044961713Sgirish 
349144961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3492adfcba55Sjoycey #if defined(__i386)
3493adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
3494adfcba55Sjoycey #else
349544961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
3496adfcba55Sjoycey #endif
349744961713Sgirish 			&nxgep->bmsr.value)) != NXGE_OK)
349844961713Sgirish 		goto fail;
349944961713Sgirish 
350044961713Sgirish 	statsp->mac_stats.xcvr_inits++;
350144961713Sgirish 	nxgep->bmsr.value = 0;
350244961713Sgirish 
350344961713Sgirish fail:
350444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
350544961713Sgirish 			"<== nxge_mii_xcvr_init status 0x%x", status));
350644961713Sgirish 	return (status);
350744961713Sgirish }
350844961713Sgirish 
3509d81011f0Ssbehera nxge_status_t
3510d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
3511d81011f0Ssbehera {
3512d81011f0Ssbehera 	p_nxge_param_t	param_arr;
3513d81011f0Ssbehera 	p_nxge_stats_t	statsp;
3514d81011f0Ssbehera 	uint8_t		xcvr_portn;
3515d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
3516d81011f0Ssbehera 	mii_bmcr_t	bmcr;
3517d81011f0Ssbehera 	mii_bmsr_t	bmsr;
3518d81011f0Ssbehera 	mii_gcr_t	gcr;
3519d81011f0Ssbehera 	mii_esr_t	esr;
3520d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
3521d81011f0Ssbehera 	int		status = NXGE_OK;
3522d81011f0Ssbehera 
3523d81011f0Ssbehera 	uint_t delay;
3524d81011f0Ssbehera 
3525d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
3526d81011f0Ssbehera 
3527d81011f0Ssbehera 	param_arr = nxgep->param_arr;
3528d81011f0Ssbehera 	statsp = nxgep->statsp;
3529d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3530d81011f0Ssbehera 
3531d81011f0Ssbehera 	mii_regs = NULL;
3532d81011f0Ssbehera 
3533d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3534d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
3535d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3536d81011f0Ssbehera 
3537d81011f0Ssbehera 	/*
3538d81011f0Ssbehera 	 * Reset the transceiver.
3539d81011f0Ssbehera 	 */
3540d81011f0Ssbehera 	delay = 0;
3541d81011f0Ssbehera 	bmcr.value = 0;
3542d81011f0Ssbehera 	bmcr.bits.reset = 1;
3543d81011f0Ssbehera 
3544d81011f0Ssbehera #if defined(__i386)
3545d81011f0Ssbehera 
3546d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3547d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3548d81011f0Ssbehera 		goto fail;
3549d81011f0Ssbehera #else
3550d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3551d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3552d81011f0Ssbehera 		goto fail;
3553d81011f0Ssbehera #endif
3554d81011f0Ssbehera 	do {
3555d81011f0Ssbehera 		drv_usecwait(500);
3556d81011f0Ssbehera #if defined(__i386)
3557d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3558d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
3559d81011f0Ssbehera 		    != NXGE_OK)
3560d81011f0Ssbehera 			goto fail;
3561d81011f0Ssbehera #else
3562d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3563d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
3564d81011f0Ssbehera 		    != NXGE_OK)
3565d81011f0Ssbehera 			goto fail;
3566d81011f0Ssbehera #endif
3567d81011f0Ssbehera 		delay++;
3568d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
3569d81011f0Ssbehera 	if (delay == 1000) {
3570d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
3571d81011f0Ssbehera 		goto fail;
3572d81011f0Ssbehera 	}
3573d81011f0Ssbehera 
3574d81011f0Ssbehera #if defined(__i386)
3575d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3576d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3577d81011f0Ssbehera 		goto fail;
3578d81011f0Ssbehera #else
3579d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3580d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3581d81011f0Ssbehera 		goto fail;
3582d81011f0Ssbehera #endif
3583d81011f0Ssbehera 
3584d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
3585d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
3586d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
3587d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
3588d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
3589d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
3590d81011f0Ssbehera 
3591d81011f0Ssbehera 	/*
3592d81011f0Ssbehera 	 * Initialize the xcvr statistics.
3593d81011f0Ssbehera 	 */
3594d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
3595d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
3596d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
3597d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
3598d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
3599d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
3600d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
3601d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3602d81011f0Ssbehera 
3603d81011f0Ssbehera 	/*
3604d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
3605d81011f0Ssbehera 	 */
3606d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
3607d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3608d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3609d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
3610d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
3611d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
3612d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
3613d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
3614d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
3615d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
3616d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3617d81011f0Ssbehera 
3618d81011f0Ssbehera 	/*
3619d81011f0Ssbehera 	 * Check for extended status just in case we're
3620d81011f0Ssbehera 	 * running a Gigibit phy.
3621d81011f0Ssbehera 	 */
3622d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
3623d81011f0Ssbehera #if defined(__i386)
3624d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3625d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
3626d81011f0Ssbehera 		    NXGE_OK)
3627d81011f0Ssbehera 			goto fail;
3628d81011f0Ssbehera #else
3629d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3630d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
3631d81011f0Ssbehera 		    NXGE_OK)
3632d81011f0Ssbehera 			goto fail;
3633d81011f0Ssbehera #endif
3634d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
3635d81011f0Ssbehera 		    esr.bits.link_1000fdx;
3636d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
3637d81011f0Ssbehera 
3638d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
3639d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
3640d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
3641d81011f0Ssbehera 	} else {
3642d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
3643d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
3644d81011f0Ssbehera 	}
3645d81011f0Ssbehera 
3646d81011f0Ssbehera 	/*
3647d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
3648d81011f0Ssbehera 	 */
3649d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3650d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3651d81011f0Ssbehera 
3652d81011f0Ssbehera 	/*
3653d81011f0Ssbehera 	 * Initialize the link statistics.
3654d81011f0Ssbehera 	 */
3655d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
3656d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
3657d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
3658d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
3659d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
3660d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
3661d81011f0Ssbehera 
3662d81011f0Ssbehera 	/*
3663d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
3664d81011f0Ssbehera 	 */
3665d81011f0Ssbehera 	bmcr.value = 0;
3666d81011f0Ssbehera #if defined(__i386)
3667d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3668d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3669d81011f0Ssbehera 		goto fail;
3670d81011f0Ssbehera #else
3671d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3672d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3673d81011f0Ssbehera 		goto fail;
3674d81011f0Ssbehera #endif
3675d81011f0Ssbehera 
3676d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
3677d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
3678d81011f0Ssbehera 		bmcr.bits.loopback = 1;
3679d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
3680d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
3681d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
3682d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
3683d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
3684d81011f0Ssbehera 	} else {
3685d81011f0Ssbehera 		bmcr.bits.loopback = 0;
3686d81011f0Ssbehera 	}
3687d81011f0Ssbehera 
3688d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
3689d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
3690d81011f0Ssbehera 		bcm5464r_aux.value = 0;
3691d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
3692d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
3693d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3694d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
3695d81011f0Ssbehera 			goto fail;
3696d81011f0Ssbehera 	}
3697d81011f0Ssbehera 
3698d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
3699d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
3700d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
3701d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
3702d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
3703d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
3704d81011f0Ssbehera 
3705d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
3706d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
3707d81011f0Ssbehera 		gcr.value = 0;
3708d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
3709d81011f0Ssbehera 		gcr.bits.master = 1;
3710d81011f0Ssbehera #if defined(__i386)
3711d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3712d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
3713d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
3714d81011f0Ssbehera 			goto fail;
3715d81011f0Ssbehera #else
3716d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3717d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
3718d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
3719d81011f0Ssbehera 			goto fail;
3720d81011f0Ssbehera #endif
3721d81011f0Ssbehera 		bmcr.value = 0;
3722d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
3723d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
3724d81011f0Ssbehera 	}
3725d81011f0Ssbehera 
3726d81011f0Ssbehera #if defined(__i386)
3727d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3728d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3729d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
3730d81011f0Ssbehera 		goto fail;
3731d81011f0Ssbehera #else
3732d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3733d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3734d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
3735d81011f0Ssbehera 		goto fail;
3736d81011f0Ssbehera #endif
3737d81011f0Ssbehera 
3738d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3739d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
3740d81011f0Ssbehera 	    bmcr.value));
3741d81011f0Ssbehera 
3742d81011f0Ssbehera #if defined(__i386)
3743d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3744d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3745d81011f0Ssbehera 		goto fail;
3746d81011f0Ssbehera #else
3747d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3748d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3749d81011f0Ssbehera 		goto fail;
3750d81011f0Ssbehera #endif
3751d81011f0Ssbehera 
3752d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3753d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
3754d81011f0Ssbehera 
3755d81011f0Ssbehera 	/*
3756d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
3757d81011f0Ssbehera 	 */
3758d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
3759d81011f0Ssbehera #if defined(__i386)
3760d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3761d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3762d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
3763d81011f0Ssbehera 		goto fail;
3764d81011f0Ssbehera #else
3765d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3766d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3767d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
3768d81011f0Ssbehera 		goto fail;
3769d81011f0Ssbehera #endif
3770d81011f0Ssbehera 
3771d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
3772d81011f0Ssbehera 	nxgep->bmsr.value = 0;
3773d81011f0Ssbehera 
3774d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3775d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3776d81011f0Ssbehera 	return (status);
3777d81011f0Ssbehera 
3778d81011f0Ssbehera fail:
3779d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3780d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3781d81011f0Ssbehera 	return (status);
3782d81011f0Ssbehera }
3783d81011f0Ssbehera 
378444961713Sgirish /* Read from a MII compliant register */
378544961713Sgirish 
378644961713Sgirish nxge_status_t
378744961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
378844961713Sgirish 		uint16_t *value)
378944961713Sgirish {
379044961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
379144961713Sgirish 
379244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
379344961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
379444961713Sgirish 
3795321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
379644961713Sgirish 
3797d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3798d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
379944961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
380044961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
380144961713Sgirish 			goto fail;
38022e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
38032e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
380444961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
380544961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
380644961713Sgirish 			goto fail;
380744961713Sgirish 	} else
380844961713Sgirish 		goto fail;
380944961713Sgirish 
3810321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
381144961713Sgirish 
381244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
381344961713Sgirish 			"xcvr_reg<%d> value=0x%x",
381444961713Sgirish 			xcvr_portn, xcvr_reg, *value));
381544961713Sgirish 	return (NXGE_OK);
381644961713Sgirish fail:
3817321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
381844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
381944961713Sgirish 			"nxge_mii_read: Failed to read mii on xcvr %d",
382044961713Sgirish 			xcvr_portn));
382144961713Sgirish 
382244961713Sgirish 	return (NXGE_ERROR | rs);
382344961713Sgirish }
382444961713Sgirish 
382544961713Sgirish /* Write to a MII compliant Register */
382644961713Sgirish 
382744961713Sgirish nxge_status_t
382844961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
382944961713Sgirish 		uint16_t value)
383044961713Sgirish {
383144961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
383244961713Sgirish 
383344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
383444961713Sgirish 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
383544961713Sgirish 			value));
383644961713Sgirish 
3837321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
383844961713Sgirish 
3839d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3840d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
384144961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
384244961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
384344961713Sgirish 			goto fail;
38442e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
38452e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
384644961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
384744961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
384844961713Sgirish 			goto fail;
384944961713Sgirish 	} else
385044961713Sgirish 		goto fail;
385144961713Sgirish 
3852321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
385344961713Sgirish 
385444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
385544961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
385644961713Sgirish 	return (NXGE_OK);
385744961713Sgirish fail:
3858321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
385944961713Sgirish 
386044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
386144961713Sgirish 			"nxge_mii_write: Failed to write mii on xcvr %d",
386244961713Sgirish 			xcvr_portn));
386344961713Sgirish 
386444961713Sgirish 	return (NXGE_ERROR | rs);
386544961713Sgirish }
386644961713Sgirish 
386744961713Sgirish /* Perform read from Clause45 serdes / transceiver device */
386844961713Sgirish 
386944961713Sgirish nxge_status_t
387044961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
387144961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
387244961713Sgirish {
387344961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
387444961713Sgirish 
387544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
387644961713Sgirish 			xcvr_portn));
387744961713Sgirish 
387853560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
387944961713Sgirish 
388044961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
388144961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
388244961713Sgirish 		goto fail;
388344961713Sgirish 
388453560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
388544961713Sgirish 
388644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
388744961713Sgirish 			xcvr_portn));
388844961713Sgirish 	return (NXGE_OK);
388944961713Sgirish fail:
389053560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
389144961713Sgirish 
389244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
389344961713Sgirish 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
389444961713Sgirish 			xcvr_portn));
389544961713Sgirish 
389644961713Sgirish 	return (NXGE_ERROR | rs);
389744961713Sgirish }
389844961713Sgirish 
389944961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
390044961713Sgirish 
390144961713Sgirish nxge_status_t
390244961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
390344961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
390444961713Sgirish {
390544961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
390644961713Sgirish 
390744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
390844961713Sgirish 			xcvr_portn));
390944961713Sgirish 
391053560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
391144961713Sgirish 
391244961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
391344961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
391444961713Sgirish 		goto fail;
391544961713Sgirish 
391653560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
391744961713Sgirish 
391844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
391944961713Sgirish 			xcvr_portn));
392044961713Sgirish 	return (NXGE_OK);
392144961713Sgirish fail:
392253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
392344961713Sgirish 
392444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
392544961713Sgirish 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
392644961713Sgirish 			xcvr_portn));
392744961713Sgirish 
392844961713Sgirish 	return (NXGE_ERROR | rs);
392944961713Sgirish }
393044961713Sgirish 
393144961713Sgirish 
393244961713Sgirish /* Check MII to see if there is any link status change */
393344961713Sgirish 
393444961713Sgirish nxge_status_t
3935a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
3936a3c5bd6dSspeer 		nxge_link_state_t *link_up)
393744961713Sgirish {
393844961713Sgirish 	p_nxge_param_t	param_arr;
393944961713Sgirish 	p_nxge_stats_t	statsp;
394044961713Sgirish 	p_mii_regs_t	mii_regs;
394144961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
394244961713Sgirish 	mii_anar_t	anar;
394344961713Sgirish 	mii_anlpar_t	anlpar;
394444961713Sgirish 	mii_anar_t	an_common;
394544961713Sgirish 	mii_aner_t	aner;
394644961713Sgirish 	mii_gsr_t	gsr;
394744961713Sgirish 	nxge_status_t	status = NXGE_OK;
394844961713Sgirish 
394944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
395044961713Sgirish 
395144961713Sgirish 	mii_regs = NULL;
395244961713Sgirish 	param_arr = nxgep->param_arr;
395344961713Sgirish 	statsp = nxgep->statsp;
395444961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
3955a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
395644961713Sgirish 
3957d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3958d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
3959d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
3960d81011f0Ssbehera 
396144961713Sgirish 	if (bmsr_ints.bits.link_status) {
3962d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3963d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
3964d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
396544961713Sgirish 		if (bmsr.bits.link_status) {
396644961713Sgirish 			soft_bmsr->bits.link_status = 1;
3967d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3968d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
3969d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
397044961713Sgirish 		} else {
397144961713Sgirish 			statsp->mac_stats.link_up = 0;
397244961713Sgirish 			soft_bmsr->bits.link_status = 0;
397344961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
397444961713Sgirish 					"Link down cable problem"));
3975a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
397644961713Sgirish 		}
397744961713Sgirish 	}
397844961713Sgirish 
3979d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
3980d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
398144961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
398244961713Sgirish 			if (bmsr.bits.auto_neg_complete)
398344961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
398444961713Sgirish 			else
398544961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
398644961713Sgirish 		}
398744961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
398844961713Sgirish 			statsp->mac_stats.link_T4 = 0;
398944961713Sgirish 			statsp->mac_stats.link_speed = 0;
399044961713Sgirish 			statsp->mac_stats.link_duplex = 0;
399144961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
399244961713Sgirish 			statsp->mac_stats.link_pause = 0;
399344961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
399444961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
399544961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
399644961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
399744961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
399844961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
399944961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
400044961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
400144961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
400244961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
400344961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
400444961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
400544961713Sgirish 		}
400644961713Sgirish 	} else
400744961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
400844961713Sgirish 
400944961713Sgirish 	if ((bmsr_ints.bits.link_status ||
401044961713Sgirish 		bmsr_ints.bits.auto_neg_complete) &&
401144961713Sgirish 		soft_bmsr->bits.link_status &&
401244961713Sgirish 		soft_bmsr->bits.auto_neg_complete) {
401344961713Sgirish 		statsp->mac_stats.link_up = 1;
4014d81011f0Ssbehera 
4015d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4016d81011f0Ssbehera 		    "==> nxge_mii_check "
4017d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
4018d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
4019d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
4020d81011f0Ssbehera 
4021d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4022d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
402344961713Sgirish 			if ((status = nxge_mii_read(nxgep,
402444961713Sgirish 				statsp->mac_stats.xcvr_portn,
4025adfcba55Sjoycey #if defined(__i386)
4026adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
4027adfcba55Sjoycey #else
402844961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anar),
4029adfcba55Sjoycey #endif
403044961713Sgirish 					&anar.value)) != NXGE_OK)
403144961713Sgirish 				goto fail;
403244961713Sgirish 			if ((status = nxge_mii_read(nxgep,
403344961713Sgirish 				statsp->mac_stats.xcvr_portn,
4034adfcba55Sjoycey #if defined(__i386)
4035adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4036adfcba55Sjoycey #else
403744961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4038adfcba55Sjoycey #endif
403944961713Sgirish 					&anlpar.value)) != NXGE_OK)
404044961713Sgirish 				goto fail;
404144961713Sgirish 			if ((status = nxge_mii_read(nxgep,
404244961713Sgirish 				statsp->mac_stats.xcvr_portn,
4043adfcba55Sjoycey #if defined(__i386)
4044adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
4045adfcba55Sjoycey #else
404644961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->aner),
4047adfcba55Sjoycey #endif
404844961713Sgirish 					&aner.value)) != NXGE_OK)
404944961713Sgirish 				goto fail;
405044961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
405144961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
405244961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
405344961713Sgirish 							anlpar.bits.cap_100fdx;
405444961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
405544961713Sgirish 							anlpar.bits.cap_100hdx;
405644961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
405744961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
405844961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
405944961713Sgirish 						anlpar.bits.cap_asmpause;
406044961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
406144961713Sgirish 			an_common.value = anar.value & anlpar.value;
406244961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
406344961713Sgirish 				param_arr[param_anar_1000hdx].value) {
406444961713Sgirish 				if ((status = nxge_mii_read(nxgep,
406544961713Sgirish 					statsp->mac_stats.xcvr_portn,
4066adfcba55Sjoycey #if defined(__i386)
4067adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
4068adfcba55Sjoycey #else
406944961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gsr),
4070adfcba55Sjoycey #endif
407144961713Sgirish 						&gsr.value))
407244961713Sgirish 						!= NXGE_OK)
407344961713Sgirish 					goto fail;
407444961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
407544961713Sgirish 					gsr.bits.link_1000fdx;
407644961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
407744961713Sgirish 					gsr.bits.link_1000hdx;
407844961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
407944961713Sgirish 					gsr.bits.link_1000fdx) {
408044961713Sgirish 					statsp->mac_stats.link_speed = 1000;
408144961713Sgirish 					statsp->mac_stats.link_duplex = 2;
408244961713Sgirish 				} else if (
408344961713Sgirish 					param_arr[param_anar_1000hdx].value &&
408444961713Sgirish 						gsr.bits.link_1000hdx) {
408544961713Sgirish 					statsp->mac_stats.link_speed = 1000;
408644961713Sgirish 					statsp->mac_stats.link_duplex = 1;
408744961713Sgirish 				}
408844961713Sgirish 			}
408944961713Sgirish 			if ((an_common.value != 0) &&
409044961713Sgirish 					!(statsp->mac_stats.link_speed)) {
409144961713Sgirish 				if (an_common.bits.cap_100T4) {
409244961713Sgirish 					statsp->mac_stats.link_T4 = 1;
409344961713Sgirish 					statsp->mac_stats.link_speed = 100;
409444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
409544961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
409644961713Sgirish 					statsp->mac_stats.link_speed = 100;
409744961713Sgirish 					statsp->mac_stats.link_duplex = 2;
409844961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
409944961713Sgirish 					statsp->mac_stats.link_speed = 100;
410044961713Sgirish 					statsp->mac_stats.link_duplex = 1;
410144961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
410244961713Sgirish 					statsp->mac_stats.link_speed = 10;
410344961713Sgirish 					statsp->mac_stats.link_duplex = 2;
410444961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
410544961713Sgirish 					statsp->mac_stats.link_speed = 10;
410644961713Sgirish 					statsp->mac_stats.link_duplex = 1;
410744961713Sgirish 				} else {
410844961713Sgirish 					goto fail;
410944961713Sgirish 				}
411044961713Sgirish 			}
411144961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
411244961713Sgirish 				statsp->mac_stats.link_asmpause =
411344961713Sgirish 					an_common.bits.cap_asmpause;
411444961713Sgirish 				if (statsp->mac_stats.link_asmpause)
411544961713Sgirish 				if ((statsp->mac_stats.cap_pause == 0) &&
411644961713Sgirish 						(statsp->mac_stats.lp_cap_pause
411744961713Sgirish 						== 1))
411844961713Sgirish 						statsp->mac_stats.link_pause
411944961713Sgirish 						= 0;
412044961713Sgirish 					else
412144961713Sgirish 						statsp->mac_stats.link_pause
412244961713Sgirish 						= 1;
412344961713Sgirish 				else
412444961713Sgirish 					statsp->mac_stats.link_pause =
412544961713Sgirish 						an_common.bits.cap_pause;
412644961713Sgirish 			}
4127d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4128d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
4129d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
413044961713Sgirish 		}
4131a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
4132a3c5bd6dSspeer 	}
4133a3c5bd6dSspeer 
4134a3c5bd6dSspeer 	if (nxgep->link_notify) {
4135a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
4136a3c5bd6dSspeer 				LINK_IS_DOWN);
4137a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
413844961713Sgirish 	}
413944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
414044961713Sgirish 	return (NXGE_OK);
414144961713Sgirish fail:
414244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
414344961713Sgirish 			"nxge_mii_check: Unable to check MII"));
414444961713Sgirish 	return (status);
414544961713Sgirish }
414644961713Sgirish 
41472e59129aSraghus /* Check PCS to see if there is any link status change */
41482e59129aSraghus nxge_status_t
41492e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
41502e59129aSraghus {
41512e59129aSraghus 	p_nxge_stats_t	statsp;
41522e59129aSraghus 	nxge_status_t	status = NXGE_OK;
41532e59129aSraghus 	boolean_t	linkup;
41542e59129aSraghus 
41552e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
41562e59129aSraghus 
41572e59129aSraghus 	statsp = nxgep->statsp;
41582e59129aSraghus 	*link_up = LINK_NO_CHANGE;
41592e59129aSraghus 
41602e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
41612e59129aSraghus 	if (linkup) {
41622e59129aSraghus 		if (nxgep->link_notify ||
41632e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
41642e59129aSraghus 			statsp->mac_stats.link_up = 1;
41652e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
41662e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
41672e59129aSraghus 			*link_up = LINK_IS_UP;
41682e59129aSraghus 			nxgep->link_notify = B_FALSE;
41692e59129aSraghus 		}
41702e59129aSraghus 	} else {
41712e59129aSraghus 		if (nxgep->link_notify ||
41722e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
41732e59129aSraghus 			statsp->mac_stats.link_up = 0;
41742e59129aSraghus 			statsp->mac_stats.link_speed = 0;
41752e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
41762e59129aSraghus 			*link_up = LINK_IS_DOWN;
41772e59129aSraghus 			nxgep->link_notify = B_FALSE;
41782e59129aSraghus 		}
41792e59129aSraghus 	}
41802e59129aSraghus 
41812e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
41822e59129aSraghus 	return (NXGE_OK);
41832e59129aSraghus fail:
41842e59129aSraghus 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
41852e59129aSraghus 	    "nxge_pcs_check: Unable to check PCS"));
41862e59129aSraghus 	return (status);
41872e59129aSraghus }
41882e59129aSraghus 
418944961713Sgirish /* Add a multicast address entry into the HW hash table */
419044961713Sgirish 
419144961713Sgirish nxge_status_t
419244961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
419344961713Sgirish {
419444961713Sgirish 	uint32_t mchash;
419544961713Sgirish 	p_hash_filter_t hash_filter;
419644961713Sgirish 	uint16_t hash_bit;
419744961713Sgirish 	boolean_t rx_init = B_FALSE;
419844961713Sgirish 	uint_t j;
419944961713Sgirish 	nxge_status_t status = NXGE_OK;
420044961713Sgirish 
420144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
420244961713Sgirish 
420344961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
420444961713Sgirish 	mchash = crc32_mchash(addrp);
420544961713Sgirish 	if (nxgep->hash_filter == NULL) {
420644961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
420744961713Sgirish 			"Allocating hash filter storage."));
420844961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
420944961713Sgirish 					KM_SLEEP);
421044961713Sgirish 	}
421144961713Sgirish 	hash_filter = nxgep->hash_filter;
421244961713Sgirish 	j = mchash / HASH_REG_WIDTH;
421344961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
421444961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
421544961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
421644961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
421744961713Sgirish 		hash_filter->hash_ref_cnt++;
421844961713Sgirish 		rx_init = B_TRUE;
421944961713Sgirish 	}
422044961713Sgirish 	if (rx_init) {
422144961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
422244961713Sgirish 			goto fail;
422344961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
422444961713Sgirish 			goto fail;
422544961713Sgirish 	}
422644961713Sgirish 
422744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
422844961713Sgirish 
422944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
423044961713Sgirish 
423144961713Sgirish 	return (NXGE_OK);
423244961713Sgirish fail:
423344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
423444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
423544961713Sgirish 					"Unable to add multicast address"));
423644961713Sgirish 	return (status);
423744961713Sgirish }
423844961713Sgirish 
423944961713Sgirish /* Remove a multicast address entry from the HW hash table */
424044961713Sgirish 
424144961713Sgirish nxge_status_t
424244961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
424344961713Sgirish {
424444961713Sgirish 	uint32_t mchash;
424544961713Sgirish 	p_hash_filter_t hash_filter;
424644961713Sgirish 	uint16_t hash_bit;
424744961713Sgirish 	boolean_t rx_init = B_FALSE;
424844961713Sgirish 	uint_t j;
424944961713Sgirish 	nxge_status_t status = NXGE_OK;
425044961713Sgirish 
425144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
425244961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
425344961713Sgirish 	mchash = crc32_mchash(addrp);
425444961713Sgirish 	if (nxgep->hash_filter == NULL) {
425544961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
425644961713Sgirish 			"Hash filter already de_allocated."));
425744961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
425844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
425944961713Sgirish 		return (NXGE_OK);
426044961713Sgirish 	}
426144961713Sgirish 	hash_filter = nxgep->hash_filter;
426244961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
426344961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
426444961713Sgirish 		j = mchash / HASH_REG_WIDTH;
426544961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
426644961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
426744961713Sgirish 		hash_filter->hash_ref_cnt--;
426844961713Sgirish 		rx_init = B_TRUE;
426944961713Sgirish 	}
427044961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
427144961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
427244961713Sgirish 			"De-allocating hash filter storage."));
427344961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
427444961713Sgirish 		nxgep->hash_filter = NULL;
427544961713Sgirish 	}
427644961713Sgirish 
427744961713Sgirish 	if (rx_init) {
427844961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
427944961713Sgirish 			goto fail;
428044961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
428144961713Sgirish 			goto fail;
428244961713Sgirish 	}
428344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
428444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
428544961713Sgirish 
428644961713Sgirish 	return (NXGE_OK);
428744961713Sgirish fail:
428844961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
428944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
429044961713Sgirish 			"Unable to remove multicast address"));
429144961713Sgirish 
429244961713Sgirish 	return (status);
429344961713Sgirish }
429444961713Sgirish 
429544961713Sgirish /* Set MAC address into MAC address HW registers */
429644961713Sgirish 
429744961713Sgirish nxge_status_t
429844961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
429944961713Sgirish {
430044961713Sgirish 	nxge_status_t status = NXGE_OK;
430144961713Sgirish 
430244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
430344961713Sgirish 
430444961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
430544961713Sgirish 	/*
430644961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
430744961713Sgirish 	 */
430844961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
430944961713Sgirish 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
431044961713Sgirish 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
431144961713Sgirish 		goto nxge_set_mac_addr_exit;
431244961713Sgirish 	}
431344961713Sgirish 	nxgep->ouraddr = *addrp;
431444961713Sgirish 	/*
431544961713Sgirish 	 * Set new interface local address and re-init device.
431644961713Sgirish 	 * This is destructive to any other streams attached
431744961713Sgirish 	 * to this device.
431844961713Sgirish 	 */
431944961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
432044961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
432144961713Sgirish 		goto fail;
432244961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
432344961713Sgirish 		goto fail;
432444961713Sgirish 
432544961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
432644961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
432744961713Sgirish 	goto nxge_set_mac_addr_end;
432844961713Sgirish nxge_set_mac_addr_exit:
432944961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
433044961713Sgirish nxge_set_mac_addr_end:
433144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
433244961713Sgirish 
433344961713Sgirish 	return (NXGE_OK);
433444961713Sgirish fail:
433544961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
433644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
433744961713Sgirish 			"Unable to set mac address"));
433844961713Sgirish 	return (status);
433944961713Sgirish }
434044961713Sgirish 
434198ecde52Stm static
434298ecde52Stm check_link_state_t
434398ecde52Stm nxge_check_link_stop(
434498ecde52Stm 	nxge_t *nxge)
434598ecde52Stm {
434698ecde52Stm 	/* If the poll has been cancelled, return STOP. */
434798ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
434898ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
434998ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
435098ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
435198ecde52Stm 		cv_broadcast(&nxge->poll_cv);
435298ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
435398ecde52Stm 
435498ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
435598ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
435698ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
435798ecde52Stm 		    nxge->mac.portnum));
435898ecde52Stm 		return (CHECK_LINK_STOP);
435998ecde52Stm 	}
436098ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
436198ecde52Stm 
436298ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
436398ecde52Stm }
436498ecde52Stm 
436544961713Sgirish /* Check status of MII (MIF or PCS) link */
436644961713Sgirish 
436759ac0c16Sdavemq static nxge_status_t
436844961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
436944961713Sgirish {
437044961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
437144961713Sgirish 	mii_anlpar_t anlpar;
437244961713Sgirish 	mii_gsr_t gsr;
437344961713Sgirish 	p_mii_regs_t mii_regs;
437444961713Sgirish 	nxge_status_t status = NXGE_OK;
437544961713Sgirish 	uint8_t portn;
4376a3c5bd6dSspeer 	nxge_link_state_t link_up;
437744961713Sgirish 
437898ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
437998ecde52Stm 		return (NXGE_ERROR);
438098ecde52Stm 
438198ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
438298ecde52Stm 		return (NXGE_OK);
438398ecde52Stm 
438444961713Sgirish 	portn = nxgep->mac.portnum;
438544961713Sgirish 
438644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
438798ecde52Stm 	    portn));
438844961713Sgirish 
438944961713Sgirish 	mii_regs = NULL;
439044961713Sgirish 
439144961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
439244961713Sgirish 
439344961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
439444961713Sgirish 		goto nxge_check_mii_link_exit;
439544961713Sgirish 
43962e59129aSraghus 	switch (nxgep->mac.portmode) {
43972e59129aSraghus 	default:
4398d81011f0Ssbehera 		bmsr_data.value = 0;
439944961713Sgirish 		if ((status = nxge_mii_read(nxgep,
44002e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
4401adfcba55Sjoycey #if defined(__i386)
4402adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4403adfcba55Sjoycey #else
44042e59129aSraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4405adfcba55Sjoycey #endif
44062e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
440744961713Sgirish 			goto fail;
440844961713Sgirish 		}
440944961713Sgirish 
4410d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4411d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
4412d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
44132d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
4414d81011f0Ssbehera 
44152e59129aSraghus 		if (nxgep->param_arr[param_autoneg].value) {
44162e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
44172e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
4418adfcba55Sjoycey #if defined(__i386)
4419adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
4420adfcba55Sjoycey #else
44212e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
4422adfcba55Sjoycey #endif
44232e59129aSraghus 				&gsr.value)) != NXGE_OK)
44242e59129aSraghus 				goto fail;
44252e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
44262e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
4427adfcba55Sjoycey #if defined(__i386)
4428adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4429adfcba55Sjoycey #else
44302e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4431adfcba55Sjoycey #endif
44322e59129aSraghus 				&anlpar.value)) != NXGE_OK)
44332e59129aSraghus 				goto fail;
4434d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
4435d81011f0Ssbehera 
4436d81011f0Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
4437d81011f0Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
4438d81011f0Ssbehera 				    gsr.bits.link_1000fdx) ||
4439d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
4440d81011f0Ssbehera 				    gsr.bits.link_1000hdx) ||
4441d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
4442d81011f0Ssbehera 				    anlpar.bits.cap_100T4) ||
4443d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
4444d81011f0Ssbehera 				    anlpar.bits.cap_100fdx) ||
4445d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
4446d81011f0Ssbehera 				    anlpar.bits.cap_100hdx) ||
4447d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
4448d81011f0Ssbehera 				    anlpar.bits.cap_10fdx) ||
4449d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
4450d81011f0Ssbehera 				    anlpar.bits.cap_10hdx))) {
4451d81011f0Ssbehera 					bmsr_data.bits.link_status = 0;
4452d81011f0Ssbehera 				}
44532e59129aSraghus 			}
44542e59129aSraghus 		}
445544961713Sgirish 
44562e59129aSraghus 		/* Workaround for link down issue */
44572e59129aSraghus 		if (bmsr_data.value == 0) {
44582e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
44592e59129aSraghus 			goto nxge_check_mii_link_exit;
44602e59129aSraghus 		}
44612e59129aSraghus 
4462d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4463d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
4464d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
44652d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
4466d81011f0Ssbehera 
44672e59129aSraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
44682e59129aSraghus 		nxgep->bmsr.value = bmsr_data.value;
4469d81011f0Ssbehera 
4470d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4471d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
4472d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
44732d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
4474d81011f0Ssbehera 
44752e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
44762e59129aSraghus 		    &link_up)) != NXGE_OK) {
44772e59129aSraghus 			goto fail;
44782e59129aSraghus 		}
44792e59129aSraghus 		break;
44802e59129aSraghus 
44812e59129aSraghus 	case PORT_1G_SERDES:
44822e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44832e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
44842e59129aSraghus 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
44852e59129aSraghus 		    != NXGE_OK) {
44862e59129aSraghus 			goto fail;
44872e59129aSraghus 		}
44882e59129aSraghus 		break;
44892e59129aSraghus 	}
449044961713Sgirish 
449144961713Sgirish nxge_check_mii_link_exit:
449244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
4493a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
4494a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
4495a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
4496a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
4497a3c5bd6dSspeer 	}
449844961713Sgirish 
449944961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
450044961713Sgirish 
450144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
45022e59129aSraghus 				portn));
450344961713Sgirish 	return (NXGE_OK);
450444961713Sgirish 
450544961713Sgirish fail:
450644961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
450744961713Sgirish 
450844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
450944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
45102e59129aSraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
45112e59129aSraghus 			portn));
451244961713Sgirish 	return (status);
451344961713Sgirish }
451444961713Sgirish 
451544961713Sgirish 
451644961713Sgirish /*ARGSUSED*/
451759ac0c16Sdavemq static nxge_status_t
451844961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
451944961713Sgirish {
452044961713Sgirish 	uint8_t		portn;
452144961713Sgirish 	nxge_status_t	status = NXGE_OK;
4522763fcc44Ssbehera 	boolean_t	link_up;
45232e59129aSraghus 	uint32_t	val;
45242e59129aSraghus 	npi_status_t	rs;
452544961713Sgirish 
452698ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
452798ecde52Stm 		return (NXGE_ERROR);
452898ecde52Stm 
452998ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
453098ecde52Stm 		return (NXGE_OK);
453198ecde52Stm 
453244961713Sgirish 	portn = nxgep->mac.portnum;
4533d81011f0Ssbehera 	val = 0;
4534d81011f0Ssbehera 	rs = NPI_SUCCESS;
453544961713Sgirish 
453644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
453798ecde52Stm 	    portn));
453844961713Sgirish 
45392e59129aSraghus 	switch (nxgep->mac.portmode) {
45402e59129aSraghus 	default:
45412d17280bSsbehera 		/*
45422d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
45432d17280bSsbehera 		 */
45442d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
45452d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
45462d17280bSsbehera 
45472d17280bSsbehera 			/*
45482d17280bSsbehera 			 * If this is the 2nd Goa port, then check 2 addresses
45492d17280bSsbehera 			 * to take care of the Goa NEM card requirements.
45502d17280bSsbehera 			 */
45512d17280bSsbehera 			if (portn == 1) {
45522d17280bSsbehera 				if (nxge_is_phy_present(nxgep,
45532d17280bSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR,
45542d17280bSsbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
45552d17280bSsbehera 					phy_present_now = B_TRUE;
45562d17280bSsbehera 					nxgep->xcvr_addr =
45572d17280bSsbehera 					    BCM8706_ALT_GOA_PORT1_ADDR;
45582d17280bSsbehera 					goto phy_check_done;
45592d17280bSsbehera 				}
45602d17280bSsbehera 			}
45612d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
45622d17280bSsbehera 			    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
45632d17280bSsbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
45642d17280bSsbehera 				nxgep->xcvr_addr =
45652d17280bSsbehera 				    (BCM8706_GOA_PORT_ADDR_BASE) + portn;
45662d17280bSsbehera 				phy_present_now = B_TRUE;
45672d17280bSsbehera 			}
45682d17280bSsbehera 
45692d17280bSsbehera phy_check_done:
45702d17280bSsbehera 			if (nxgep->phy_absent) {
45712d17280bSsbehera 				if (phy_present_now) {
45722d17280bSsbehera 				/*
45732d17280bSsbehera 				 * Detect, Initialize phy and do link up
45742d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
45752d17280bSsbehera 				 */
45762d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45772d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
45782d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
45792d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
45802d17280bSsbehera 					(void) nxge_link_init(nxgep);
45812d17280bSsbehera 					if (!(nxgep->drv_state &
45822d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
45832d17280bSsbehera 						status = nxge_init(nxgep);
45842d17280bSsbehera 						if (status != NXGE_OK) {
45852d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
45862d17280bSsbehera 							    NXGE_ERR_CTL,
45872d17280bSsbehera 							    "Hot swappable "
45882d17280bSsbehera 							    "phy present, but"
45892d17280bSsbehera 							    " driver init"
45902d17280bSsbehera 							    "  failed..."));
45912d17280bSsbehera 							goto fail;
45922d17280bSsbehera 						}
45932d17280bSsbehera 					}
45942d17280bSsbehera 				}
45952d17280bSsbehera 
45962d17280bSsbehera 				goto start_link_check;
45972d17280bSsbehera 
45982d17280bSsbehera 			} else if (!phy_present_now) {
45992d17280bSsbehera 				/*
46002d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
46012d17280bSsbehera 				 */
46022d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46032d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
46042d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
46052d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
46062d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
46072d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
46082d17280bSsbehera 				nxge_link_is_down(nxgep);
46092d17280bSsbehera 				nxgep->link_notify = B_FALSE;
46102d17280bSsbehera 
46112d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
46122d17280bSsbehera 
46132d17280bSsbehera 				goto start_link_check;
46142d17280bSsbehera 
46152d17280bSsbehera 			}
46162d17280bSsbehera 		}
46172d17280bSsbehera 
46182e59129aSraghus 		status = nxge_check_bcm8704_link(nxgep, &link_up);
46192e59129aSraghus 		if (status != NXGE_OK)
46202e59129aSraghus 			goto fail;
46212e59129aSraghus 		break;
46222e59129aSraghus 	case PORT_10G_SERDES:
46232e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4624763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
46252e59129aSraghus 		if (rs != 0)
46262e59129aSraghus 			goto fail;
46272e59129aSraghus 
46282e59129aSraghus 		link_up = B_FALSE;
4629763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
4630763fcc44Ssbehera 			link_up = B_TRUE;
46312e59129aSraghus 		}
46322e59129aSraghus 
46332e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46342e59129aSraghus 		    "==> nxge_check_10g_link port<%d> "
4635763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
4636763fcc44Ssbehera 		    portn, val, link_up));
46372e59129aSraghus 
46382e59129aSraghus 		break;
46392e59129aSraghus 	}
464044961713Sgirish 
464144961713Sgirish 	if (link_up) {
4642a3c5bd6dSspeer 		if (nxgep->link_notify ||
4643a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 0) {
464444961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
464544961713Sgirish 				goto fail;
464644961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
464744961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
464844961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
464944961713Sgirish 
465044961713Sgirish 			nxge_link_is_up(nxgep);
4651a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
465244961713Sgirish 		}
465344961713Sgirish 	} else {
4654a3c5bd6dSspeer 		if (nxgep->link_notify ||
4655a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 1) {
465644961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
465744961713Sgirish 				goto fail;
465844961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46592e59129aSraghus 					"Link down cable problem"));
466044961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
466144961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
466244961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
466344961713Sgirish 
466444961713Sgirish 			nxge_link_is_down(nxgep);
4665a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
466644961713Sgirish 		}
466744961713Sgirish 	}
466844961713Sgirish 
46692d17280bSsbehera start_link_check:
467044961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
467144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
467298ecde52Stm 	    portn));
467344961713Sgirish 	return (NXGE_OK);
467444961713Sgirish 
467544961713Sgirish fail:
467698ecde52Stm 	(void) nxge_check_link_stop(nxgep);
467798ecde52Stm 
467844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
467998ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
468098ecde52Stm 	    portn));
468144961713Sgirish 	return (status);
468244961713Sgirish }
468344961713Sgirish 
468444961713Sgirish 
468544961713Sgirish /* Declare link down */
468644961713Sgirish 
468744961713Sgirish void
468844961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
468944961713Sgirish {
469059ac0c16Sdavemq 	p_nxge_stats_t statsp;
469159ac0c16Sdavemq 	char link_stat_msg[64];
469259ac0c16Sdavemq 
469344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
469444961713Sgirish 
469559ac0c16Sdavemq 	statsp = nxgep->statsp;
469659ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
469759ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
469859ac0c16Sdavemq 
469959ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
470059ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
470159ac0c16Sdavemq 	}
470259ac0c16Sdavemq 
470344961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
470444961713Sgirish 
470544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
470644961713Sgirish }
470744961713Sgirish 
470844961713Sgirish /* Declare link up */
470944961713Sgirish 
471044961713Sgirish void
471144961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
471244961713Sgirish {
471359ac0c16Sdavemq 	p_nxge_stats_t statsp;
471459ac0c16Sdavemq 	char link_stat_msg[64];
471544961713Sgirish 	uint32_t val;
471644961713Sgirish 
471744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
471844961713Sgirish 
471959ac0c16Sdavemq 	statsp = nxgep->statsp;
472059ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
472159ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
472259ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
472359ac0c16Sdavemq 
472459ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
472559ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
472659ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
472759ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
472859ac0c16Sdavemq 	else
472959ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
473059ac0c16Sdavemq 
473144961713Sgirish 	(void) nxge_xif_init(nxgep);
473244961713Sgirish 
473344961713Sgirish 	/* Clean up symbol errors incurred during link transition */
47342e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
47352e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
473644961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
473744961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
473844961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
473944961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
474044961713Sgirish 	}
474144961713Sgirish 
474259ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
474359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
474459ac0c16Sdavemq 	}
474559ac0c16Sdavemq 
474644961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
474744961713Sgirish 
474844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
474944961713Sgirish }
475044961713Sgirish 
475144961713Sgirish /*
475244961713Sgirish  * Calculate the bit in the multicast address filter
475344961713Sgirish  * that selects the given * address.
475444961713Sgirish  * Note: For GEM, the last 8-bits are used.
475544961713Sgirish  */
475644961713Sgirish uint32_t
475744961713Sgirish crc32_mchash(p_ether_addr_t addr)
475844961713Sgirish {
475944961713Sgirish 	uint8_t *cp;
476044961713Sgirish 	uint32_t crc;
476144961713Sgirish 	uint32_t c;
476244961713Sgirish 	int byte;
476344961713Sgirish 	int bit;
476444961713Sgirish 
476544961713Sgirish 	cp = (uint8_t *)addr;
476644961713Sgirish 	crc = (uint32_t)0xffffffff;
476744961713Sgirish 	for (byte = 0; byte < 6; byte++) {
476844961713Sgirish 		c = (uint32_t)cp[byte];
476944961713Sgirish 		for (bit = 0; bit < 8; bit++) {
477044961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
477144961713Sgirish 				crc = (crc >> 1)^0xedb88320;
477244961713Sgirish 			else
477344961713Sgirish 				crc = (crc >> 1);
477444961713Sgirish 			c >>= 1;
477544961713Sgirish 		}
477644961713Sgirish 	}
477744961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
477844961713Sgirish }
477944961713Sgirish 
478044961713Sgirish /* Reset serdes */
478144961713Sgirish 
478244961713Sgirish nxge_status_t
478344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
478444961713Sgirish {
478544961713Sgirish 	npi_handle_t		handle;
478644961713Sgirish 
478744961713Sgirish 	handle = nxgep->npi_handle;
478844961713Sgirish 
478944961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
479044961713Sgirish 	drv_usecwait(500);
479144961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
479244961713Sgirish 
479344961713Sgirish 	return (NXGE_OK);
479444961713Sgirish }
479544961713Sgirish 
479644961713Sgirish /* Monitor link status using interrupt or polling */
479744961713Sgirish nxge_status_t
479844961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
479944961713Sgirish {
480044961713Sgirish 	nxge_status_t status = NXGE_OK;
480144961713Sgirish 
4802*678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
4803*678453a8Sspeer 	if (isLDOMguest(nxgep))
4804*678453a8Sspeer 		return (status);
4805*678453a8Sspeer 
480644961713Sgirish 	/*
480798ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
480898ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
480944961713Sgirish 	 */
48102e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
48112e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
48122e59129aSraghus 	    (nxgep->mac.portnum > 1))
481344961713Sgirish 		return (NXGE_OK);
481444961713Sgirish 
481544961713Sgirish 	if (nxgep->statsp == NULL) {
481644961713Sgirish 		/* stats has not been allocated. */
481744961713Sgirish 		return (NXGE_OK);
481844961713Sgirish 	}
4819321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
4820321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
482144961713Sgirish 		return (NXGE_OK);
482244961713Sgirish 
482344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
482498ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
482598ecde52Stm 	    nxgep->mac.portnum, enable));
482644961713Sgirish 	if (enable == LINK_MONITOR_START) {
482744961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
482844961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
482998ecde52Stm 			    != NXGE_OK)
483044961713Sgirish 				goto fail;
483144961713Sgirish 		} else {
483298ecde52Stm 			timeout_id_t timerid;
483398ecde52Stm 
483498ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
483598ecde52Stm 				return (NXGE_OK);
483698ecde52Stm 
483759ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
483859ac0c16Sdavemq 				timerid = timeout(
483959ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
484098ecde52Stm 				    nxgep,
484198ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
484259ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
484359ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
484459ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
484559ac0c16Sdavemq 			} else {
484698ecde52Stm 				return (NXGE_ERROR);
484744961713Sgirish 			}
484844961713Sgirish 		}
484944961713Sgirish 	} else {
485044961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
485144961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
485298ecde52Stm 			    != NXGE_OK)
485344961713Sgirish 				goto fail;
485444961713Sgirish 		} else {
485598ecde52Stm 			clock_t rv;
485698ecde52Stm 
485798ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
485898ecde52Stm 
485998ecde52Stm 			/* If <timerid> == 0, the link monitor has */
486098ecde52Stm 			/* never been started, or just now stopped. */
486198ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
486298ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
486398ecde52Stm 				return (NXGE_OK);
486498ecde52Stm 			}
486598ecde52Stm 
486698ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
486798ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
486898ecde52Stm 			    &nxgep->poll_lock,
486998ecde52Stm 			    ddi_get_lbolt() +
487098ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
487198ecde52Stm 			    LINK_MONITOR_PERIOD));
487298ecde52Stm 			if (rv == -1) {
487398ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
487498ecde52Stm 				    "==> stopping port %d: "
487598ecde52Stm 				    "cv_timedwait(%d) timed out",
487698ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
487798ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
487844961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
487944961713Sgirish 			}
488098ecde52Stm 
488198ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
488244961713Sgirish 		}
488344961713Sgirish 	}
488444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
488598ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
488698ecde52Stm 	    nxgep->mac.portnum, enable));
4887*678453a8Sspeer 
488844961713Sgirish 	return (NXGE_OK);
488944961713Sgirish fail:
489044961713Sgirish 	return (status);
489144961713Sgirish }
489244961713Sgirish 
489344961713Sgirish /* Set promiscous mode */
489444961713Sgirish 
489544961713Sgirish nxge_status_t
489644961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
489744961713Sgirish {
489844961713Sgirish 	nxge_status_t status = NXGE_OK;
489944961713Sgirish 
490059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
490144961713Sgirish 
490244961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
490344961713Sgirish 
490444961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
490544961713Sgirish 
490644961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
490744961713Sgirish 		goto fail;
490844961713Sgirish 	}
490944961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
491044961713Sgirish 		goto fail;
491144961713Sgirish 	}
491244961713Sgirish 
491344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
491444961713Sgirish 
491544961713Sgirish 	if (on)
491644961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
491744961713Sgirish 	else
491844961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
491944961713Sgirish 
492044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
492144961713Sgirish 
492244961713Sgirish 	return (NXGE_OK);
492344961713Sgirish fail:
492444961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
492544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
492659ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
492744961713Sgirish 
492844961713Sgirish 	return (status);
492944961713Sgirish }
493044961713Sgirish 
493144961713Sgirish /*ARGSUSED*/
493244961713Sgirish uint_t
493344961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
493444961713Sgirish {
493544961713Sgirish #ifdef	NXGE_DEBUG
493644961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
493744961713Sgirish #endif
493844961713Sgirish #if NXGE_MIF
493944961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
494044961713Sgirish 	uint32_t		status;
494144961713Sgirish 	npi_handle_t		handle;
494244961713Sgirish 	uint8_t			portn;
494344961713Sgirish 	p_nxge_stats_t		statsp;
494444961713Sgirish #endif
494544961713Sgirish 
494644961713Sgirish #ifdef	NXGE_MIF
494744961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
494844961713Sgirish 		nxgep = ldvp->nxgep;
494944961713Sgirish 	}
495044961713Sgirish 	nxgep = ldvp->nxgep;
495144961713Sgirish #endif
495244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
495344961713Sgirish 
495444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
495544961713Sgirish 	return (DDI_INTR_CLAIMED);
495644961713Sgirish 
495744961713Sgirish mif_intr_fail:
495844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
495944961713Sgirish 	return (DDI_INTR_UNCLAIMED);
496044961713Sgirish }
496144961713Sgirish 
496244961713Sgirish /*ARGSUSED*/
496344961713Sgirish uint_t
496444961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
496544961713Sgirish {
496644961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
496744961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
496844961713Sgirish 	p_nxge_ldg_t		ldgp;
496944961713Sgirish 	uint32_t		status;
497044961713Sgirish 	npi_handle_t		handle;
497144961713Sgirish 	uint8_t			portn;
497244961713Sgirish 	p_nxge_stats_t		statsp;
497344961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
497444961713Sgirish 
497544961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
497644961713Sgirish 		nxgep = ldvp->nxgep;
497744961713Sgirish 	}
497844961713Sgirish 
497944961713Sgirish 	ldgp = ldvp->ldgp;
498044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
498159ac0c16Sdavemq 	    "group %d", ldgp->ldg));
498244961713Sgirish 
498344961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
498444961713Sgirish 	/*
498544961713Sgirish 	 * This interrupt handler is for a specific
498644961713Sgirish 	 * mac port.
498744961713Sgirish 	 */
498844961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
498944961713Sgirish 	portn = nxgep->mac.portnum;
499044961713Sgirish 
499144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
499259ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
499344961713Sgirish 
499444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
499544961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
499644961713Sgirish 					(xmac_tx_iconfig_t *)&status);
499744961713Sgirish 		if (rs != NPI_SUCCESS)
499844961713Sgirish 			goto npi_fail;
499944961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
500044961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
500144961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
500244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
500344961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
500444961713Sgirish 			}
500544961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
500644961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
5007f6485eecSyc 				/*
5008f6485eecSyc 				 * Do not send FMA ereport because this
5009f6485eecSyc 				 * error does not indicate HW failure.
5010f6485eecSyc 				 */
501144961713Sgirish 			}
501244961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
501344961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
501444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
501544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
501644961713Sgirish 			}
501744961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
501844961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
501944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
502044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
502144961713Sgirish 			}
502244961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
502344961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
502444961713Sgirish 							XTXMAC_BYTE_CNT_MASK;
502544961713Sgirish 			}
502644961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
502744961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
502844961713Sgirish 							XTXMAC_FRM_CNT_MASK;
502944961713Sgirish 			}
503044961713Sgirish 		}
503144961713Sgirish 
503244961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
503344961713Sgirish 					(xmac_rx_iconfig_t *)&status);
503444961713Sgirish 		if (rs != NPI_SUCCESS)
503544961713Sgirish 			goto npi_fail;
503644961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
503744961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
503844961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
503944961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
504044961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
504144961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
504244961713Sgirish 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
504344961713Sgirish 			}
5044f6485eecSyc 			/*
5045f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5046f6485eecSyc 			 * because they do not indicate HW failures.
5047f6485eecSyc 			 */
504844961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
504944961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
505044961713Sgirish 							XRXMAC_CRC_ER_CNT_MASK;
505144961713Sgirish 			}
505244961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
505344961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
505444961713Sgirish 							MAC_LEN_ER_CNT_MASK;
505544961713Sgirish 			}
505644961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
505744961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
505844961713Sgirish 							XRXMAC_CD_VIO_CNT_MASK;
505944961713Sgirish 			}
506044961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
506144961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
506244961713Sgirish 							XRXMAC_BT_CNT_MASK;
506344961713Sgirish 			}
506444961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
506544961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
506644961713Sgirish 							XRXMAC_HIST_CNT1_MASK;
506744961713Sgirish 			}
506844961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
506944961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
507044961713Sgirish 							XRXMAC_HIST_CNT2_MASK;
507144961713Sgirish 			}
507244961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
507344961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
507444961713Sgirish 							XRXMAC_HIST_CNT3_MASK;
507544961713Sgirish 			}
507644961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
507744961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
507844961713Sgirish 							XRXMAC_HIST_CNT4_MASK;
507944961713Sgirish 			}
508044961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
508144961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
508244961713Sgirish 							XRXMAC_HIST_CNT5_MASK;
508344961713Sgirish 			}
508444961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
508544961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
508644961713Sgirish 							XRXMAC_HIST_CNT6_MASK;
508744961713Sgirish 			}
508844961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
508944961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
509044961713Sgirish 							XRXMAC_BC_FRM_CNT_MASK;
509144961713Sgirish 			}
509244961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
509344961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
509444961713Sgirish 							XRXMAC_MC_FRM_CNT_MASK;
509544961713Sgirish 			}
5096f6485eecSyc 			/*
5097f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5098f6485eecSyc 			 * because they do not indicate HW failures.
5099f6485eecSyc 			 */
510044961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
510144961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
510244961713Sgirish 							XRXMAC_FRAG_CNT_MASK;
510344961713Sgirish 			}
510444961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
510544961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
510644961713Sgirish 							XRXMAC_AL_ER_CNT_MASK;
510744961713Sgirish 			}
510844961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
510944961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
511044961713Sgirish 							XMAC_LINK_FLT_CNT_MASK;
511144961713Sgirish 			}
511244961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
511344961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
511444961713Sgirish 			}
511544961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
511644961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
511744961713Sgirish 			}
511844961713Sgirish 		}
511944961713Sgirish 
512044961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
512144961713Sgirish 						(xmac_ctl_iconfig_t *)&status);
512244961713Sgirish 		if (rs != NPI_SUCCESS)
512344961713Sgirish 			goto npi_fail;
512444961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
512544961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
512644961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
512744961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
512844961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
512944961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
513044961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
513144961713Sgirish 		}
513244961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
513344961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
513444961713Sgirish 						(bmac_tx_iconfig_t *)&status);
513544961713Sgirish 		if (rs != NPI_SUCCESS)
513644961713Sgirish 			goto npi_fail;
513744961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
513844961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
513944961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
514044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
514144961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
514244961713Sgirish 			}
514344961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
514444961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
514544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
514644961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
514744961713Sgirish 			}
514844961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
514944961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
515044961713Sgirish 							BTXMAC_BYTE_CNT_MASK;
515144961713Sgirish 			}
515244961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
515344961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
515444961713Sgirish 							BTXMAC_FRM_CNT_MASK;
515544961713Sgirish 			}
515644961713Sgirish 		}
515744961713Sgirish 
515844961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
515944961713Sgirish 						(bmac_rx_iconfig_t *)&status);
516044961713Sgirish 		if (rs != NPI_SUCCESS)
516144961713Sgirish 			goto npi_fail;
516244961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
516344961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
516444961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
516544961713Sgirish 			}
516644961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
516744961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
516844961713Sgirish 							RXMAC_FRM_CNT_MASK;
516944961713Sgirish 			}
517044961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
517144961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
517244961713Sgirish 							BMAC_CRC_ER_CNT_MASK;
517344961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
517444961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
517544961713Sgirish 			}
517644961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
517744961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
517844961713Sgirish 							MAC_LEN_ER_CNT_MASK;
517944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
518044961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
518144961713Sgirish 			}
518244961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
518344961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
518444961713Sgirish 							BMAC_CD_VIO_CNT_MASK;
518544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
518644961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
518744961713Sgirish 			}
518844961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
518944961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
519044961713Sgirish 							BRXMAC_BYTE_CNT_MASK;
519144961713Sgirish 			}
519244961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
519344961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
519444961713Sgirish 							BMAC_AL_ER_CNT_MASK;
519544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
519644961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
519744961713Sgirish 			}
519844961713Sgirish 
519944961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
520044961713Sgirish 						(bmac_ctl_iconfig_t *)&status);
520144961713Sgirish 			if (rs != NPI_SUCCESS)
520244961713Sgirish 				goto npi_fail;
520344961713Sgirish 
520444961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
520544961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
520644961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
520744961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
520844961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
520944961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
521044961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
521144961713Sgirish 			}
521244961713Sgirish 		}
521344961713Sgirish 
521444961713Sgirish 	if (ldgp->nldvs == 1) {
521544961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
521644961713Sgirish 			B_TRUE, ldgp->ldg_timer);
521744961713Sgirish 	}
521844961713Sgirish 
521944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
522044961713Sgirish 	return (DDI_INTR_CLAIMED);
522144961713Sgirish 
522244961713Sgirish npi_fail:
522344961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
522444961713Sgirish 	return (DDI_INTR_UNCLAIMED);
522544961713Sgirish }
522644961713Sgirish 
522744961713Sgirish nxge_status_t
522844961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
522944961713Sgirish {
523044961713Sgirish 	uint8_t		phy_port_addr;
523144961713Sgirish 	nxge_status_t	status = NXGE_OK;
523244961713Sgirish 	boolean_t	rx_sig_ok;
523344961713Sgirish 	boolean_t	pcs_blk_lock;
523444961713Sgirish 	boolean_t	link_align;
523544961713Sgirish 	uint16_t	val1, val2, val3;
523644961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
523744961713Sgirish 	uint16_t	val_debug;
523844961713Sgirish 	uint16_t	val;
523944961713Sgirish #endif
524044961713Sgirish 
524144961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
524244961713Sgirish 
524344961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
524444961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
524544961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
524644961713Sgirish 	if ((val_debug & ~0x200) != 0) {
524744961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
524844961713Sgirish 				nxgep->mac.portnum, val_debug);
524944961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
525044961713Sgirish 				&val_debug);
525144961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
525244961713Sgirish 				nxgep->mac.portnum, val_debug);
525344961713Sgirish 	}
525444961713Sgirish 
525544961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
525644961713Sgirish 					XPCS_REG_DESCWERR_COUNTER, &val);
525744961713Sgirish 	if (val != 0)
525844961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
525944961713Sgirish 
526044961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
526144961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
526244961713Sgirish 	if (val != 0)
526344961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
526444961713Sgirish 
526544961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
526644961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
526744961713Sgirish 	if (val != 0)
526844961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
526944961713Sgirish #endif
527044961713Sgirish 
527144961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
527244961713Sgirish 
527344961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
527444961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
527544961713Sgirish 			BCM8704_PMA_PMD_DEV_ADDR,
527644961713Sgirish 			BCM8704_PMD_RECEIVE_SIG_DETECT,
527744961713Sgirish 			&val1);
527844961713Sgirish 	if (status != NXGE_OK)
527944961713Sgirish 		goto fail;
528044961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
528144961713Sgirish 
528244961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
528344961713Sgirish 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
528444961713Sgirish 			BCM8704_PCS_DEV_ADDR,
528544961713Sgirish 			BCM8704_10GBASE_R_PCS_STATUS_REG,
528644961713Sgirish 			&val2)) != NPI_SUCCESS)
528744961713Sgirish 		goto fail;
528844961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
528944961713Sgirish 
529044961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
529144961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
529244961713Sgirish 			BCM8704_PHYXS_ADDR,
529344961713Sgirish 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
529444961713Sgirish 			&val3);
529544961713Sgirish 	if (status != NXGE_OK)
529644961713Sgirish 		goto fail;
52972d17280bSsbehera 
52982d17280bSsbehera 	switch (nxgep->chip_id) {
52992d17280bSsbehera 	case BCM8704_CHIP_ID:
53002d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
53012d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
53022d17280bSsbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
53032d17280bSsbehera 		break;
53042d17280bSsbehera 	case BCM8706_CHIP_ID:
53052d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
53062d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
53072d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
53082d17280bSsbehera 		    B_TRUE : B_FALSE;
53092d17280bSsbehera 		break;
53102d17280bSsbehera 	default:
53112d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
53122d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
53132d17280bSsbehera 		goto fail;
53142d17280bSsbehera 	}
53152d17280bSsbehera 
531644961713Sgirish 
531744961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
531844961713Sgirish 	/* Temp workaround for link down issue */
531944961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
532044961713Sgirish 		if (val2 != 0x4) {
532144961713Sgirish 			pcs_blk_lock = B_TRUE;
532244961713Sgirish 			cmn_err(CE_NOTE,
532344961713Sgirish 				"!LINK DEBUG: port%d PHY Dev3 "
532444961713Sgirish 				"Reg 0x20 = 0x%x\n",
532544961713Sgirish 				nxgep->mac.portnum, val2);
532644961713Sgirish 		}
532744961713Sgirish 	}
532844961713Sgirish 
532944961713Sgirish 	if (link_align == B_FALSE) {
533044961713Sgirish 		if (val3 != 0x140f) {
533144961713Sgirish 			link_align = B_TRUE;
533244961713Sgirish 			cmn_err(CE_NOTE,
533344961713Sgirish 				"!LINK DEBUG: port%d PHY Dev4 "
533444961713Sgirish 				"Reg 0x18 = 0x%x\n",
533544961713Sgirish 				nxgep->mac.portnum, val3);
533644961713Sgirish 		}
533744961713Sgirish 	}
533844961713Sgirish 
533944961713Sgirish 	if (rx_sig_ok == B_FALSE) {
534044961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
534144961713Sgirish 			rx_sig_ok = B_TRUE;
534244961713Sgirish 			cmn_err(CE_NOTE,
534344961713Sgirish 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
534444961713Sgirish 				nxgep->mac.portnum);
534544961713Sgirish 		}
534644961713Sgirish 	}
534744961713Sgirish #endif
534844961713Sgirish 
534944961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
535044961713Sgirish 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
535144961713Sgirish 
535244961713Sgirish 	return (NXGE_OK);
535344961713Sgirish fail:
535444961713Sgirish 	return (status);
535544961713Sgirish }
535644961713Sgirish 
535759ac0c16Sdavemq nxge_status_t
535859ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
535959ac0c16Sdavemq {
536059ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
536159ac0c16Sdavemq 	    != NPI_SUCCESS)
536259ac0c16Sdavemq 		return (NXGE_ERROR);
536359ac0c16Sdavemq 	else
536459ac0c16Sdavemq 		return (NXGE_OK);
536559ac0c16Sdavemq }
536644961713Sgirish 
536744961713Sgirish nxge_status_t
536859ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
536944961713Sgirish {
537059ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
537159ac0c16Sdavemq 	    != NPI_SUCCESS)
537259ac0c16Sdavemq 		return (NXGE_ERROR);
537359ac0c16Sdavemq 	else
537459ac0c16Sdavemq 		return (NXGE_OK);
537559ac0c16Sdavemq }
537644961713Sgirish 
53772d17280bSsbehera static boolean_t
53782d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
53792d17280bSsbehera {
53802d17280bSsbehera 	uint32_t pma_pmd_id = 0;
53812d17280bSsbehera 	uint32_t pcs_id = 0;
53822d17280bSsbehera 	uint32_t phy_id = 0;
53832d17280bSsbehera 
53842d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
53852d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53862d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
53872d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
53882d17280bSsbehera 		goto found_phy;
53892d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
53902d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53912d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
53922d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
53932d17280bSsbehera 		goto found_phy;
53942d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
53952d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53962d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
53972d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
53982d17280bSsbehera 		goto found_phy;
53992d17280bSsbehera 
54002d17280bSsbehera 	return (B_FALSE);
54012d17280bSsbehera 
54022d17280bSsbehera found_phy:
54032d17280bSsbehera 	return (B_TRUE);
54042d17280bSsbehera }
54052d17280bSsbehera 
540659ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
540759ac0c16Sdavemq 
540859ac0c16Sdavemq static boolean_t
540959ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
541059ac0c16Sdavemq {
541159ac0c16Sdavemq 	int		i;
541259ac0c16Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
541359ac0c16Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
541459ac0c16Sdavemq 	boolean_t	found = B_FALSE;
541559ac0c16Sdavemq 
541659ac0c16Sdavemq 	switch (type) {
541759ac0c16Sdavemq 	case CLAUSE_45_TYPE:
541859ac0c16Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
541930505775Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
542030505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
542159ac0c16Sdavemq 				found = B_TRUE;
542259ac0c16Sdavemq 				break;
542359ac0c16Sdavemq 			}
542459ac0c16Sdavemq 		}
542559ac0c16Sdavemq 		break;
542659ac0c16Sdavemq 	case CLAUSE_22_TYPE:
542759ac0c16Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
542830505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
542930505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
543059ac0c16Sdavemq 				found = B_TRUE;
543159ac0c16Sdavemq 				break;
543256d930aeSspeer 			}
543344961713Sgirish 		}
543459ac0c16Sdavemq 		break;
543559ac0c16Sdavemq 	default:
543659ac0c16Sdavemq 		break;
543756d930aeSspeer 	}
543856d930aeSspeer 
543959ac0c16Sdavemq 	return (found);
544059ac0c16Sdavemq }
544159ac0c16Sdavemq 
54422e59129aSraghus static uint32_t
54432e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
54442e59129aSraghus {
54452e59129aSraghus 	uint16_t	val1 = 0;
54462e59129aSraghus 	uint16_t	val2 = 0;
54472e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
54482e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
54492e59129aSraghus 
545053560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
54512e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
54522e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
54532e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
54542e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
545553560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
54562e59129aSraghus 
54572e59129aSraghus 	pma_pmd_dev_id = val1;
54582e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
54592e59129aSraghus 	pma_pmd_dev_id |= val2;
54602e59129aSraghus 
54612e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
54622e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
54632e59129aSraghus 
54642e59129aSraghus 	return (pma_pmd_dev_id);
54652e59129aSraghus }
54662e59129aSraghus 
54672e59129aSraghus static uint32_t
54682e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
54692e59129aSraghus {
54702e59129aSraghus 	uint16_t	val1 = 0;
54712e59129aSraghus 	uint16_t	val2 = 0;
54722e59129aSraghus 	uint32_t	pcs_dev_id = 0;
54732e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
54742e59129aSraghus 
547553560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
54762e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
54772e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
54782e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
54792e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
548053560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
54812e59129aSraghus 
54822e59129aSraghus 	pcs_dev_id = val1;
54832e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
54842e59129aSraghus 	pcs_dev_id |= val2;
54852e59129aSraghus 
54862e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
54872e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
54882e59129aSraghus 
54892e59129aSraghus 	return (pcs_dev_id);
54902e59129aSraghus }
54912e59129aSraghus 
54922e59129aSraghus static uint32_t
54932e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
54942e59129aSraghus {
54952e59129aSraghus 	uint16_t	val1 = 0;
54962e59129aSraghus 	uint16_t	val2 = 0;
54972e59129aSraghus 	uint32_t	phy_id = 0;
54982e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
54992e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
55002e59129aSraghus 
5501321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
55022e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
55032e59129aSraghus 	    &val1);
55042e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
55052e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
55062e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
55072e59129aSraghus 		goto exit;
55082e59129aSraghus 	}
55092e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
55102e59129aSraghus 	    &val2);
55112e59129aSraghus 	if (npi_status != 0) {
55122e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
55132e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
55142e59129aSraghus 		goto exit;
55152e59129aSraghus 	}
55162e59129aSraghus 	phy_id = val1;
55172e59129aSraghus 	phy_id = (phy_id << 16);
55182e59129aSraghus 	phy_id |= val2;
55192e59129aSraghus 
55202e59129aSraghus exit:
5521321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55222e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
55232e59129aSraghus 	    phy_port, phy_id));
55242e59129aSraghus 
55252e59129aSraghus 	return (phy_id);
55262e59129aSraghus }
55272e59129aSraghus 
552859ac0c16Sdavemq /*
552959ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
553059ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
553159ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
553259ac0c16Sdavemq  * and the Neptune type.
553359ac0c16Sdavemq  */
553459ac0c16Sdavemq 
553559ac0c16Sdavemq nxge_status_t
553659ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
553759ac0c16Sdavemq {
553859a835ddSjoycey 	int		i, j, l;
553959ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
554059ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
554159ac0c16Sdavemq 	uint32_t	phy_id = 0;
554230505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
554330505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
554430505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
554559ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
554659ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
55472d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
55482d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
554959ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
555059ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
555156d930aeSspeer 
555259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
555356d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
555459ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
555559ac0c16Sdavemq 	    nxgep->niu_type));
555659ac0c16Sdavemq 
5557*678453a8Sspeer 	if (isLDOMguest(nxgep)) {
5558*678453a8Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
5559*678453a8Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
5560*678453a8Sspeer 		return (NXGE_OK);
5561*678453a8Sspeer 	}
5562*678453a8Sspeer 
556359a835ddSjoycey 	j = l = 0;
556459ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
556556d930aeSspeer 	/*
556659ac0c16Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
556759ac0c16Sdavemq 	 * for on chip serdes usages.
556856d930aeSspeer 	 */
556959ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
55702e59129aSraghus 
55712e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
557259ac0c16Sdavemq 
557359ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
557459ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
557559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
557659ac0c16Sdavemq 			    "PMA/PMD dev found", i));
557730505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
557830505775Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
557930505775Ssbehera 				    BCM_PHY_ID_MASK;
55802d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
558159ac0c16Sdavemq 				j++;
558259ac0c16Sdavemq 			}
558359ac0c16Sdavemq 		} else {
558459ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
558559ac0c16Sdavemq 		}
558659ac0c16Sdavemq 
55872e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
558859ac0c16Sdavemq 
558959ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
559059ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
559159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
559259ac0c16Sdavemq 			    "dev found", i));
559359a835ddSjoycey 			if (pma_pmd_dev_fd[i] == 1) {
559459a835ddSjoycey 				port_pcs_dev_id[j - 1] = pcs_dev_id &
559530505775Ssbehera 				    BCM_PHY_ID_MASK;
559659a835ddSjoycey 			} else {
559759a835ddSjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
559859a835ddSjoycey 					port_pcs_dev_id[j] = pcs_dev_id &
559959a835ddSjoycey 					    BCM_PHY_ID_MASK;
560059a835ddSjoycey 					port_fd_arr[j] = (uint8_t)i;
560159a835ddSjoycey 					j++;
560259a835ddSjoycey 				}
560359ac0c16Sdavemq 			}
560459ac0c16Sdavemq 		} else {
560559ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
560659ac0c16Sdavemq 		}
560759ac0c16Sdavemq 
56082d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
56092d17280bSsbehera 			total_port_fd ++;
56102d17280bSsbehera 		}
561159ac0c16Sdavemq 
56122e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
561359ac0c16Sdavemq 
561459ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
56152d17280bSsbehera 			total_phy_fd ++;
561659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
561759ac0c16Sdavemq 			    "found", i));
561830505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
561930505775Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
56202d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
562159ac0c16Sdavemq 				l++;
562259ac0c16Sdavemq 			}
562359ac0c16Sdavemq 		}
562459ac0c16Sdavemq 	}
562559ac0c16Sdavemq 
562659ac0c16Sdavemq 	switch (total_port_fd) {
562759ac0c16Sdavemq 	case 2:
562859ac0c16Sdavemq 		switch (total_phy_fd) {
562959ac0c16Sdavemq 		case 2:
563059a835ddSjoycey 			/* 2 10G, 2 1G RGMII Fiber */
563159a835ddSjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
563259a835ddSjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
563359a835ddSjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
563459a835ddSjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
563559a835ddSjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
563659a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
563759a835ddSjoycey 
563859a835ddSjoycey 				hw_p->platform_type =
563959a835ddSjoycey 					    P_NEPTUNE_GENERIC;
564059a835ddSjoycey 
564159a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
564259a835ddSjoycey 
564359a835ddSjoycey 				hw_p->xcvr_addr[0] = port_fd_arr[0];
564459a835ddSjoycey 				hw_p->xcvr_addr[1] = port_fd_arr[1];
564559a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
564659a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
564759a835ddSjoycey 
564859a835ddSjoycey 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
564959a835ddSjoycey 				    "ARTM card with 2 10G, 2 1G"));
565059a835ddSjoycey 			} else {
565159a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
565259a835ddSjoycey 				    "Unsupported neptune type 1"));
565359a835ddSjoycey 				goto error_exit;
565459a835ddSjoycey 			}
565559a835ddSjoycey 			break;
565659a835ddSjoycey 
565759ac0c16Sdavemq 		case 1:
565859ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
565959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
566059ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
566159ac0c16Sdavemq 			goto error_exit;
566259ac0c16Sdavemq 		case 0:
566359ac0c16Sdavemq 			/* 2 10G */
566430505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
566530505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
566630505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
566730505775Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
56682e59129aSraghus 
56692e59129aSraghus 				/*
56702e59129aSraghus 				 * Check the first phy port address against
56712e59129aSraghus 				 * the known phy start addresses to determine
56722e59129aSraghus 				 * the platform type.
56732e59129aSraghus 				 */
56742d17280bSsbehera 
56752d17280bSsbehera 				switch (port_fd_arr[0]) {
56762d17280bSsbehera 				case BCM8704_NEPTUNE_PORT_ADDR_BASE:
56772e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
56782e59129aSraghus 					hw_p->platform_type =
56792e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
56802d17280bSsbehera 					break;
56812d17280bSsbehera 				case BCM8706_GOA_PORT_ADDR_BASE:
56822d17280bSsbehera 					if (hw_p->platform_type !=
56832d17280bSsbehera 					    P_NEPTUNE_NIU) {
56842d17280bSsbehera 						hw_p->platform_type =
56852d17280bSsbehera 						    P_NEPTUNE_GENERIC;
56862d17280bSsbehera 						hw_p->niu_type =
56872d17280bSsbehera 						    NEPTUNE_2_10GF;
56882d17280bSsbehera 					}
56892d17280bSsbehera 					break;
56902d17280bSsbehera 				default:
56912d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
56922e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
56932e59129aSraghus 					goto error_exit;
56942e59129aSraghus 				}
56952d17280bSsbehera 
56962d17280bSsbehera 				for (i = 0; i < 2; i++) {
56972d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
56982d17280bSsbehera 				}
569959ac0c16Sdavemq 			} else {
570059ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
570159ac0c16Sdavemq 				    "Unsupported neptune type 2"));
570259ac0c16Sdavemq 				goto error_exit;
570359ac0c16Sdavemq 			}
570459ac0c16Sdavemq 			break;
570559ac0c16Sdavemq 		case 4:
570659ac0c16Sdavemq 			/* Maramba with 2 XAUI */
570730505775Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
570830505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
570930505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
571030505775Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
571130505775Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
571230505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
571330505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
571430505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
571559ac0c16Sdavemq 
571659ac0c16Sdavemq 				/*
571759ac0c16Sdavemq 				 * Check the first phy port address against
571859ac0c16Sdavemq 				 * the known phy start addresses to determine
571959ac0c16Sdavemq 				 * the platform type.
572059ac0c16Sdavemq 				 */
57212d17280bSsbehera 				switch (phy_fd_arr[0]) {
57222d17280bSsbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
572359ac0c16Sdavemq 					hw_p->platform_type =
572459ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
57252d17280bSsbehera 					break;
57262d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
572759ac0c16Sdavemq 					hw_p->platform_type =
572859ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
57292d17280bSsbehera 					break;
57302d17280bSsbehera 				default:
573159ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
573259ac0c16Sdavemq 					    "Unknown port %d...Cannot "
573359ac0c16Sdavemq 					    "determine platform type", i));
57342e59129aSraghus 					goto error_exit;
573559ac0c16Sdavemq 				}
57362d17280bSsbehera 
57372e59129aSraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
57382e59129aSraghus 
57392d17280bSsbehera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
57402d17280bSsbehera 				hw_p->xcvr_addr[1] = port_fd_arr[1];
57412d17280bSsbehera 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
57422d17280bSsbehera 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
57432d17280bSsbehera 
574459ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
574559ac0c16Sdavemq 				    "Maramba with 2 XAUI"));
574659ac0c16Sdavemq 			} else {
574759ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
574859ac0c16Sdavemq 				    "Unsupported neptune type 3"));
574959ac0c16Sdavemq 				goto error_exit;
575059ac0c16Sdavemq 			}
575159ac0c16Sdavemq 			break;
575259ac0c16Sdavemq 		default:
575359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
575459ac0c16Sdavemq 			    "Unsupported neptune type 5"));
575559ac0c16Sdavemq 			goto error_exit;
575659ac0c16Sdavemq 		}
575730505775Ssbehera 		break;
575859ac0c16Sdavemq 	case 1:
575959ac0c16Sdavemq 		switch (total_phy_fd) {
576059ac0c16Sdavemq 		case 3:
57612e59129aSraghus 			/*
57622e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
57632e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
57642e59129aSraghus 			 * 1_10G_3_1G
57652e59129aSraghus 			 */
57662e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
57672e59129aSraghus 			    "Unsupported neptune type 7"));
57682e59129aSraghus 			goto error_exit;
576959ac0c16Sdavemq 		case 2:
577059ac0c16Sdavemq 			/*
577159ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
577259ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
577359ac0c16Sdavemq 			 * 1_10G_2_1G
577459ac0c16Sdavemq 			 */
577559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
577659ac0c16Sdavemq 			    "Unsupported neptune type 8"));
577759ac0c16Sdavemq 			goto error_exit;
577859ac0c16Sdavemq 		case 1:
577959ac0c16Sdavemq 			/*
578059ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
578159ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
578259ac0c16Sdavemq 			 * 1_10G_1_1G
578359ac0c16Sdavemq 			 */
578459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
578559ac0c16Sdavemq 			    "Unsupported neptune type 9"));
578659ac0c16Sdavemq 			goto error_exit;
578759ac0c16Sdavemq 		case 0:
57882d17280bSsbehera 			/* 1 10G mode, N2 with 1 XAUI */
57892d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
57902d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
57912d17280bSsbehera 
57922d17280bSsbehera 				/*
57932d17280bSsbehera 				 * Check the first phy port address against
57942d17280bSsbehera 				 * the known phy start addresses to determine
57952d17280bSsbehera 				 * the platform type.
57962d17280bSsbehera 				 */
57972d17280bSsbehera 
57982d17280bSsbehera 				switch (port_fd_arr[0]) {
57992d17280bSsbehera 				case BCM8704_N2_PORT_ADDR_BASE:
58002d17280bSsbehera 				case (BCM8704_N2_PORT_ADDR_BASE + 1):
58012d17280bSsbehera 				case BCM8706_ALT_GOA_PORT1_ADDR:
58022d17280bSsbehera 					if (hw_p->platform_type !=
58032d17280bSsbehera 					    P_NEPTUNE_NIU) {
58042d17280bSsbehera 						hw_p->platform_type =
58052d17280bSsbehera 						    P_NEPTUNE_GENERIC;
58062d17280bSsbehera 						hw_p->niu_type =
58072d17280bSsbehera 						    NEPTUNE_2_10GF;
58082d17280bSsbehera 					}
58092d17280bSsbehera 					break;
58102d17280bSsbehera 				default:
58112d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58122d17280bSsbehera 					    "Unsupported neptune type 10"));
58132d17280bSsbehera 					goto error_exit;
58142d17280bSsbehera 				}
5815321febdeSsbehera 				/*
5816321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
5817321febdeSsbehera 				 * phy address to function number mapping
5818321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
5819321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
5820321febdeSsbehera 				 * But for Huron XAUI, the assignment should
5821321febdeSsbehera 				 * be by function number, i.e., whichever
5822321febdeSsbehera 				 * function number attaches should be
5823321febdeSsbehera 				 * assigned the available PHY (this is required
5824321febdeSsbehera 				 * primarily to support pre-production Huron
5825321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
5826321febdeSsbehera 				 */
5827321febdeSsbehera 				if (port_fd_arr[0] ==
5828321febdeSsbehera 				    BCM8706_ALT_GOA_PORT1_ADDR) {
5829321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
5830321febdeSsbehera 				} else {
5831321febdeSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
5832321febdeSsbehera 					    port_fd_arr[0];
5833321febdeSsbehera 				}
58342d17280bSsbehera 			} else {
58352d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
58362d17280bSsbehera 				    "Unsupported neptune type 10 - 1"));
58372d17280bSsbehera 				goto error_exit;
58382d17280bSsbehera 			}
58392d17280bSsbehera 			break;
584059ac0c16Sdavemq 		case 4:
584159ac0c16Sdavemq 			/* Maramba with 1 XAUI */
584230505775Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
584330505775Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
584459ac0c16Sdavemq 
584559ac0c16Sdavemq 				/*
584659ac0c16Sdavemq 				 * Check the first phy port address against
584759ac0c16Sdavemq 				 * the known phy start addresses to determine
584859ac0c16Sdavemq 				 * the platform type.
584959ac0c16Sdavemq 				 */
58502d17280bSsbehera 				switch (phy_fd_arr[0]) {
58512d17280bSsbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
585259ac0c16Sdavemq 					hw_p->platform_type =
585359ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
58542d17280bSsbehera 					break;
58552d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
585659ac0c16Sdavemq 					hw_p->platform_type =
585759ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
58582d17280bSsbehera 					break;
58592d17280bSsbehera 				default:
586059ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
586159ac0c16Sdavemq 					    "Unknown port %d...Cannot "
58622d17280bSsbehera 					    "determine platform type 10 - 2",
58632d17280bSsbehera 					    i));
58642e59129aSraghus 					goto error_exit;
58652e59129aSraghus 				}
58662e59129aSraghus 
58672d17280bSsbehera 				/*
58682d17280bSsbehera 				 * Check the BCM8704 address to determine
58692d17280bSsbehera 				 * if XAUI is in port 0 or port 1.
58702d17280bSsbehera 				 */
58712d17280bSsbehera 				switch (port_fd_arr[0]) {
58722d17280bSsbehera 				case BCM8704_MARAMBA_PORT_ADDR_BASE:
58732e59129aSraghus 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
58742d17280bSsbehera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
58752d17280bSsbehera 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
58762d17280bSsbehera 						hw_p->xcvr_addr[i] =
58772d17280bSsbehera 						    phy_fd_arr[i];
58782d17280bSsbehera 					}
58792d17280bSsbehera 					break;
58802d17280bSsbehera 				case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1):
58812e59129aSraghus 					hw_p->niu_type =
58822e59129aSraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
58832d17280bSsbehera 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
58842d17280bSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
58852d17280bSsbehera 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
58862d17280bSsbehera 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
58872d17280bSsbehera 					break;
58882d17280bSsbehera 				default:
58892e59129aSraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
58902e59129aSraghus 					    "Unsupported neptune type 11"));
58912e59129aSraghus 					goto error_exit;
589259ac0c16Sdavemq 				}
589359ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
589459ac0c16Sdavemq 				    "Maramba with 1 XAUI"));
589559ac0c16Sdavemq 			} else {
589659ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
589759ac0c16Sdavemq 				    "Unsupported neptune type 12"));
589859ac0c16Sdavemq 				goto error_exit;
589959ac0c16Sdavemq 			}
590059ac0c16Sdavemq 			break;
590159ac0c16Sdavemq 		default:
590259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
590359ac0c16Sdavemq 			    "Unsupported neptune type 13"));
590459ac0c16Sdavemq 			goto error_exit;
590559ac0c16Sdavemq 		}
590659ac0c16Sdavemq 		break;
590759ac0c16Sdavemq 	case 0:
590859ac0c16Sdavemq 		switch (total_phy_fd) {
590959ac0c16Sdavemq 		case 4:
591030505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
591130505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
591230505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
591330505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
591459ac0c16Sdavemq 
591559ac0c16Sdavemq 				/*
591659ac0c16Sdavemq 				 * Check the first phy port address against
591759ac0c16Sdavemq 				 * the known phy start addresses to determine
591859ac0c16Sdavemq 				 * the platform type.
591959ac0c16Sdavemq 				 */
59202d17280bSsbehera 				switch (phy_fd_arr[0]) {
59212d17280bSsbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
592259ac0c16Sdavemq 					hw_p->platform_type =
592359ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
59242d17280bSsbehera 					break;
59252d17280bSsbehera 				case BCM5464_NEPTUNE_PORT_ADDR_BASE:
59262e59129aSraghus 					hw_p->platform_type =
59272e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
59282d17280bSsbehera 					break;
59292d17280bSsbehera 				default:
59302e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
59312e59129aSraghus 					    "Unknown port %d...Cannot "
59322e59129aSraghus 					    "determine platform type", i));
59332e59129aSraghus 					goto error_exit;
593459ac0c16Sdavemq 				}
59352e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
59362d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
59372d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
59382d17280bSsbehera 				}
593959ac0c16Sdavemq 			} else {
594059ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
594159ac0c16Sdavemq 				    "Unsupported neptune type 14"));
594259ac0c16Sdavemq 				goto error_exit;
594359ac0c16Sdavemq 			}
594459ac0c16Sdavemq 			break;
594559ac0c16Sdavemq 		case 3:
594659ac0c16Sdavemq 			/* TODO 3 1G mode */
594759ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
594859ac0c16Sdavemq 			    "Unsupported neptune type 15"));
594959ac0c16Sdavemq 			goto error_exit;
595059ac0c16Sdavemq 		case 2:
595159ac0c16Sdavemq 			/* TODO 2 1G mode */
595259a835ddSjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
595359a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
595459a835ddSjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
595559a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
595659a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
595759a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
595859a835ddSjoycey 			} else {
595959a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
596059a835ddSjoycey 				    "Unsupported neptune type 16"));
596159a835ddSjoycey 				goto error_exit;
596259a835ddSjoycey 			}
596359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
596459a835ddSjoycey 			    "2 RGMII Fiber ports - RTM"));
596559a835ddSjoycey 			break;
596659a835ddSjoycey 
596759ac0c16Sdavemq 		case 1:
596859ac0c16Sdavemq 			/* TODO 1 1G mode */
596959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
597059ac0c16Sdavemq 			    "Unsupported neptune type 17"));
597159ac0c16Sdavemq 			goto error_exit;
597259ac0c16Sdavemq 		default:
597359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
597459ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
597559ac0c16Sdavemq 			    total_phy_fd));
597659ac0c16Sdavemq 			goto error_exit;
597759ac0c16Sdavemq 		}
597859ac0c16Sdavemq 		break;
597959ac0c16Sdavemq 	default:
598056d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
598159ac0c16Sdavemq 		    "Unsupported neptune type 19"));
598259ac0c16Sdavemq 		goto error_exit;
598344961713Sgirish 	}
598444961713Sgirish 
598559ac0c16Sdavemq scan_exit:
598644961713Sgirish 
598759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
598859ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
598959ac0c16Sdavemq 	return (status);
599044961713Sgirish 
599159ac0c16Sdavemq error_exit:
599259ac0c16Sdavemq 	return (NXGE_ERROR);
599344961713Sgirish }
599456d930aeSspeer 
599556d930aeSspeer boolean_t
599656d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
599756d930aeSspeer {
599856d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
599956d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
600056d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
600156d930aeSspeer 		return (B_FALSE);
600256d930aeSspeer 	else
600356d930aeSspeer 		return (B_TRUE);
600456d930aeSspeer }
600559ac0c16Sdavemq 
600659ac0c16Sdavemq static void
600759ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
600859ac0c16Sdavemq 
600959ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
601059ac0c16Sdavemq 	uint8_t xcvr_portn;
601159ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
601259ac0c16Sdavemq 
601359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
601459ac0c16Sdavemq 
601559ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
601659ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
601759ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
601859ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
601959ac0c16Sdavemq 	}
602059ac0c16Sdavemq 	/*
602159ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
602259ac0c16Sdavemq 	 * swapped with ethernet port number. This is
602359ac0c16Sdavemq 	 * designed for better signal integrity in routing.
602459ac0c16Sdavemq 	 */
602559ac0c16Sdavemq 	switch (portn) {
602659ac0c16Sdavemq 	case 0:
602759ac0c16Sdavemq 		xcvr_portn += 3;
602859ac0c16Sdavemq 		break;
602959ac0c16Sdavemq 	case 1:
603059ac0c16Sdavemq 		xcvr_portn += 2;
603159ac0c16Sdavemq 		break;
603259ac0c16Sdavemq 	case 2:
603359ac0c16Sdavemq 		xcvr_portn += 1;
603459ac0c16Sdavemq 		break;
603559ac0c16Sdavemq 	case 3:
603659ac0c16Sdavemq 	default:
603759ac0c16Sdavemq 		break;
603859ac0c16Sdavemq 	}
603959ac0c16Sdavemq 
6040321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
604159ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
604259ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
604359ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
604459ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
604559ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
604659ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
6047321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
604859ac0c16Sdavemq 		return;
604959ac0c16Sdavemq 	}
605059ac0c16Sdavemq 
605159ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
605259ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
605359ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
605459ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
605559ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
605659ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
605759ac0c16Sdavemq 	}
605859ac0c16Sdavemq 
6059321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
606059ac0c16Sdavemq }
6061d81011f0Ssbehera 
6062d81011f0Ssbehera static nxge_status_t
6063d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
6064d81011f0Ssbehera {
6065d81011f0Ssbehera 	p_nxge_stats_t	statsp;
6066d81011f0Ssbehera 	uint8_t		xcvr_portn;
6067d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
6068d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
6069d81011f0Ssbehera 	int		status = NXGE_OK;
6070d81011f0Ssbehera 
6071d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
6072d81011f0Ssbehera 
6073d81011f0Ssbehera 	statsp = nxgep->statsp;
6074d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
6075d81011f0Ssbehera 	mii_regs = NULL;
6076d81011f0Ssbehera 	mode.value = 0;
60776b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
6078d81011f0Ssbehera #if defined(__i386)
6079d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
6080d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
6081d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
6082d81011f0Ssbehera 		goto fail;
6083d81011f0Ssbehera #else
6084d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
6085d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
6086d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
6087d81011f0Ssbehera 		goto fail;
6088d81011f0Ssbehera #endif
6089d81011f0Ssbehera 	}
6090d81011f0Ssbehera #if defined(__i386)
6091d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
6092d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
6093d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
6094d81011f0Ssbehera 		goto fail;
6095d81011f0Ssbehera 	}
6096d81011f0Ssbehera #else
6097d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
6098d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
6099d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
6100d81011f0Ssbehera 		goto fail;
6101d81011f0Ssbehera 	}
6102d81011f0Ssbehera #endif
6103d81011f0Ssbehera 
6104d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
6105d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6106d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6107d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
6108d81011f0Ssbehera 	}
6109d81011f0Ssbehera 
6110d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6111d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
6112d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
61136b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
6114d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
6115d81011f0Ssbehera 
6116d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6117d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
6118d81011f0Ssbehera 	return (status);
6119d81011f0Ssbehera fail:
6120d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6121d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
6122d81011f0Ssbehera 	return (NXGE_ERROR);
6123d81011f0Ssbehera }
6124d81011f0Ssbehera 
61251bd6825cSml nxge_status_t
61261bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep)
61271bd6825cSml {
61281bd6825cSml 	npi_attr_t		ap;
61291bd6825cSml 	uint8_t			portn;
61301bd6825cSml 	npi_handle_t		handle;
61311bd6825cSml 	npi_status_t		rs = NPI_SUCCESS;
61321bd6825cSml 
61331bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
61341bd6825cSml 
61351bd6825cSml 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
61361bd6825cSml 	handle = nxgep->npi_handle;
61371bd6825cSml 
61381bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61391bd6825cSml 	    "==> nxge_mac_sec_framesize: port<%d> "
61401bd6825cSml 	    "min framesize %d max framesize %d ",
61411bd6825cSml 	    portn,
61421bd6825cSml 	    nxgep->mac.minframesize,
61431bd6825cSml 	    nxgep->mac.maxframesize));
61441bd6825cSml 
61451bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
61461bd6825cSml 	    MAC_PORT_FRAME_SIZE,
61471bd6825cSml 	    nxgep->mac.minframesize,
61481bd6825cSml 	    nxgep->mac.maxframesize,
61491bd6825cSml 	    rs);
61501bd6825cSml 	if (rs != NPI_SUCCESS) {
61511bd6825cSml 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61521bd6825cSml 		    "<== nxge_mac_set_framesize: failed to configure "
61531bd6825cSml 		    "max/min frame size port %d", portn));
61541bd6825cSml 
61551bd6825cSml 		return (NXGE_ERROR | rs);
61561bd6825cSml 	}
61571bd6825cSml 
61581bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61591bd6825cSml 	    "<== nxge_mac_set_framesize: port<%d>", portn));
61601bd6825cSml 
61611bd6825cSml 	return (NXGE_OK);
61621bd6825cSml }
61631bd6825cSml 
6164d81011f0Ssbehera #ifdef NXGE_DEBUG
6165d81011f0Ssbehera static void
6166d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
6167d81011f0Ssbehera {
6168d81011f0Ssbehera 	p_nxge_stats_t	statsp;
6169d81011f0Ssbehera 	uint8_t		xcvr_portn;
6170d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
6171d81011f0Ssbehera 	mii_bmcr_t	bmcr;
6172d81011f0Ssbehera 	mii_bmsr_t	bmsr;
6173d81011f0Ssbehera 	mii_idr1_t	idr1;
6174d81011f0Ssbehera 	mii_idr2_t	idr2;
6175d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
6176*678453a8Sspeer 	p_nxge_param_t	param_arr;
6177d81011f0Ssbehera 
6178d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
6179d81011f0Ssbehera 
6180d81011f0Ssbehera 	statsp = nxgep->statsp;
6181d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
6182d81011f0Ssbehera 
6183d81011f0Ssbehera 	mii_regs = NULL;
6184d81011f0Ssbehera 
6185d81011f0Ssbehera #if defined(__i386)
6186d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
6187d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
6188d81011f0Ssbehera #else
6189d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
6190d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
6191d81011f0Ssbehera #endif
6192d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6193d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
6194d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
6195d81011f0Ssbehera 
6196d81011f0Ssbehera #if defined(__i386)
6197d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6198d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6199d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
6200d81011f0Ssbehera #else
6201d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6202d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6203d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
6204d81011f0Ssbehera #endif
6205d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6206d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
6207d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
6208d81011f0Ssbehera 
6209d81011f0Ssbehera #if defined(__i386)
6210d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6211d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6212d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
6213d81011f0Ssbehera #else
6214d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6215d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6216d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
6217d81011f0Ssbehera #endif
6218d81011f0Ssbehera 
6219d81011f0Ssbehera 
6220d81011f0Ssbehera #if defined(__i386)
6221d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6222d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6223d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
6224d81011f0Ssbehera #else
6225d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
6226d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
6227d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
6228d81011f0Ssbehera #endif
6229d81011f0Ssbehera 
6230d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6231d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
6232d81011f0Ssbehera 	    xcvr_portn, idr1.value));
6233d81011f0Ssbehera 
6234d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6235d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
6236d81011f0Ssbehera 	    xcvr_portn, idr2.value));
6237d81011f0Ssbehera 
6238d81011f0Ssbehera 	mode.value = 0;
62396b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
6240d81011f0Ssbehera 
6241d81011f0Ssbehera #if defined(__i386)
6242d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
6243d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
6244d81011f0Ssbehera 
6245d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
6246d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
6247d81011f0Ssbehera #else
6248d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
6249d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
6250d81011f0Ssbehera 
6251d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
6252d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
6253d81011f0Ssbehera #endif
6254d81011f0Ssbehera 
6255d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6256d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
6257d81011f0Ssbehera 	    xcvr_portn, mode.value));
6258d81011f0Ssbehera }
6259d81011f0Ssbehera #endif
6260