xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 6028:72bc433f666e)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
225780Ssbehera  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <sys/nxge/nxge_impl.h>
293859Sml29623 #include <sys/nxge/nxge_mac.h>
303859Sml29623 
314693Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
324693Stm144005 #define	LM_WAIT_MULTIPLIER	8
334693Stm144005 
343859Sml29623 extern uint32_t nxge_no_link_notify;
354732Sdavemq extern boolean_t nxge_no_msg;
363859Sml29623 extern uint32_t nxge_lb_dbg;
373859Sml29623 extern boolean_t nxge_jumbo_enable;
38*6028Ssbehera extern uint32_t nxge_jumbo_mtu;
393859Sml29623 
404693Stm144005 typedef enum {
414693Stm144005 	CHECK_LINK_RESCHEDULE,
424693Stm144005 	CHECK_LINK_STOP
434693Stm144005 } check_link_state_t;
444693Stm144005 
454693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
464693Stm144005 
473859Sml29623 /*
483859Sml29623  * Ethernet broadcast address definition.
493859Sml29623  */
503859Sml29623 static ether_addr_st etherbroadcastaddr =
513859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
524732Sdavemq /*
534732Sdavemq  * Ethernet zero address definition.
544732Sdavemq  */
554185Sspeer static ether_addr_st etherzeroaddr =
564185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
574732Sdavemq /*
584732Sdavemq  * Supported chip types
594732Sdavemq  */
605572Ssbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID};
614732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
624732Sdavemq 
634732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
644732Sdavemq 				sizeof (uint32_t))
654732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
664732Sdavemq 				sizeof (uint32_t))
674732Sdavemq /*
684732Sdavemq  * static functions
694732Sdavemq  */
704977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
714977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
724977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
734732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
745572Ssbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
754732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
764732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
774732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
784732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
794732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
804732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
814732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
824732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
834732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
844732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
854732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
864732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
875572Ssbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
885572Ssbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
894732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
904732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
914732Sdavemq 
924732Sdavemq /*
934732Sdavemq  * xcvr tables for supported transceivers
944732Sdavemq  */
954732Sdavemq 
964977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
974732Sdavemq 	nxge_n2_serdes_init,
984732Sdavemq 	nxge_10G_xcvr_init,
994732Sdavemq 	nxge_10G_link_intr_stop,
1004732Sdavemq 	nxge_10G_link_intr_start,
1014732Sdavemq 	nxge_check_10g_link,
1025572Ssbehera 	PCS_XCVR
1034732Sdavemq };
1044732Sdavemq 
1054977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1064977Sraghus 	nxge_n2_serdes_init,
1074977Sraghus 	nxge_1G_xcvr_init,
1084977Sraghus 	nxge_1G_fiber_link_intr_stop,
1094977Sraghus 	nxge_1G_fiber_link_intr_start,
1104977Sraghus 	nxge_check_mii_link,
1115572Ssbehera 	PCS_XCVR
1124977Sraghus };
1134977Sraghus 
1144732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
1154732Sdavemq 	nxge_neptune_10G_serdes_init,
1164732Sdavemq 	nxge_10G_xcvr_init,
1174732Sdavemq 	nxge_10G_link_intr_stop,
1184732Sdavemq 	nxge_10G_link_intr_start,
1194732Sdavemq 	nxge_check_10g_link,
1205572Ssbehera 	PCS_XCVR
1214732Sdavemq };
1224732Sdavemq 
1234732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
1244732Sdavemq 	NULL,
1254732Sdavemq 	nxge_1G_xcvr_init,
1264732Sdavemq 	nxge_1G_copper_link_intr_stop,
1274732Sdavemq 	nxge_1G_copper_link_intr_start,
1284732Sdavemq 	nxge_check_mii_link,
1295572Ssbehera 	INT_MII_XCVR
1304732Sdavemq };
1314732Sdavemq 
1324732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
1334732Sdavemq 	nxge_1G_serdes_init,
1344732Sdavemq 	nxge_1G_xcvr_init,
1354732Sdavemq 	nxge_1G_fiber_link_intr_stop,
1364732Sdavemq 	nxge_1G_fiber_link_intr_start,
1374732Sdavemq 	nxge_check_mii_link,
1385572Ssbehera 	PCS_XCVR
1394732Sdavemq };
1404732Sdavemq 
1414732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
1424732Sdavemq 	nxge_neptune_10G_serdes_init,
1434732Sdavemq 	NULL,
1444732Sdavemq 	NULL,
1454732Sdavemq 	NULL,
1464977Sraghus 	NULL,
1475572Ssbehera 	PCS_XCVR
1484732Sdavemq };
1493859Sml29623 
1503859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
1513859Sml29623 
1525196Ssbehera #ifdef NXGE_DEBUG
1535196Ssbehera static void nxge_mii_dump(p_nxge_t);
1545196Ssbehera #endif
1555196Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
1565196Ssbehera 
1574977Sraghus nxge_status_t
1584977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep)
1594977Sraghus {
1604977Sraghus 	nxge_status_t status = NXGE_OK;
1614977Sraghus 	char *phy_type;
1624977Sraghus 	char *prop_val;
1634977Sraghus 
1644977Sraghus 	nxgep->mac.portmode = 0;
1655572Ssbehera 	nxgep->xcvr_addr = 0;
1665572Ssbehera 
1675572Ssbehera 	/*
1685572Ssbehera 	 * First check for hot swappable phy property.
1695572Ssbehera 	 */
1705572Ssbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
1715572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1725572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1735572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
1745572Ssbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
1755572Ssbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1765572Ssbehera 	    "hot-swappable-phy") == 1) {
1775572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1785572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1795572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
1805572Ssbehera 	} else if (nxgep->niu_type == N2_NIU &&
1815572Ssbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
1825572Ssbehera 	    "hot-swappable-phy") == 1) {
1835572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1845572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1855572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
1865572Ssbehera 	}
1875572Ssbehera 
1885572Ssbehera 	/*
1895572Ssbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
1905572Ssbehera 	 */
1915572Ssbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
1925572Ssbehera 
1935572Ssbehera 		uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1945572Ssbehera 
1955572Ssbehera 		nxgep->hot_swappable_phy = B_TRUE;
1965572Ssbehera 		/*
1975572Ssbehera 		 * If this is the 2nd NIU port, then check 2 addresses
1985572Ssbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
1995572Ssbehera 		 * (in the eval board) or 20 (in the P0 board).
2005572Ssbehera 		 */
2015572Ssbehera 		if (portn == 1) {
2025572Ssbehera 			if (nxge_is_phy_present(nxgep,
2035572Ssbehera 			    BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID,
2045572Ssbehera 			    BCM_PHY_ID_MASK)) {
2055572Ssbehera 				nxgep->xcvr_addr =
2065572Ssbehera 				    BCM8706_ALT_GOA_PORT1_ADDR;
2075572Ssbehera 				goto found_phy;
2085572Ssbehera 			}
2095572Ssbehera 		}
2105572Ssbehera 		if (nxge_is_phy_present(nxgep,
2115572Ssbehera 		    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
2125572Ssbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
2135572Ssbehera 			nxgep->xcvr_addr = (BCM8706_GOA_PORT_ADDR_BASE) +
2145572Ssbehera 			    portn;
2155572Ssbehera 			goto found_phy;
2165572Ssbehera 		}
2175572Ssbehera 
2185572Ssbehera 		nxgep->phy_absent = B_TRUE;
2195572Ssbehera 		goto check_phy_done;
2205572Ssbehera found_phy:
2215572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2225572Ssbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
2235572Ssbehera 		nxgep->phy_absent = B_FALSE;
2245572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
2255572Ssbehera 		    "found for hot swappable phy"));
2265572Ssbehera check_phy_done:
2275572Ssbehera 		return (status);
2285572Ssbehera 	}
2295572Ssbehera 
2305572Ssbehera 	/* Get phy-type property from the driver conf. file */
2314977Sraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
2324977Sraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2334977Sraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
2344977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2354977Sraghus 		    "found  conf file: phy-type %s", prop_val));
2364977Sraghus 		if (strcmp("xgsd", prop_val) == 0) {
2374977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2384977Sraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
2394977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2404977Sraghus 			    "found: 10G Serdes"));
2414977Sraghus 		} else if (strcmp("gsd", prop_val) == 0) {
2424977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2434977Sraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
2444977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
2454977Sraghus 		} else if (strcmp("mif", prop_val) == 0) {
2464977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
2474977Sraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
2484977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
2494977Sraghus 		} else if (strcmp("pcs", prop_val) == 0) {
2504977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2514977Sraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
2524977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
2534977Sraghus 		}
2544977Sraghus 
2554977Sraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
2564977Sraghus 		    "phy-type", prop_val);
2574977Sraghus 		ddi_prop_free(prop_val);
2584977Sraghus 
2594977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
2604977Sraghus 		    "Got phy type [0x%x] from conf file",
2614977Sraghus 		    nxgep->mac.portmode));
2624977Sraghus 
2634977Sraghus 		return (NXGE_OK);
2644977Sraghus 	}
2655572Ssbehera 
2665572Ssbehera 	/* Get phy-type property from OBP */
2674977Sraghus 	if (nxgep->niu_type == N2_NIU) {
2684977Sraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
2694977Sraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
2704977Sraghus 			if (strcmp("xgf", prop_val) == 0) {
2714977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2724977Sraghus 				    XPCS_XCVR;
2734977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
2744977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2754977Sraghus 				    "10G Fiber Xcvr"));
2764977Sraghus 			} else if (strcmp("mif", prop_val) == 0) {
2774977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2784977Sraghus 				    INT_MII_XCVR;
2794977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
2804977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2814977Sraghus 				    "1G Copper Xcvr"));
2824977Sraghus 			} else if (strcmp("pcs", prop_val) == 0) {
2834977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2844977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
2854977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2864977Sraghus 				    "1G Fiber Xcvr"));
2874977Sraghus 			} else if (strcmp("xgc", prop_val) == 0) {
2884977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2894977Sraghus 				    XPCS_XCVR;
2904977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
2914977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2924977Sraghus 				    "10G Copper Xcvr"));
2934977Sraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
2944977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2954977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
2964977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2974977Sraghus 				    "OBP: 10G Serdes"));
2984977Sraghus 			} else if (strcmp("gsd", prop_val) == 0) {
2994977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3004977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
3014977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3024977Sraghus 				    "OBP: 1G Serdes"));
3034977Sraghus 			} else {
3044977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3054977Sraghus 				    "Unknown phy-type: %s", prop_val));
3064977Sraghus 				ddi_prop_free(prop_val);
3074977Sraghus 				return (NXGE_ERROR);
3084977Sraghus 			}
3094977Sraghus 			status = NXGE_OK;
3104977Sraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3114977Sraghus 			    nxgep->dip, "phy-type", prop_val);
3124977Sraghus 			ddi_prop_free(prop_val);
3134977Sraghus 
3144977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3154977Sraghus 			    "Got phy type [0x%x] from OBP",
3164977Sraghus 			    nxgep->mac.portmode));
3174977Sraghus 
3184977Sraghus 			return (status);
3194977Sraghus 		} else {
3204977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3214977Sraghus 			    "Exiting...phy-type property not found"));
3224977Sraghus 			return (NXGE_ERROR);
3234977Sraghus 		}
3244977Sraghus 	}
3254977Sraghus 
3264977Sraghus 
3274977Sraghus 	if (!nxgep->vpd_info.present) {
3284977Sraghus 		return (NXGE_OK);
3294977Sraghus 	}
3304977Sraghus 
3314977Sraghus 	if (!nxgep->vpd_info.ver_valid) {
3324977Sraghus 		goto read_seeprom;
3334977Sraghus 	}
3344977Sraghus 
3354977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3364977Sraghus 	    "Reading phy type from expansion ROM"));
3374977Sraghus 	/*
3384977Sraghus 	 * Try to read the phy type from the vpd data read off the
3394977Sraghus 	 * expansion ROM.
3404977Sraghus 	 */
3414977Sraghus 	phy_type = nxgep->vpd_info.phy_type;
3424977Sraghus 
3435196Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
3444977Sraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
3454977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3465196Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
3474977Sraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
3484977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3495196Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
3504977Sraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
3514977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3525196Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
3534977Sraghus 		nxgep->mac.portmode = PORT_10G_COPPER;
3544977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3555196Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
3565196Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
3575196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3585196Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
3595196Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
3605196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3614977Sraghus 	} else {
3625196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3634977Sraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
3644977Sraghus 		    phy_type[0], phy_type[1], phy_type[2]));
3654977Sraghus 		goto read_seeprom;
3664977Sraghus 	}
3674977Sraghus 
3684977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3694977Sraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
3704977Sraghus 
3714977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
3724977Sraghus 	return (status);
3734977Sraghus 
3744977Sraghus read_seeprom:
3754977Sraghus 	/*
3764977Sraghus 	 * read the phy type from the SEEPROM - NCR registers
3774977Sraghus 	 */
3784977Sraghus 	status = nxge_espc_phy_type_get(nxgep);
3794977Sraghus 	if (status != NXGE_OK) {
3804977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3814977Sraghus 		    "Failed to get phy type"));
3824977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3834977Sraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
3844977Sraghus 	}
3854977Sraghus 
3864977Sraghus 	return (status);
3874977Sraghus 
3884977Sraghus }
3894977Sraghus 
3904732Sdavemq /* Set up the PHY specific values. */
3914732Sdavemq 
3924732Sdavemq nxge_status_t
3934732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
3944732Sdavemq {
3954732Sdavemq 	nxge_status_t	status = NXGE_OK;
3964732Sdavemq 	uint32_t	port_type;
3974732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3984977Sraghus 	uint32_t	pcs_id = 0;
3994977Sraghus 	uint32_t	pma_pmd_id = 0;
4004977Sraghus 	uint32_t	phy_id = 0;
4015572Ssbehera 	uint16_t	chip_id = 0;
4024732Sdavemq 
4034732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
4044732Sdavemq 	    portn));
4054732Sdavemq 
4064977Sraghus 	switch (nxgep->niu_type) {
4074977Sraghus 	case N2_NIU:
4084977Sraghus 		switch (nxgep->mac.portmode) {
4094977Sraghus 		case PORT_1G_FIBER:
4104977Sraghus 		case PORT_1G_SERDES:
4114977Sraghus 			nxgep->xcvr = nxge_n2_1G_table;
4125572Ssbehera 			nxgep->xcvr_addr = portn;
4134977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
4144977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
4154977Sraghus 			    "Serdes"));
4164977Sraghus 			break;
4174977Sraghus 		case PORT_10G_FIBER:
4184977Sraghus 		case PORT_10G_SERDES:
4194977Sraghus 			nxgep->xcvr = nxge_n2_10G_table;
4205572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
4215572Ssbehera 				nxgep->xcvr_addr =
4225572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
4235572Ssbehera 			}
4244977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
4254977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
4264977Sraghus 			    "Serdes"));
4274977Sraghus 			break;
4285572Ssbehera 		case PORT_HSP_MODE:
4295572Ssbehera 			nxgep->xcvr = nxge_n2_10G_table;
4305572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
4315572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
4325572Ssbehera 			    "Swappable Xcvr (not present)"));
4335572Ssbehera 			break;
4344977Sraghus 		default:
4354977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4364977Sraghus 			    "<== nxge_setup_xcvr_table: "
4374977Sraghus 			    "Unable to determine NIU portmode"));
4384977Sraghus 			return (NXGE_ERROR);
4394977Sraghus 		}
4404977Sraghus 		break;
4414977Sraghus 	default:
4424977Sraghus 		if (nxgep->mac.portmode == 0) {
4434977Sraghus 			/*
4444977Sraghus 			 * Would be the case for platforms like Maramba
4454977Sraghus 			 * in which the phy type could not be got from conf
4464977Sraghus 			 * file, OBP, VPD or Serial PROM.
4474977Sraghus 			 */
4484977Sraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4494977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4504977Sraghus 				    "<== nxge_setup_xcvr_table:"
4514977Sraghus 				    " Invalid Neptune type [0x%x]",
4524977Sraghus 				    nxgep->niu_type));
4534977Sraghus 				return (NXGE_ERROR);
4544977Sraghus 			}
4554977Sraghus 
4564977Sraghus 			port_type = nxgep->niu_type >>
4574977Sraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
4584977Sraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
4594977Sraghus 
4604977Sraghus 			switch (port_type) {
4614977Sraghus 
4624977Sraghus 			case NXGE_PORT_1G_COPPER:
4634977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4644977Sraghus 				break;
4654977Sraghus 			case NXGE_PORT_10G_COPPER:
4664977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
4674977Sraghus 				break;
4684977Sraghus 			case NXGE_PORT_1G_FIBRE:
4694977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4704977Sraghus 				break;
4714977Sraghus 			case NXGE_PORT_10G_FIBRE:
4724977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
4734977Sraghus 				break;
4744977Sraghus 			case NXGE_PORT_1G_SERDES:
4754977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4764977Sraghus 				break;
4774977Sraghus 			case NXGE_PORT_10G_SERDES:
4784977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4794977Sraghus 				break;
4804977Sraghus 			case NXGE_PORT_1G_RGMII_FIBER:
4814977Sraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
4824977Sraghus 				break;
4834977Sraghus 			default:
4844977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4854977Sraghus 				    "<== nxge_setup_xcvr_table: "
4864977Sraghus 				    "Unknown port-type: 0x%x", port_type));
4874977Sraghus 				return (NXGE_ERROR);
4884977Sraghus 			}
4894977Sraghus 		}
4904977Sraghus 
4914977Sraghus 		switch (nxgep->mac.portmode) {
4924977Sraghus 		case PORT_1G_COPPER:
4934977Sraghus 		case PORT_1G_RGMII_FIBER:
4944732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
4955572Ssbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
4964732Sdavemq 			/*
4974732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
4984732Sdavemq 			 * swapped with ethernet port number. This is
4994977Sraghus 			 * designed for better signal integrity in
5004977Sraghus 			 * routing. This is also the case for the
5014977Sraghus 			 * on-board Neptune copper ports on the Maramba
5024977Sraghus 			 * platform.
5034732Sdavemq 			 */
5044977Sraghus 			switch (nxgep->platform_type) {
5054977Sraghus 			case P_NEPTUNE_ATLAS_4PORT:
5064977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
5074977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
5084977Sraghus 				switch (portn) {
5094977Sraghus 				case 0:
5105572Ssbehera 					nxgep->xcvr_addr += 3;
5114977Sraghus 					break;
5124977Sraghus 				case 1:
5135572Ssbehera 					nxgep->xcvr_addr += 1;
5144977Sraghus 					break;
5154977Sraghus 				case 2:
5165572Ssbehera 					nxgep->xcvr_addr -= 1;
5174977Sraghus 					break;
5184977Sraghus 				case 3:
5195572Ssbehera 					nxgep->xcvr_addr -= 3;
5204977Sraghus 					break;
5214977Sraghus 				default:
5224977Sraghus 					return (NXGE_ERROR);
5234977Sraghus 				}
5244732Sdavemq 				break;
5255196Ssbehera 			case P_NEPTUNE_ALONSO:
5265196Ssbehera 			/*
5275196Ssbehera 			 * The Alonso Neptune, xcvr port numbers for
5285196Ssbehera 			 * ports 2 and 3 are not swapped. Port 2 has
5295196Ssbehera 			 * the BCM5464_PORT_BASE_ADDR and port 3 has
5305196Ssbehera 			 * next address.
5315196Ssbehera 			 */
5325572Ssbehera 				nxgep->xcvr_addr =
5335572Ssbehera 				    BCM5464_NEPTUNE_PORT_ADDR_BASE;
5345196Ssbehera 				if (portn == 3) {
5355572Ssbehera 					nxgep->xcvr_addr += 1;
5365196Ssbehera 				}
5375196Ssbehera 				break;
5384732Sdavemq 			default:
5394977Sraghus 				break;
5404732Sdavemq 			}
5415196Ssbehera 
5424977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5434977Sraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
5444977Sraghus 			    "Copper" : "RGMII Fiber"));
5454732Sdavemq 			break;
5464977Sraghus 		case PORT_10G_COPPER:
5474732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
5484732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
5494732Sdavemq 			break;
5504977Sraghus 		case PORT_1G_FIBER:
5514977Sraghus 		case PORT_1G_SERDES:
5524732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
5535572Ssbehera 			nxgep->xcvr_addr = portn;
5544977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5554977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
5564977Sraghus 			    "Fiber" : "Serdes"));
5574732Sdavemq 			break;
5584977Sraghus 		case PORT_10G_FIBER:
5594977Sraghus 		case PORT_10G_SERDES:
5604732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
5615572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
5625572Ssbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
5635572Ssbehera 			    "nxgep->xcvr_addr = [%d]",
5645572Ssbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
5655572Ssbehera 			    nxgep->xcvr_addr));
5665572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5675572Ssbehera 				nxgep->xcvr_addr =
5685572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5695572Ssbehera 			}
5704977Sraghus 			switch (nxgep->platform_type) {
5714977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
5724977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
5734732Sdavemq 				/*
5744732Sdavemq 				 * Switch off LED for corresponding copper
5754732Sdavemq 				 * port
5764732Sdavemq 				 */
5774732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
5784977Sraghus 				break;
5794977Sraghus 			default:
5804977Sraghus 				break;
5814732Sdavemq 			}
5824977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
5834977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
5844977Sraghus 			    "Fiber" : "Serdes"));
5854732Sdavemq 			break;
5865572Ssbehera 
5875572Ssbehera 		case PORT_HSP_MODE:
5885572Ssbehera 			nxgep->xcvr = nxge_10G_fiber_table;
5895572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
5905572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
5915572Ssbehera 			    "Swappable Xcvr (not present)"));
5925572Ssbehera 			break;
5934732Sdavemq 		default:
5944732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5954732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
5964732Sdavemq 			return (NXGE_ERROR);
5974732Sdavemq 		}
5984732Sdavemq 	}
5994732Sdavemq 
6005572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
6015572Ssbehera 		if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6025572Ssbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
6035572Ssbehera 		    &chip_id)) == NXGE_OK) {
6045572Ssbehera 
6055572Ssbehera 			switch (chip_id) {
6065572Ssbehera 			case BCM8704_CHIP_ID:
6075572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6085572Ssbehera 				    "nxge_setup_xcvr_table: "
6095572Ssbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
6105572Ssbehera 				    chip_id));
6115572Ssbehera 				break;
6125572Ssbehera 			case BCM8706_CHIP_ID:
6135572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6145572Ssbehera 				    "nxge_setup_xcvr_table: "
6155572Ssbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
6165572Ssbehera 				    chip_id));
6175572Ssbehera 				break;
6185572Ssbehera 			default:
6195572Ssbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6205572Ssbehera 				    "nxge_setup_xcvr_table: "
6215572Ssbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
6225572Ssbehera 				    chip_id));
6235572Ssbehera 				break;
6245572Ssbehera 			}
6255572Ssbehera 		}
6265572Ssbehera 	}
6275572Ssbehera 
6284732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
6295572Ssbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
6305572Ssbehera 	nxgep->chip_id = chip_id;
6314977Sraghus 
6324977Sraghus 	/*
6334977Sraghus 	 * Get the actual device ID value returned by MDIO read.
6344977Sraghus 	 */
6354977Sraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
6364977Sraghus 
6375572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
6384977Sraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
6394977Sraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
6404977Sraghus 	} else {
6415572Ssbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
6424977Sraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
6434977Sraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
6444977Sraghus 		} else {
6454977Sraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
6465572Ssbehera 			    nxgep->xcvr_addr);
6474977Sraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
6484977Sraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
6494977Sraghus 			}
6504977Sraghus 		}
6514977Sraghus 	}
6524977Sraghus 
6534732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
6544732Sdavemq 
6554977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
6565572Ssbehera 	    "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type,
6575572Ssbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
6584977Sraghus 
6594732Sdavemq 	return (status);
6604732Sdavemq }
6614732Sdavemq 
6623859Sml29623 /* Initialize the entire MAC and physical layer */
6633859Sml29623 
6643859Sml29623 nxge_status_t
6653859Sml29623 nxge_mac_init(p_nxge_t nxgep)
6663859Sml29623 {
6673859Sml29623 	uint8_t			portn;
6683859Sml29623 	nxge_status_t		status = NXGE_OK;
6693859Sml29623 
6703859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6713859Sml29623 
6723859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
6733859Sml29623 
6743859Sml29623 	nxgep->mac.portnum = portn;
6753859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
6763859Sml29623 
6773859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
6783859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
6793859Sml29623 
6803859Sml29623 	/* Initialize XIF to configure a network mode */
6813859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
6823859Sml29623 		goto fail;
6833859Sml29623 	}
6843859Sml29623 
6853859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
6863859Sml29623 		goto fail;
6873859Sml29623 	}
6883859Sml29623 
6893859Sml29623 	/* Initialize TX and RX MACs */
6903859Sml29623 	/*
6913859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
6923859Sml29623 	 */
6933859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
6943859Sml29623 		goto fail;
6953859Sml29623 
6963859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
6973859Sml29623 		goto fail;
6983859Sml29623 
6993859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
7003859Sml29623 		goto fail;
7013859Sml29623 
7023859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
7033859Sml29623 		goto fail;
7043859Sml29623 
7053859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
7063859Sml29623 		goto fail;
7073859Sml29623 
7083859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
7093859Sml29623 		goto fail;
7103859Sml29623 
7115553Smisaki 	/* Initialize MAC control configuration */
7125553Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
7135553Smisaki 		goto fail;
7145553Smisaki 	}
7155553Smisaki 
7163859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
7173859Sml29623 
7185196Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
7195196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
7205196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
7215196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
7225196Ssbehera 	    ((portn == 0) || (portn == 1))) {
7235196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7245196Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
7255196Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
7265196Ssbehera 			goto fail;
7275196Ssbehera 		}
7285196Ssbehera 	}
7295196Ssbehera 
7304977Sraghus 
7313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
7323859Sml29623 
7333859Sml29623 	return (NXGE_OK);
7343859Sml29623 fail:
7353859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7363859Sml29623 			"nxge_mac_init: failed to initialize MAC port<%d>",
7373859Sml29623 			portn));
7383859Sml29623 	return (status);
7393859Sml29623 }
7403859Sml29623 
7413859Sml29623 /* Initialize the Ethernet Link */
7423859Sml29623 
7433859Sml29623 nxge_status_t
7443859Sml29623 nxge_link_init(p_nxge_t nxgep)
7453859Sml29623 {
7463859Sml29623 	nxge_status_t		status = NXGE_OK;
7474977Sraghus 	nxge_port_mode_t	portmode;
7483859Sml29623 #ifdef	NXGE_DEBUG
7493859Sml29623 	uint8_t			portn;
7503859Sml29623 
7513859Sml29623 	portn = nxgep->mac.portnum;
7523859Sml29623 
7533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
7543859Sml29623 #endif
7555572Ssbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
7565572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
7575572Ssbehera 		    "Phy not present, cannot initialize link"));
7585572Ssbehera 		return (status);
7595572Ssbehera 	}
7603859Sml29623 
7614977Sraghus 	portmode = nxgep->mac.portmode;
7625572Ssbehera 
7634977Sraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
7644977Sraghus 	    (portmode != PORT_1G_SERDES)) {
7653859Sml29623 		/* Workaround to get link up in both NIU ports */
7664977Sraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
7673859Sml29623 			goto fail;
7684977Sraghus 		}
7693859Sml29623 	}
7703859Sml29623 	NXGE_DELAY(200000);
7713859Sml29623 	/* Initialize internal serdes */
7723859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
7733859Sml29623 		goto fail;
7743859Sml29623 	NXGE_DELAY(200000);
7753859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
7763859Sml29623 		goto fail;
7773859Sml29623 
7783859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
7793859Sml29623 
7803859Sml29623 	return (NXGE_OK);
7813859Sml29623 
7823859Sml29623 fail:
7833859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7843859Sml29623 		"nxge_link_init: ",
7853859Sml29623 		"failed to initialize Ethernet link on port<%d>",
7863859Sml29623 		portn));
7873859Sml29623 
7883859Sml29623 	return (status);
7893859Sml29623 }
7903859Sml29623 
7913859Sml29623 
7923859Sml29623 /* Initialize the XIF sub-block within the MAC */
7933859Sml29623 
7943859Sml29623 nxge_status_t
7953859Sml29623 nxge_xif_init(p_nxge_t nxgep)
7963859Sml29623 {
7973859Sml29623 	uint32_t		xif_cfg = 0;
7983859Sml29623 	npi_attr_t		ap;
7993859Sml29623 	uint8_t			portn;
8003859Sml29623 	nxge_port_t		portt;
8013859Sml29623 	nxge_port_mode_t	portmode;
8023859Sml29623 	p_nxge_stats_t		statsp;
8033859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
8043859Sml29623 	npi_handle_t		handle;
8053859Sml29623 
8063859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8073859Sml29623 
8083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
8093859Sml29623 
8103859Sml29623 	handle = nxgep->npi_handle;
8113859Sml29623 	portmode = nxgep->mac.portmode;
8123859Sml29623 	portt = nxgep->mac.porttype;
8133859Sml29623 	statsp = nxgep->statsp;
8143859Sml29623 
8155196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
8165196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
8175196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
8185196Ssbehera 	    ((portn == 0) || (portn == 1))) {
8195196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8205196Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
8215196Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
8225196Ssbehera 	}
8235196Ssbehera 
8243859Sml29623 	if (portt == PORT_TYPE_XMAC) {
8253859Sml29623 
8263859Sml29623 		/* Setup XIF Configuration for XMAC */
8273859Sml29623 
8283859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
8294977Sraghus 		    (portmode == PORT_10G_COPPER) ||
8304977Sraghus 		    (portmode == PORT_10G_SERDES))
8313859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
8323859Sml29623 
8333859Sml29623 		if (portmode == PORT_1G_COPPER) {
8343859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
8353859Sml29623 		}
8363859Sml29623 
8373859Sml29623 		/* Set MAC Internal Loopback if necessary */
8383859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
8393859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
8403859Sml29623 
8413859Sml29623 		if (statsp->mac_stats.link_speed == 100)
8423859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
8433859Sml29623 
8443859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
8453859Sml29623 
8464977Sraghus 		if ((portmode == PORT_10G_FIBER) ||
8474977Sraghus 		    (portmode == PORT_10G_SERDES)) {
8483859Sml29623 			if (statsp->mac_stats.link_up) {
8493859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
8503859Sml29623 			} else {
8513859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
8523859Sml29623 			}
8533859Sml29623 		}
8543859Sml29623 
8553859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
8563859Sml29623 		if (rs != NPI_SUCCESS)
8573859Sml29623 			goto fail;
8583859Sml29623 
8593859Sml29623 		nxgep->mac.xif_config = xif_cfg;
8603859Sml29623 
8613859Sml29623 		/* Set Port Mode */
8623859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
8634977Sraghus 		    (portmode == PORT_10G_COPPER) ||
8644977Sraghus 		    (portmode == PORT_10G_SERDES)) {
8653859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
8663859Sml29623 						MAC_XGMII_MODE, rs);
8673859Sml29623 			if (rs != NPI_SUCCESS)
8683859Sml29623 				goto fail;
8693859Sml29623 			if (statsp->mac_stats.link_up) {
8703859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
8713859Sml29623 					goto fail;
8723859Sml29623 			} else {
8733859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
8743859Sml29623 					goto fail;
8753859Sml29623 			}
8763859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
8774977Sraghus 		    (portmode == PORT_1G_COPPER) ||
8785196Ssbehera 		    (portmode == PORT_1G_SERDES) ||
8795196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
8805196Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8815196Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
8825196Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
8833859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
8843859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
8853859Sml29623 							MAC_GMII_MODE, rs);
8863859Sml29623 			} else {
8873859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
8883859Sml29623 							MAC_MII_MODE, rs);
8893859Sml29623 			}
8903859Sml29623 			if (rs != NPI_SUCCESS)
8913859Sml29623 				goto fail;
8923859Sml29623 		} else {
8933859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8943859Sml29623 					"nxge_xif_init: Unknown port mode (%d)"
8953859Sml29623 					" for port<%d>", portmode, portn));
8963859Sml29623 			goto fail;
8973859Sml29623 		}
8983859Sml29623 
8995196Ssbehera 		/* Enable ATCA mode */
9005196Ssbehera 
9013859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
9023859Sml29623 
9033859Sml29623 		/* Setup XIF Configuration for BMAC */
9043859Sml29623 
9055196Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
9065196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
9073859Sml29623 			if (statsp->mac_stats.link_speed == 100)
9083859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
9093859Sml29623 		}
9103859Sml29623 
9113859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
9123859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
9133859Sml29623 
9143859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
9153859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
9163859Sml29623 
9173859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
9183859Sml29623 
9193859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
9203859Sml29623 		if (rs != NPI_SUCCESS)
9213859Sml29623 			goto fail;
9223859Sml29623 		nxgep->mac.xif_config = xif_cfg;
9233859Sml29623 	}
9243859Sml29623 
9253859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
9263859Sml29623 	return (NXGE_OK);
9273859Sml29623 fail:
9283859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9293859Sml29623 			"nxge_xif_init: Failed to initialize XIF port<%d>",
9303859Sml29623 			portn));
9313859Sml29623 	return (NXGE_ERROR | rs);
9323859Sml29623 }
9333859Sml29623 
9343859Sml29623 /* Initialize the PCS sub-block in the MAC */
9353859Sml29623 
9363859Sml29623 nxge_status_t
9373859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
9383859Sml29623 {
9393859Sml29623 	pcs_cfg_t		pcs_cfg;
9403859Sml29623 	uint32_t		val;
9413859Sml29623 	uint8_t			portn;
9423859Sml29623 	nxge_port_mode_t	portmode;
9433859Sml29623 	npi_handle_t		handle;
9443859Sml29623 	p_nxge_stats_t		statsp;
9453859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
9463859Sml29623 
9473859Sml29623 	handle = nxgep->npi_handle;
9483859Sml29623 	portmode = nxgep->mac.portmode;
9493859Sml29623 	portn = nxgep->mac.portnum;
9503859Sml29623 	statsp = nxgep->statsp;
9513859Sml29623 
9523859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
9533859Sml29623 
9544977Sraghus 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
9554977Sraghus 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
9564977Sraghus 			goto fail;
9574977Sraghus 		}
9584977Sraghus 
9593859Sml29623 		/* Initialize port's PCS */
9603859Sml29623 		pcs_cfg.value = 0;
9613859Sml29623 		pcs_cfg.bits.w0.enable = 1;
9623859Sml29623 		pcs_cfg.bits.w0.mask = 1;
9633859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
9643859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
9654977Sraghus 
9664977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9674977Sraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
9684977Sraghus 		    portn, pcs_cfg.value));
9693859Sml29623 	} else if ((portmode == PORT_10G_FIBER) ||
9704977Sraghus 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
9713859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
9723859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
9733859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
9743859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
9753859Sml29623 
9763859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
9773859Sml29623 			goto fail;
9783859Sml29623 
9793859Sml29623 		/* Set XPCS Internal Loopback if necessary */
9803859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
9813859Sml29623 						XPCS_REG_CONTROL1, &val))
9823859Sml29623 						!= NPI_SUCCESS)
9833859Sml29623 			goto fail;
9843859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
9853859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
9863859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
9873859Sml29623 		else
9883859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
9893859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
9903859Sml29623 						XPCS_REG_CONTROL1, val))
9913859Sml29623 						!= NPI_SUCCESS)
9923859Sml29623 			goto fail;
9933859Sml29623 
9943859Sml29623 		/* Clear descw errors */
9953859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
9963859Sml29623 						XPCS_REG_DESCWERR_COUNTER, 0))
9973859Sml29623 						!= NPI_SUCCESS)
9983859Sml29623 			goto fail;
9993859Sml29623 		/* Clear symbol errors */
10003859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
10013859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
10023859Sml29623 					!= NPI_SUCCESS)
10033859Sml29623 			goto fail;
10043859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
10053859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
10063859Sml29623 					!= NPI_SUCCESS)
10073859Sml29623 			goto fail;
10083859Sml29623 
10095196Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
10105196Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
10115196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10125196Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
10133859Sml29623 		if (portn < 4) {
10143859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
10153859Sml29623 					PCS_DATAPATH_MODE_MII);
10163859Sml29623 		}
10173859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
10183859Sml29623 			goto fail;
10193859Sml29623 
10203859Sml29623 	} else {
10213859Sml29623 		goto fail;
10223859Sml29623 	}
10233859Sml29623 pass:
10243859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
10253859Sml29623 	return (NXGE_OK);
10263859Sml29623 fail:
10273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10283859Sml29623 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
10293859Sml29623 			portn));
10303859Sml29623 	return (NXGE_ERROR | rs);
10313859Sml29623 }
10323859Sml29623 
10335553Smisaki /*
10345553Smisaki  * Initialize the MAC CTRL sub-block within the MAC
10355553Smisaki  * Only the receive-pause-cap is supported.
10365553Smisaki  */
10375553Smisaki nxge_status_t
10385553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
10395553Smisaki {
10405553Smisaki 	uint8_t			portn;
10415553Smisaki 	nxge_port_t		portt;
10425553Smisaki 	p_nxge_stats_t		statsp;
10435553Smisaki 	npi_handle_t		handle;
10445553Smisaki 	uint32_t		val;
10455553Smisaki 
10465553Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
10475553Smisaki 
10485553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
10495553Smisaki 	    portn));
10505553Smisaki 
10515553Smisaki 	handle = nxgep->npi_handle;
10525553Smisaki 	portt = nxgep->mac.porttype;
10535553Smisaki 	statsp = nxgep->statsp;
10545553Smisaki 
10555553Smisaki 	if (portt == PORT_TYPE_XMAC) {
10565553Smisaki 		/* Readin the current XMAC Config Register for XMAC */
10575553Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
10585553Smisaki 
10595553Smisaki 		/*
10605553Smisaki 		 * Setup XMAC Configuration for XMAC
10615553Smisaki 		 * XMAC only supports receive-pause
10625553Smisaki 		 */
10635553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
10645553Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
10655553Smisaki 				/*
10665553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
10675553Smisaki 				 * is 0, enable receive pause.
10685553Smisaki 				 */
10695553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
10705553Smisaki 			} else {
10715553Smisaki 				/*
10725553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
10735553Smisaki 				 * is 1, disable receive pause.  Send pause is
10745553Smisaki 				 * not supported.
10755553Smisaki 				 */
10765553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
10775553Smisaki 			}
10785553Smisaki 		} else {
10795553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
10805553Smisaki 				/*
10815553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
10825553Smisaki 				 * is 1, enable receive pause.
10835553Smisaki 				 */
10845553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
10855553Smisaki 			} else {
10865553Smisaki 				/*
10875553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
10885553Smisaki 				 * is 0, disable receive pause. Send pause is
10895553Smisaki 				 * not supported
10905553Smisaki 				 */
10915553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
10925553Smisaki 			}
10935553Smisaki 		}
10945553Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
10955553Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
10965553Smisaki 		/* Readin the current MAC CTRL Config Register for BMAC */
10975553Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
10985553Smisaki 
10995553Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
11005553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
11015553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
11025553Smisaki 				/*
11035553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
11045553Smisaki 				 * is 1, disable receive pause. Send pause
11055553Smisaki 				 * is not supported
11065553Smisaki 				 */
11075553Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
11085553Smisaki 			} else {
11095553Smisaki 				/*
11105553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
11115553Smisaki 				 * is 0, enable receive pause and disable
11125553Smisaki 				 * send pause.
11135553Smisaki 				 */
11145553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
11155553Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
11165553Smisaki 			}
11175553Smisaki 		} else {
11185553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
11195553Smisaki 				/*
11205553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11215553Smisaki 				 * is 1, enable receive pause. Send pause is
11225553Smisaki 				 * not supported.
11235553Smisaki 				 */
11245553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
11255553Smisaki 			} else {
11265553Smisaki 				/*
11275553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11285553Smisaki 				 * is 0, pause capability is not available in
11295553Smisaki 				 * either direction.
11305553Smisaki 				 */
11315553Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
11325553Smisaki 					~MAC_CTRL_CFG_RECV_PAUSE_EN);
11335553Smisaki 			}
11345553Smisaki 		}
11355553Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
11365553Smisaki 	}
11375553Smisaki 
11385553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
11395553Smisaki 	    portn));
11405553Smisaki 
11415553Smisaki 	return (NXGE_OK);
11425553Smisaki }
11435553Smisaki 
11443859Sml29623 /* Initialize the Internal Serdes */
11453859Sml29623 
11463859Sml29623 nxge_status_t
11473859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
11483859Sml29623 {
11493859Sml29623 	p_nxge_stats_t		statsp;
11503859Sml29623 #ifdef	NXGE_DEBUG
11513859Sml29623 	uint8_t			portn;
11523859Sml29623 #endif
11533859Sml29623 	nxge_status_t		status = NXGE_OK;
11543859Sml29623 
11553859Sml29623 #ifdef	NXGE_DEBUG
11563859Sml29623 	portn = nxgep->mac.portnum;
11573859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11584732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
11593859Sml29623 #endif
11603859Sml29623 
11614732Sdavemq 	if (nxgep->xcvr.serdes_init) {
11624732Sdavemq 		statsp = nxgep->statsp;
11634732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
11644732Sdavemq 		if (status != NXGE_OK)
11653859Sml29623 			goto fail;
11664732Sdavemq 		statsp->mac_stats.serdes_inits++;
11673859Sml29623 	}
11683859Sml29623 
11693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
11704732Sdavemq 	    portn));
11713859Sml29623 
11723859Sml29623 	return (NXGE_OK);
11733859Sml29623 
11743859Sml29623 fail:
11753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11764732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
11774732Sdavemq 	    portn));
11783859Sml29623 
11793859Sml29623 	return (status);
11803859Sml29623 }
11813859Sml29623 
11823859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
11833859Sml29623 
11844732Sdavemq static nxge_status_t
11853859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
11863859Sml29623 {
11873859Sml29623 	uint8_t portn;
11883859Sml29623 	int chan;
11893859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
11904977Sraghus 	esr_ti_cfgpll_l_t pll_sts_l;
11913859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
11923859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
11933859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
11943859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
11954977Sraghus #ifdef NXGE_DEBUG
11964977Sraghus 	esr_ti_testcfg_t cfg;
11974977Sraghus #endif
11983859Sml29623 	esr_ti_testcfg_t test_cfg;
11993859Sml29623 	nxge_status_t status = NXGE_OK;
12003859Sml29623 
12013859Sml29623 	portn = nxgep->mac.portnum;
12023859Sml29623 
12033859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
12043859Sml29623 			portn));
12053859Sml29623 
12063859Sml29623 	tx_cfg_l.value = 0;
12073859Sml29623 	tx_cfg_h.value = 0;
12083859Sml29623 	rx_cfg_l.value = 0;
12093859Sml29623 	rx_cfg_h.value = 0;
12103859Sml29623 	pll_cfg_l.value = 0;
12114977Sraghus 	pll_sts_l.value = 0;
12123859Sml29623 	test_cfg.value = 0;
12133859Sml29623 
12144977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
12154977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
12163859Sml29623 		/* 0x0E01 */
12173859Sml29623 		tx_cfg_l.bits.entx = 1;
12183859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
12193859Sml29623 
12203859Sml29623 		/* 0x9101 */
12213859Sml29623 		rx_cfg_l.bits.enrx = 1;
12223859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
12233859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
12243859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
12253859Sml29623 
12263859Sml29623 		/* 0x0008 */
12273859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12283859Sml29623 
12293859Sml29623 		/* Set loopback mode if necessary */
12303859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
12313859Sml29623 			tx_cfg_l.bits.entest = 1;
12323859Sml29623 			rx_cfg_l.bits.entest = 1;
12333859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
12343859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
12353859Sml29623 				ESR_N2_DEV_ADDR,
12363859Sml29623 				ESR_N2_TEST_CFG_REG, test_cfg.value))
12373859Sml29623 				!= NXGE_OK)
12383859Sml29623 			goto fail;
12393859Sml29623 		}
12403859Sml29623 
12413859Sml29623 		/* Use default PLL value */
12423859Sml29623 
12434977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
12444977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
12453859Sml29623 
12463859Sml29623 		/* 0x0E21 */
12473859Sml29623 		tx_cfg_l.bits.entx = 1;
12483859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
12493859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
12503859Sml29623 
12513859Sml29623 		/* 0x9121 */
12523859Sml29623 		rx_cfg_l.bits.enrx = 1;
12533859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
12543859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
12553859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
12563859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
12573859Sml29623 
12584977Sraghus 		if (portn == 0) {
12594977Sraghus 			/* 0x8 */
12604977Sraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12614977Sraghus 		}
12623859Sml29623 
12633859Sml29623 		/* MPY = 0x100 */
12643859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
12653859Sml29623 
12663859Sml29623 		/* Set PLL */
12673859Sml29623 		pll_cfg_l.bits.enpll = 1;
12684977Sraghus 		pll_sts_l.bits.enpll = 1;
12693859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
12703859Sml29623 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
12713859Sml29623 				!= NXGE_OK)
12723859Sml29623 			goto fail;
12734977Sraghus 
12744977Sraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
12754977Sraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
12764977Sraghus 			goto fail;
12774977Sraghus 
12784977Sraghus #ifdef  NXGE_DEBUG
12794977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12804977Sraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
12814977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12824977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
12834977Sraghus 		    portn, pll_cfg_l.value, cfg.value));
12844977Sraghus 
12854977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
12864977Sraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
12874977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12884977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
12894977Sraghus 		    portn, pll_sts_l.value, cfg.value));
12904977Sraghus #endif
12914977Sraghus 
12924977Sraghus 		/* Set loopback mode if necessary */
12934977Sraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
12944977Sraghus 			tx_cfg_l.bits.entest = 1;
12954977Sraghus 			rx_cfg_l.bits.entest = 1;
12964977Sraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
12974977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12984977Sraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
12994977Sraghus 			    portn, test_cfg.value));
13004977Sraghus 			if ((status = nxge_mdio_write(nxgep, portn,
13014977Sraghus 			    ESR_N2_DEV_ADDR,
13024977Sraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
13034977Sraghus 				goto fail;
13044977Sraghus 			}
13054977Sraghus 		}
13063859Sml29623 	} else {
13073859Sml29623 		goto fail;
13083859Sml29623 	}
13093859Sml29623 
13103859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
13113859Sml29623 
13123859Sml29623 	NXGE_DELAY(20);
13133859Sml29623 
13143859Sml29623 	/* init TX channels */
13153859Sml29623 	for (chan = 0; chan < 4; chan++) {
13163859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13173859Sml29623 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
13183859Sml29623 				!= NXGE_OK)
13193859Sml29623 			goto fail;
13203859Sml29623 
13213859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13223859Sml29623 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
13233859Sml29623 				!= NXGE_OK)
13243859Sml29623 			goto fail;
13254977Sraghus 
13264977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13274977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
13284977Sraghus 		    portn, chan, tx_cfg_l.value));
13294977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13304977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
13314977Sraghus 		    portn, chan, tx_cfg_h.value));
13323859Sml29623 	}
13333859Sml29623 
13343859Sml29623 	/* init RX channels */
13353859Sml29623 	for (chan = 0; chan < 4; chan++) {
13363859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13373859Sml29623 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
13383859Sml29623 				!= NXGE_OK)
13393859Sml29623 			goto fail;
13403859Sml29623 
13413859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13423859Sml29623 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
13433859Sml29623 				!= NXGE_OK)
13443859Sml29623 			goto fail;
13454977Sraghus 
13464977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13474977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
13484977Sraghus 		    portn, chan, rx_cfg_l.value));
13494977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13504977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
13514977Sraghus 		    portn, chan, rx_cfg_h.value));
13523859Sml29623 	}
13533859Sml29623 
13543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
13553859Sml29623 			portn));
13563859Sml29623 
13573859Sml29623 	return (NXGE_OK);
13583859Sml29623 fail:
13595572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13605572Ssbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
13615572Ssbehera 	    portn));
13623859Sml29623 
13633859Sml29623 	return (status);
13643859Sml29623 }
13653859Sml29623 
13664732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
13674732Sdavemq 
13684732Sdavemq static nxge_status_t
13694732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
13703859Sml29623 {
13713859Sml29623 	npi_handle_t		handle;
13723859Sml29623 	uint8_t			portn;
13733859Sml29623 	int			chan;
13743859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
13753859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
13763859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
13773859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
13783859Sml29623 	uint64_t		val;
13793859Sml29623 	uint16_t		val16l;
13803859Sml29623 	uint16_t		val16h;
13813859Sml29623 	nxge_status_t		status = NXGE_OK;
13823859Sml29623 
13833859Sml29623 	portn = nxgep->mac.portnum;
13843859Sml29623 
13853859Sml29623 	if ((portn != 0) && (portn != 1))
13863859Sml29623 		return (NXGE_OK);
13873859Sml29623 
13884732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13894732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
13903859Sml29623 
13913859Sml29623 	handle = nxgep->npi_handle;
13924732Sdavemq 	switch (portn) {
13934732Sdavemq 	case 0:
1394*6028Ssbehera 		/* Reset Serdes */
1395*6028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
1396*6028Ssbehera 		NXGE_DELAY(20);
1397*6028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
1398*6028Ssbehera 		NXGE_DELAY(2000);
1399*6028Ssbehera 
1400*6028Ssbehera 		/* Configure Serdes to 10G mode */
1401*6028Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1402*6028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
1403*6028Ssbehera 
14044732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
14054732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
14064732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
14074732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
14084732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
14094732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
14104732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14114732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14124732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
14134732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
14144732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
14154732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
14164732Sdavemq 
14174732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
14184732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
14194732Sdavemq 			ESR_REG_WR(handle,
14204732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
14214732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
14224732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
14234732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
14244732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
14254732Sdavemq 		} else {
14264732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
14273859Sml29623 		}
14284732Sdavemq 		break;
14294732Sdavemq 	case 1:
1430*6028Ssbehera 		/* Reset Serdes */
1431*6028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
1432*6028Ssbehera 		NXGE_DELAY(20);
1433*6028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
1434*6028Ssbehera 		NXGE_DELAY(2000);
1435*6028Ssbehera 
1436*6028Ssbehera 		/* Configure Serdes to 10G mode */
1437*6028Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1438*6028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
1439*6028Ssbehera 
14404732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
14414732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
14424732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
14434732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
14444732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
14454732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
14464732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14474732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14484732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
14494732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
14504732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
14514732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
14524732Sdavemq 
14534732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
14544732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
14554732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
14564732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
14574732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
14584732Sdavemq 		} else {
14594732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
14603859Sml29623 		}
14614732Sdavemq 		break;
14624732Sdavemq 	default:
14634732Sdavemq 		/* Nothing to do here */
14644732Sdavemq 		goto done;
14654732Sdavemq 	}
14664732Sdavemq 
14674732Sdavemq 	/* init TX RX channels */
14684732Sdavemq 	for (chan = 0; chan < 4; chan++) {
14694732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
14704732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
14714732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
14723859Sml29623 			goto fail;
14734732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
14744732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
14754732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
14763859Sml29623 			goto fail;
14773859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
14784732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
14794732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
14803859Sml29623 			goto fail;
14813859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
14824732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
14834732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
14844732Sdavemq 			goto fail;
14854732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
14864732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
14874732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
14884732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
14894732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
14904732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
14914732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
14924732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
14934732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
14944732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
14954732Sdavemq 			goto fail;
14964732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
14974732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
14984732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
14994732Sdavemq 			goto fail;
15004732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15014732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
15024732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
15034732Sdavemq 			goto fail;
15044732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15054732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
15064732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
15073859Sml29623 			goto fail;
15083859Sml29623 		}
15093859Sml29623 
15104732Sdavemq 	/* Apply Tx core reset */
15114732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
15124732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
15134732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
15144732Sdavemq 		goto fail;
15154732Sdavemq 
15164732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15174732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
15184732Sdavemq 	    NXGE_OK)
15194732Sdavemq 		goto fail;
15204732Sdavemq 
15214732Sdavemq 	NXGE_DELAY(200);
15224732Sdavemq 
15234732Sdavemq 	/* Apply Rx core reset */
15244732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15254732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
15264732Sdavemq 	    NXGE_OK)
15274732Sdavemq 		goto fail;
15284732Sdavemq 
15294732Sdavemq 	NXGE_DELAY(200);
15304732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15314732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
15324732Sdavemq 		goto fail;
15334732Sdavemq 
15344732Sdavemq 	NXGE_DELAY(200);
15354732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
15364732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
15374732Sdavemq 	    &val16l)) != NXGE_OK)
15384732Sdavemq 		goto fail;
15394732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15404732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
15414732Sdavemq 		goto fail;
15424732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
15434732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15445196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
15455196Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
15465196Ssbehera 		    portn, val16l, val16h));
15474732Sdavemq 	}
15484732Sdavemq 
15494732Sdavemq 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
15504732Sdavemq 
15514732Sdavemq 	if (portn == 0) {
15524732Sdavemq 		if ((val & ESR_SIG_P0_BITS_MASK) !=
15533859Sml29623 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
15543859Sml29623 					ESR_SIG_XSERDES_RDY_P0 |
15553859Sml29623 					ESR_SIG_XDETECT_P0_CH3 |
15563859Sml29623 					ESR_SIG_XDETECT_P0_CH2 |
15573859Sml29623 					ESR_SIG_XDETECT_P0_CH1 |
15583859Sml29623 					ESR_SIG_XDETECT_P0_CH0)) {
15594732Sdavemq 			goto fail;
15604732Sdavemq 		}
15614732Sdavemq 	} else if (portn == 1) {
15624732Sdavemq 		if ((val & ESR_SIG_P1_BITS_MASK) !=
15633859Sml29623 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
15643859Sml29623 					ESR_SIG_XSERDES_RDY_P1 |
15653859Sml29623 					ESR_SIG_XDETECT_P1_CH3 |
15663859Sml29623 					ESR_SIG_XDETECT_P1_CH2 |
15673859Sml29623 					ESR_SIG_XDETECT_P1_CH1 |
15683859Sml29623 					ESR_SIG_XDETECT_P1_CH0)) {
15693859Sml29623 			goto fail;
15703859Sml29623 		}
15713859Sml29623 	}
15723859Sml29623 
15733859Sml29623 done:
15744732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15754732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
15764732Sdavemq 
15773859Sml29623 	return (NXGE_OK);
15783859Sml29623 fail:
15795572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15804732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
15814732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
15823859Sml29623 
15833859Sml29623 	return (status);
15843859Sml29623 }
15853859Sml29623 
15864732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
15874732Sdavemq 
15884732Sdavemq static nxge_status_t
15894732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
15903859Sml29623 {
15914732Sdavemq 	npi_handle_t		handle;
15924732Sdavemq 	uint8_t			portn;
15935196Ssbehera 	int			chan;
15945196Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
15955196Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
15965196Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
15975196Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
15984732Sdavemq 	uint64_t		val;
15995196Ssbehera 	uint16_t		val16l;
16005196Ssbehera 	uint16_t		val16h;
16015196Ssbehera 	nxge_status_t		status = NXGE_OK;
16023859Sml29623 
16033859Sml29623 	portn = nxgep->mac.portnum;
16044732Sdavemq 
16054732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16064732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
16074732Sdavemq 
16084732Sdavemq 	handle = nxgep->npi_handle;
16094732Sdavemq 
16104732Sdavemq 	switch (portn) {
16114732Sdavemq 	case 0:
16125196Ssbehera 		/* Assert the reset register */
16135196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16145196Ssbehera 		val |= ESR_RESET_0;
16155196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16165196Ssbehera 
16175196Ssbehera 		/* Set the PLL register to 0x79 */
16185196Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
16195196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
16205196Ssbehera 
16215196Ssbehera 		/* Set the control register to 0x249249f */
16225196Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
16235196Ssbehera 
16245196Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
16255196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16265196Ssbehera 			/* Set pad loopback modes 0xaa */
16275196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
16285196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
16295196Ssbehera 		} else {
16305196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
16315196Ssbehera 		}
16325196Ssbehera 
16335196Ssbehera 		/* Deassert the reset register */
16345196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16355196Ssbehera 		val &= ~ESR_RESET_0;
16365196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16374732Sdavemq 		break;
16385196Ssbehera 
16394732Sdavemq 	case 1:
16405196Ssbehera 		/* Assert the reset register */
16415196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16425196Ssbehera 		val |= ESR_RESET_1;
16435196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16445196Ssbehera 
16455196Ssbehera 		/* Set PLL register to 0x79 */
16465196Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
16475196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
16485196Ssbehera 
16495196Ssbehera 		/* Set the control register to 0x249249f */
16505196Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
16515196Ssbehera 
16525196Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
16535196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16545196Ssbehera 			/* Set pad loopback mode 0xaa */
16555196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
16565196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
16575196Ssbehera 		} else {
16585196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
16595196Ssbehera 		}
16605196Ssbehera 
16615196Ssbehera 		/* Deassert the reset register */
16625196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16635196Ssbehera 		val &= ~ESR_RESET_1;
16645196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16654732Sdavemq 		break;
16665196Ssbehera 
16674732Sdavemq 	default:
16685196Ssbehera 		/* Nothing to do here */
16695196Ssbehera 		goto done;
16705196Ssbehera 	}
16715196Ssbehera 
16725196Ssbehera 	/* init TX RX channels */
16735196Ssbehera 	for (chan = 0; chan < 4; chan++) {
16745196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
16755196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
16765196Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
16775196Ssbehera 			goto fail;
16785196Ssbehera 		}
16795196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
16805196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
16815196Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
16825196Ssbehera 			goto fail;
16835196Ssbehera 		}
16845196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
16855196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
16865196Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
16875196Ssbehera 			goto fail;
16885196Ssbehera 		}
16895196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
16905196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
16915196Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
16925196Ssbehera 			goto fail;
16935196Ssbehera 		}
16945196Ssbehera 
16955196Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
16965196Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
16975196Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
16985196Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
16995196Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
17005196Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
17015196Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
17025196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17035196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17045196Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
17055196Ssbehera 			goto fail;
17065196Ssbehera 		}
17075196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17085196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17095196Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
17105196Ssbehera 			goto fail;
17115196Ssbehera 		}
17125196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17135196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17145196Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
17155196Ssbehera 			goto fail;
17165196Ssbehera 		}
17175196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17185196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17195196Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
17205196Ssbehera 			goto fail;
17215196Ssbehera 		}
17225196Ssbehera 	}
17235196Ssbehera 
17245196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17255196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
17264732Sdavemq 		goto fail;
17273859Sml29623 	}
17285196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17295196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
17305196Ssbehera 		goto fail;
17315196Ssbehera 	}
17325196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17335196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
17345196Ssbehera 		goto fail;
17355196Ssbehera 	}
17365196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17375196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
17385196Ssbehera 		goto fail;
17395196Ssbehera 	}
17405196Ssbehera 
17415196Ssbehera 	/* Apply Tx core reset */
17425196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17435196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
17445196Ssbehera 		goto fail;
17455196Ssbehera 	}
17465196Ssbehera 
17475196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17485196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
17495196Ssbehera 	    NXGE_OK) {
17505196Ssbehera 		goto fail;
17515196Ssbehera 	}
17525196Ssbehera 
17535196Ssbehera 	NXGE_DELAY(200);
17545196Ssbehera 
17555196Ssbehera 	/* Apply Rx core reset */
17565196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17575196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
17585196Ssbehera 	    NXGE_OK) {
17595196Ssbehera 		goto fail;
17605196Ssbehera 	}
17615196Ssbehera 
17625196Ssbehera 	NXGE_DELAY(200);
17635196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17645196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
17655196Ssbehera 		goto fail;
17665196Ssbehera 	}
17675196Ssbehera 
17685196Ssbehera 	NXGE_DELAY(200);
17695196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17705196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
17715196Ssbehera 		goto fail;
17725196Ssbehera 	}
17735196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17745196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
17755196Ssbehera 		goto fail;
17765196Ssbehera 	}
17775196Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
17785196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17795196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
17805196Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
17815196Ssbehera 		status = NXGE_ERROR;
17825196Ssbehera 		goto fail;
17835196Ssbehera 	}
17845196Ssbehera 
17855196Ssbehera 	NXGE_DELAY(200);
17865196Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
17875196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17885196Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
17895196Ssbehera 	    "val 0x%x", portn, val));
17905196Ssbehera 	if (portn == 0) {
17915196Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
17925196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
17935196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17945196Ssbehera 			    "nxge_neptune_serdes_init: "
17955196Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
17965196Ssbehera 			    portn, (val & ESR_SIG_P0_BITS_MASK)));
17975196Ssbehera 			status = NXGE_ERROR;
17985196Ssbehera 			goto fail;
17995196Ssbehera 		}
18005196Ssbehera 	} else if (portn == 1) {
18015196Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
18025196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
18035196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18045196Ssbehera 			    "nxge_neptune_serdes_init: "
18055196Ssbehera 			    "Failed to get Serdes up for port<%d> val 0x%x",
18065196Ssbehera 			    portn, (val & ESR_SIG_P1_BITS_MASK)));
18075196Ssbehera 			status = NXGE_ERROR;
18085196Ssbehera 			goto fail;
18095196Ssbehera 		}
18105196Ssbehera 	}
18115196Ssbehera done:
18124732Sdavemq 
18134732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18144732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
18153859Sml29623 	return (NXGE_OK);
18164732Sdavemq fail:
18175196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18184732Sdavemq 	    "nxge_1G_serdes_init: "
18194732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
18204732Sdavemq 	    portn));
18214732Sdavemq 
18225196Ssbehera 	return (status);
18233859Sml29623 }
18243859Sml29623 
18255572Ssbehera /* Initialize the BCM 8704 xcvr */
18264732Sdavemq 
18274732Sdavemq static nxge_status_t
18285572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
18293859Sml29623 {
18303859Sml29623 	uint16_t		val;
18313859Sml29623 #ifdef	NXGE_DEBUG
18323859Sml29623 	uint8_t			portn;
18333859Sml29623 	uint16_t		val1;
18343859Sml29623 #endif
18353859Sml29623 	uint8_t			phy_port_addr;
18363859Sml29623 	pmd_tx_control_t	tx_ctl;
18373859Sml29623 	control_t		ctl;
18383859Sml29623 	phyxs_control_t		phyxs_ctl;
18393859Sml29623 	pcs_control_t		pcs_ctl;
18403859Sml29623 	uint32_t		delay = 0;
18413859Sml29623 	optics_dcntr_t		op_ctr;
18423859Sml29623 	nxge_status_t		status = NXGE_OK;
18433859Sml29623 #ifdef	NXGE_DEBUG
18443859Sml29623 	portn = nxgep->mac.portnum;
18453859Sml29623 #endif
18465572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
18474732Sdavemq 	    portn));
18484732Sdavemq 
18494732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
18504732Sdavemq 
18514732Sdavemq 	/* Reset the transceiver */
18524732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
18534732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
18544732Sdavemq 		goto fail;
18554732Sdavemq 
18564732Sdavemq 	phyxs_ctl.bits.reset = 1;
18574732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
18584732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
18594732Sdavemq 		goto fail;
18604732Sdavemq 
18614732Sdavemq 	do {
18624732Sdavemq 		drv_usecwait(500);
18634732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
18644732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
18654732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
18664732Sdavemq 			goto fail;
18674732Sdavemq 		delay++;
18684732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
18694732Sdavemq 	if (delay == 100) {
18704732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
18714732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
18724732Sdavemq 		status = NXGE_ERROR;
18734732Sdavemq 		goto fail;
18744732Sdavemq 	}
18754732Sdavemq 
18764732Sdavemq 	/* Set to 0x7FBF */
18774732Sdavemq 	ctl.value = 0;
18784732Sdavemq 	ctl.bits.res1 = 0x3F;
18794732Sdavemq 	ctl.bits.optxon_lvl = 1;
18804732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
18814732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
18824732Sdavemq 	ctl.bits.optxflt_lvl = 1;
18834732Sdavemq 	ctl.bits.opprflt_lvl = 1;
18844732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
18854732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
18864732Sdavemq 	ctl.bits.optxrst_lvl = 1;
18874732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
18884732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
18894732Sdavemq 	    != NXGE_OK)
18904732Sdavemq 		goto fail;
18914732Sdavemq 
18924732Sdavemq 	/* Set to 0x164 */
18934732Sdavemq 	tx_ctl.value = 0;
18944732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
18954732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
18964732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
18974732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
18984732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
18994732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
19004732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
19014732Sdavemq 		goto fail;
19024732Sdavemq 	/*
19034732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
19044732Sdavemq 	 * back these registers twice after written.
19054732Sdavemq 	 */
19064732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19074732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
19084732Sdavemq 	    != NXGE_OK)
19094732Sdavemq 		goto fail;
19104732Sdavemq 
19114732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19124732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
19134732Sdavemq 	    != NXGE_OK)
19144732Sdavemq 		goto fail;
19154732Sdavemq 
19164732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19174732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
19184732Sdavemq 	    != NXGE_OK)
19194732Sdavemq 		goto fail;
19204732Sdavemq 
19214732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19224732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
19234732Sdavemq 	    != NXGE_OK)
19244732Sdavemq 		goto fail;
19254732Sdavemq 
19264732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
19274732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19284732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
19294732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
19304732Sdavemq 		goto fail;
19315553Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
19325553Smisaki 		op_ctr.bits.gpio_sel = 0x1;
19335553Smisaki 	} else {
19345553Smisaki 		op_ctr.bits.gpio_sel = 0x3;
19355553Smisaki 	}
19364732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
19374732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
19384732Sdavemq 	    op_ctr.value)) != NXGE_OK)
19394732Sdavemq 		goto fail;
19404732Sdavemq 
19414732Sdavemq 	NXGE_DELAY(1000000);
19424732Sdavemq 
19434732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
19444732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19454732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
19464732Sdavemq 	    != NXGE_OK)
19474732Sdavemq 		goto fail;
19484732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
19494732Sdavemq 		pcs_ctl.bits.loopback = 1;
19504732Sdavemq 	else
19514732Sdavemq 		pcs_ctl.bits.loopback = 0;
19524732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
19534732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
19544732Sdavemq 	    != NXGE_OK)
19554732Sdavemq 		goto fail;
19564732Sdavemq 
19574732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
19584732Sdavemq 	if (status != NXGE_OK)
19594732Sdavemq 		goto fail;
19604732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19614732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
19624732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
19634732Sdavemq 	if (status != NXGE_OK)
19644732Sdavemq 		goto fail;
19654732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19664732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
19674732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
19684732Sdavemq 	if (status != NXGE_OK)
19694732Sdavemq 		goto fail;
19704732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19714732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
19724732Sdavemq 
19734732Sdavemq #ifdef	NXGE_DEBUG
19744732Sdavemq 	/* Diagnose link issue if link is not up */
19754732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
19764732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
19774732Sdavemq 	    &val);
19784732Sdavemq 	if (status != NXGE_OK)
19794732Sdavemq 		goto fail;
19804732Sdavemq 
19814732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
19824732Sdavemq 				BCM8704_USER_DEV3_ADDR,
19834732Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
19844732Sdavemq 				&val);
19854732Sdavemq 	if (status != NXGE_OK)
19864732Sdavemq 		goto fail;
19874732Sdavemq 
19884732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
19894732Sdavemq 				BCM8704_USER_DEV3_ADDR,
19904732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
19914732Sdavemq 				&val1);
19924732Sdavemq 	if (status != NXGE_OK)
19934732Sdavemq 		goto fail;
19944732Sdavemq 
19954732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
19964732Sdavemq 				BCM8704_USER_DEV3_ADDR,
19974732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
19984732Sdavemq 				&val1);
19994732Sdavemq 	if (status != NXGE_OK)
20004732Sdavemq 		goto fail;
20014732Sdavemq 
20024732Sdavemq 	if (val != 0x3FC) {
20034732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
20044732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20054732Sdavemq 			    "Cable not connected to peer or bad"
20064732Sdavemq 			    " cable on port<%d>\n", portn));
20074732Sdavemq 		} else if (val == 0x639C) {
20084732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20094732Sdavemq 			    "Optical module (XFP) is bad or absent"
20104732Sdavemq 			    " on port<%d>\n", portn));
20114732Sdavemq 		}
20124732Sdavemq 	}
20134732Sdavemq #endif
20144732Sdavemq 
20155572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
20165572Ssbehera 	    portn));
20175572Ssbehera 	return (NXGE_OK);
20185572Ssbehera 
20195572Ssbehera fail:
20205572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20215572Ssbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
20225572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
20235572Ssbehera 	return (NXGE_ERROR);
20245572Ssbehera }
20255572Ssbehera 
20265572Ssbehera /* Initialize the BCM 8706 Transceiver */
20275572Ssbehera 
20285572Ssbehera static nxge_status_t
20295572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
20305572Ssbehera {
20315572Ssbehera 	uint8_t			phy_port_addr;
20325572Ssbehera 	phyxs_control_t		phyxs_ctl;
20335572Ssbehera 	pcs_control_t		pcs_ctl;
20345572Ssbehera 	uint32_t		delay = 0;
20355572Ssbehera 	optics_dcntr_t		op_ctr;
20365572Ssbehera 	nxge_status_t		status = NXGE_OK;
20375572Ssbehera #ifdef	NXGE_DEBUG
20385572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
20395572Ssbehera #endif
20405572Ssbehera 
20415572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
20425572Ssbehera 	    portn));
20435572Ssbehera 
20445572Ssbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
20455572Ssbehera 
20465572Ssbehera 	/* Reset the transceiver */
20475572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20485572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
20495572Ssbehera 		goto fail;
20505572Ssbehera 
20515572Ssbehera 	phyxs_ctl.bits.reset = 1;
20525572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
20535572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
20545572Ssbehera 		goto fail;
20555572Ssbehera 	do {
20565572Ssbehera 		drv_usecwait(500);
20575572Ssbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20585572Ssbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
20595572Ssbehera 		    &phyxs_ctl.value)) != NXGE_OK)
20605572Ssbehera 			goto fail;
20615572Ssbehera 		delay++;
20625572Ssbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
20635572Ssbehera 
20645572Ssbehera 	if (delay == 100) {
20655572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
20665572Ssbehera 		    "failed to reset Transceiver on port<%d>", portn));
20675572Ssbehera 		status = NXGE_ERROR;
20685572Ssbehera 		goto fail;
20695572Ssbehera 	}
20705572Ssbehera 
20715572Ssbehera 	NXGE_DELAY(1000000);
20725572Ssbehera 
20735572Ssbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
20745572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20755572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
20765572Ssbehera 	    != NXGE_OK)
20775572Ssbehera 		goto fail;
20785572Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
20795572Ssbehera 		pcs_ctl.bits.loopback = 1;
20805572Ssbehera 	else
20815572Ssbehera 		pcs_ctl.bits.loopback = 0;
20825572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
20835572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
20845572Ssbehera 	    != NXGE_OK)
20855572Ssbehera 		goto fail;
20865572Ssbehera 
20875572Ssbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
20885572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20895572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
20905572Ssbehera 	    &op_ctr.value)) != NXGE_OK)
20915572Ssbehera 		goto fail;
20925572Ssbehera 	op_ctr.bits.gpio_sel = 0x3;
20935572Ssbehera 	op_ctr.bits.res2 = 0x1;
20945572Ssbehera 
20955572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
20965572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
20975572Ssbehera 	    op_ctr.value)) != NXGE_OK)
20985572Ssbehera 		goto fail;
20995572Ssbehera 
21005572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
21015572Ssbehera 	    portn));
21025572Ssbehera 	return (NXGE_OK);
21035572Ssbehera 
21045572Ssbehera fail:
21055572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21065572Ssbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
21075572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
21085572Ssbehera 	return (status);
21095572Ssbehera }
21105572Ssbehera 
21115572Ssbehera /* Initialize the 10G Transceiver */
21125572Ssbehera 
21135572Ssbehera static nxge_status_t
21145572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
21155572Ssbehera {
21165572Ssbehera 	p_nxge_stats_t		statsp;
21175572Ssbehera 	nxge_status_t		status = NXGE_OK;
21185572Ssbehera #ifdef	NXGE_DEBUG
21195572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
21205572Ssbehera #endif
21215572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
21225572Ssbehera 	    portn));
21235572Ssbehera 
21245572Ssbehera 	statsp = nxgep->statsp;
21255572Ssbehera 
21265572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
21275572Ssbehera 		goto done;
21285572Ssbehera 	}
21295572Ssbehera 
21305572Ssbehera 	/* Disable Link LEDs */
21315572Ssbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
21325572Ssbehera 		goto fail;
21335572Ssbehera 
21345572Ssbehera 	/* Set Clause 45 */
21355572Ssbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
21365572Ssbehera 
21375572Ssbehera 	switch (nxgep->chip_id) {
21385572Ssbehera 	case BCM8704_CHIP_ID:
21395572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21405572Ssbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
21415572Ssbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
21425572Ssbehera 		break;
21435572Ssbehera 	case BCM8706_CHIP_ID:
21445572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21455572Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
21465572Ssbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
21475572Ssbehera 		break;
21485572Ssbehera 	default:
21495572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
21505572Ssbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
21515572Ssbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
21525572Ssbehera 		goto fail;
21535572Ssbehera 	}
21545572Ssbehera 
21555572Ssbehera 	if (status != NXGE_OK) {
21565572Ssbehera 		goto fail;
21575572Ssbehera 	}
21584977Sraghus done:
21594732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
21604732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
21614732Sdavemq 
21624732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
21634732Sdavemq 	    portn));
21644732Sdavemq 	return (NXGE_OK);
21654732Sdavemq 
21664732Sdavemq fail:
21675572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21684732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
21695572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
21705572Ssbehera 	return (NXGE_ERROR);
21714732Sdavemq }
21724732Sdavemq 
21734732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
21744732Sdavemq 
21754732Sdavemq static nxge_status_t
21764732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
21774732Sdavemq {
21784732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
21794732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
21804732Sdavemq 	nxge_status_t		status = NXGE_OK;
21814732Sdavemq 
21824977Sraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
21834977Sraghus 		statsp->mac_stats.cap_1000fdx =
21844977Sraghus 		    param_arr[param_anar_1000fdx].value;
21854977Sraghus 		goto done;
21864977Sraghus 	}
21874977Sraghus 
21884732Sdavemq 	/* Set Clause 22 */
21894732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
21904732Sdavemq 
21914732Sdavemq 	/* Set capability flags */
21924732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
21934977Sraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
21944977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
21954977Sraghus 		statsp->mac_stats.cap_100fdx =
21964977Sraghus 		    param_arr[param_anar_100fdx].value;
21974977Sraghus 		statsp->mac_stats.cap_10fdx =
21984977Sraghus 		    param_arr[param_anar_10fdx].value;
21994977Sraghus 	}
22004732Sdavemq 
22014732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
22024977Sraghus done:
22034732Sdavemq 	return (status);
22044732Sdavemq }
22054732Sdavemq 
22064732Sdavemq /* Initialize transceiver */
22074732Sdavemq 
22084732Sdavemq nxge_status_t
22094732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
22104732Sdavemq {
22114732Sdavemq 	p_nxge_stats_t		statsp;
22124732Sdavemq #ifdef	NXGE_DEBUG
22134732Sdavemq 	uint8_t			portn;
22144732Sdavemq #endif
22154732Sdavemq 
22164732Sdavemq 	nxge_status_t		status = NXGE_OK;
22174732Sdavemq #ifdef	NXGE_DEBUG
22184732Sdavemq 	portn = nxgep->mac.portnum;
22194732Sdavemq #endif
22203859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
22213859Sml29623 	statsp = nxgep->statsp;
22223859Sml29623 
22233859Sml29623 	/*
22243859Sml29623 	 * Initialize the xcvr statistics.
22253859Sml29623 	 */
22263859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
22273859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
22283859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
22293859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
22303859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
22313859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
22323859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
22333859Sml29623 	statsp->mac_stats.cap_pause = 0;
22343859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
22353859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
22363859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
22373859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
22383859Sml29623 
22393859Sml29623 	/*
22403859Sml29623 	 * Initialize the link statistics.
22413859Sml29623 	 */
22423859Sml29623 	statsp->mac_stats.link_T4 = 0;
22433859Sml29623 	statsp->mac_stats.link_asmpause = 0;
22443859Sml29623 	statsp->mac_stats.link_pause = 0;
22453859Sml29623 
22464732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
22474732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
22483859Sml29623 		if (status != NXGE_OK)
22493859Sml29623 			goto fail;
22504732Sdavemq 		statsp->mac_stats.xcvr_inits++;
22513859Sml29623 	}
22523859Sml29623 
22534732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
22544732Sdavemq 	    portn));
22553859Sml29623 	return (NXGE_OK);
22563859Sml29623 
22573859Sml29623 fail:
22583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
22594732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
22604732Sdavemq 	    portn));
22613859Sml29623 	return (status);
22623859Sml29623 }
22633859Sml29623 
22644977Sraghus /* Look for transceiver type */
22654977Sraghus 
22664977Sraghus nxge_status_t
22674977Sraghus nxge_xcvr_find(p_nxge_t nxgep)
22684977Sraghus {
22695196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
22705196Ssbehera 	    nxgep->mac.portnum));
22714977Sraghus 
22724977Sraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
22734977Sraghus 		return (NXGE_ERROR);
22744977Sraghus 
22754977Sraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
22764977Sraghus 		return (NXGE_ERROR);
22774977Sraghus 
22784977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
22794977Sraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
22804977Sraghus 	return (NXGE_OK);
22814977Sraghus }
22823859Sml29623 
22833859Sml29623 /* Initialize the TxMAC sub-block */
22843859Sml29623 
22853859Sml29623 nxge_status_t
22863859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
22873859Sml29623 {
22883859Sml29623 	npi_attr_t		ap;
22893859Sml29623 	uint8_t			portn;
22903859Sml29623 	nxge_port_mode_t	portmode;
22913859Sml29623 	nxge_port_t		portt;
22923859Sml29623 	npi_handle_t		handle;
22933859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
22943859Sml29623 
22953859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
22963859Sml29623 	portt    = nxgep->mac.porttype;
22973859Sml29623 	handle   = nxgep->npi_handle;
22983859Sml29623 	portmode = nxgep->mac.portmode;
22993859Sml29623 
23003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
23013859Sml29623 			portn));
23023859Sml29623 
23033859Sml29623 	/* Set Max and Min Frame Size */
23043859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
23053859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
2306*6028Ssbehera 		    MAC_PORT_FRAME_SIZE, 64, nxge_jumbo_mtu, rs);
23073859Sml29623 	} else {
2308*6028Ssbehera 		/*
2309*6028Ssbehera 		 * Set the maxframe size to 1522 (1518 + 4) to account for
2310*6028Ssbehera 		 * VLAN tagged packets
2311*6028Ssbehera 		 */
23123859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
2313*6028Ssbehera 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
23143859Sml29623 	}
23153859Sml29623 
23163859Sml29623 	if (rs != NPI_SUCCESS)
23173859Sml29623 		goto fail;
23183859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value ||
23193859Sml29623 		nxgep->mac.is_jumbo == B_TRUE)
2320*6028Ssbehera 		nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu;
23213859Sml29623 	else
23223859Sml29623 		nxgep->mac.maxframesize = 0x5EE + 4;
23233859Sml29623 	nxgep->mac.minframesize = 64;
23243859Sml29623 
23253859Sml29623 	if (portt == PORT_TYPE_XMAC) {
23263859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
23273859Sml29623 				0)) != NPI_SUCCESS)
23283859Sml29623 			goto fail;
23293859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
23303859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
23314977Sraghus 		    (portmode == PORT_10G_COPPER) ||
23324977Sraghus 		    (portmode == PORT_10G_SERDES)) {
23333859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
23343859Sml29623 					XGMII_IPG_12_15, rs);
23353859Sml29623 			if (rs != NPI_SUCCESS)
23363859Sml29623 				goto fail;
23373859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
23383859Sml29623 		} else {
23393859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
23403859Sml29623 					MII_GMII_IPG_12, rs);
23413859Sml29623 			if (rs != NPI_SUCCESS)
23423859Sml29623 				goto fail;
23433859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
23443859Sml29623 		}
23453859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
23463859Sml29623 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
23473859Sml29623 			goto fail;
23483859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
23493859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
23503859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
23513859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
23523859Sml29623 
23533859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
23543859Sml29623 							!= NPI_SUCCESS)
23553859Sml29623 			goto fail;
23563859Sml29623 
23573859Sml29623 	} else {
23583859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
23593859Sml29623 				0)) != NPI_SUCCESS)
23603859Sml29623 			goto fail;
23613859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
23623859Sml29623 
23633859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
23643859Sml29623 				rs);
23653859Sml29623 		if (rs != NPI_SUCCESS)
23663859Sml29623 			goto fail;
23673859Sml29623 		nxgep->mac.ctrltype = 0x8808;
23683859Sml29623 
23693859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
23703859Sml29623 		if (rs != NPI_SUCCESS)
23713859Sml29623 			goto fail;
23723859Sml29623 		nxgep->mac.pa_size = 0x7;
23733859Sml29623 
23743859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
23753859Sml29623 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
23763859Sml29623 			goto fail;
23773859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
23783859Sml29623 	}
23793859Sml29623 
23803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
23813859Sml29623 			portn));
23823859Sml29623 
23833859Sml29623 	return (NXGE_OK);
23843859Sml29623 fail:
23853859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23863859Sml29623 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
23873859Sml29623 					portn));
23883859Sml29623 
23893859Sml29623 	return (NXGE_ERROR | rs);
23903859Sml29623 }
23913859Sml29623 
23923859Sml29623 /* Initialize the RxMAC sub-block */
23933859Sml29623 
23943859Sml29623 nxge_status_t
23953859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
23963859Sml29623 {
23973859Sml29623 	npi_attr_t		ap;
23983859Sml29623 	uint32_t		i;
23993859Sml29623 	uint16_t		hashtab_e;
24003859Sml29623 	p_hash_filter_t		hash_filter;
24013859Sml29623 	nxge_port_t		portt;
24023859Sml29623 	uint8_t			portn;
24033859Sml29623 	npi_handle_t		handle;
24043859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
24053859Sml29623 	uint16_t 		*addr16p;
24063859Sml29623 	uint16_t 		addr0, addr1, addr2;
24073859Sml29623 	xmac_rx_config_t	xconfig;
24083859Sml29623 	bmac_rx_config_t	bconfig;
24093859Sml29623 
24103859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
24113859Sml29623 
24123859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
24133859Sml29623 			portn));
24143859Sml29623 	handle = nxgep->npi_handle;
24153859Sml29623 	portt = nxgep->mac.porttype;
24163859Sml29623 
24173859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
24183859Sml29623 	addr0 = ntohs(addr16p[2]);
24193859Sml29623 	addr1 = ntohs(addr16p[1]);
24203859Sml29623 	addr2 = ntohs(addr16p[0]);
24213859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
24223859Sml29623 		rs);
24233859Sml29623 
24243859Sml29623 	if (rs != NPI_SUCCESS)
24253859Sml29623 		goto fail;
24263859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
24273859Sml29623 	if (rs != NPI_SUCCESS)
24283859Sml29623 		goto fail;
24293859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
24303859Sml29623 	if (rs != NPI_SUCCESS)
24313859Sml29623 		goto fail;
24323859Sml29623 
24333859Sml29623 	/*
24343859Sml29623 	 * Load the multicast hash filter bits.
24353859Sml29623 	 */
24363859Sml29623 	hash_filter = nxgep->hash_filter;
24373859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
24383859Sml29623 		if (hash_filter != NULL) {
24393859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
24403859Sml29623 				(NMCFILTER_REGS - 1) - i];
24413859Sml29623 		} else {
24423859Sml29623 			hashtab_e = 0;
24433859Sml29623 		}
24443859Sml29623 
24453859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
24463859Sml29623 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
24473859Sml29623 			goto fail;
24483859Sml29623 	}
24493859Sml29623 
24503859Sml29623 	if (portt == PORT_TYPE_XMAC) {
24513859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
24523859Sml29623 				0)) != NPI_SUCCESS)
24533859Sml29623 			goto fail;
24543859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
24553859Sml29623 
24563859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
24573859Sml29623 
24583859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
24593859Sml29623 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
24603859Sml29623 			~CFG_XMAC_RX_STRIP_CRC;
24613859Sml29623 
24623859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
24633859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
24643859Sml29623 
24653859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
24663859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
24673859Sml29623 
24683859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
24693859Sml29623 
24703859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
24713859Sml29623 					xconfig)) != NPI_SUCCESS)
24723859Sml29623 			goto fail;
24733859Sml29623 		nxgep->mac.rx_config = xconfig;
24743859Sml29623 
24753859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
24763859Sml29623 
24773859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
24783859Sml29623 							!= NPI_SUCCESS)
24793859Sml29623 			goto fail;
24803859Sml29623 	} else {
24813859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
24823859Sml29623 
24833859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
24843859Sml29623 					0) != NPI_SUCCESS)
24853859Sml29623 			goto fail;
24863859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
24873859Sml29623 
24883859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
24893859Sml29623 			~CFG_BMAC_RX_STRIP_CRC;
24903859Sml29623 
24913859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
24923859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
24933859Sml29623 
24943859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
24953859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
24963859Sml29623 
24973859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
24983859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
24993859Sml29623 					bconfig)) != NPI_SUCCESS)
25003859Sml29623 			goto fail;
25013859Sml29623 		nxgep->mac.rx_config = bconfig;
25023859Sml29623 
25033859Sml29623 		/* Always enable comparison of mac unique address */
25043859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
25053859Sml29623 					!= NPI_SUCCESS)
25063859Sml29623 			goto fail;
25073859Sml29623 	}
25083859Sml29623 
25093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
25103859Sml29623 			portn));
25113859Sml29623 
25123859Sml29623 	return (NXGE_OK);
25133859Sml29623 
25143859Sml29623 fail:
25153859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
25163859Sml29623 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
25173859Sml29623 				portn));
25183859Sml29623 
25193859Sml29623 	return (NXGE_ERROR | rs);
25203859Sml29623 }
25213859Sml29623 
25223859Sml29623 /* Enable TXMAC */
25233859Sml29623 
25243859Sml29623 nxge_status_t
25253859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
25263859Sml29623 {
25273859Sml29623 	npi_handle_t	handle;
25283859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
25293859Sml29623 	nxge_status_t	status = NXGE_OK;
25303859Sml29623 
25313859Sml29623 	handle = nxgep->npi_handle;
25323859Sml29623 
25333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
25343859Sml29623 			nxgep->mac.portnum));
25353859Sml29623 
25363859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
25373859Sml29623 		goto fail;
25383859Sml29623 
25393859Sml29623 	/* based on speed */
25403859Sml29623 	nxgep->msg_min = ETHERMIN;
25413859Sml29623 
25423859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
25433859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
25443859Sml29623 						CFG_XMAC_TX)) != NPI_SUCCESS)
25453859Sml29623 			goto fail;
25463859Sml29623 	} else {
25473859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
25483859Sml29623 						CFG_BMAC_TX)) != NPI_SUCCESS)
25493859Sml29623 			goto fail;
25503859Sml29623 	}
25513859Sml29623 
25523859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
25533859Sml29623 			nxgep->mac.portnum));
25543859Sml29623 
25553859Sml29623 	return (NXGE_OK);
25563859Sml29623 fail:
25573859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
25583859Sml29623 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
25593859Sml29623 			nxgep->mac.portnum));
25603859Sml29623 	if (rs != NPI_SUCCESS)
25613859Sml29623 		return (NXGE_ERROR | rs);
25623859Sml29623 	else
25633859Sml29623 		return (status);
25643859Sml29623 }
25653859Sml29623 
25663859Sml29623 /* Disable TXMAC */
25673859Sml29623 
25683859Sml29623 nxge_status_t
25693859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
25703859Sml29623 {
25713859Sml29623 	npi_handle_t	handle;
25723859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
25733859Sml29623 
25743859Sml29623 	handle = nxgep->npi_handle;
25753859Sml29623 
25763859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
25773859Sml29623 			nxgep->mac.portnum));
25783859Sml29623 
25793859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
25803859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
25813859Sml29623 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
25823859Sml29623 			goto fail;
25833859Sml29623 	} else {
25843859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
25853859Sml29623 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
25863859Sml29623 			goto fail;
25873859Sml29623 	}
25883859Sml29623 
25893859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
25903859Sml29623 			nxgep->mac.portnum));
25913859Sml29623 	return (NXGE_OK);
25923859Sml29623 fail:
25933859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
25943859Sml29623 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
25953859Sml29623 			nxgep->mac.portnum));
25963859Sml29623 	return (NXGE_ERROR | rs);
25973859Sml29623 }
25983859Sml29623 
25993859Sml29623 /* Enable RXMAC */
26003859Sml29623 
26013859Sml29623 nxge_status_t
26023859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
26033859Sml29623 {
26043859Sml29623 	npi_handle_t	handle;
26053859Sml29623 	uint8_t 	portn;
26063859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
26073859Sml29623 	nxge_status_t	status = NXGE_OK;
26083859Sml29623 
26093859Sml29623 	handle = nxgep->npi_handle;
26103859Sml29623 	portn = nxgep->mac.portnum;
26113859Sml29623 
26123859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
26133859Sml29623 			portn));
26143859Sml29623 
26153859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
26163859Sml29623 		goto fail;
26173859Sml29623 
26183859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
26193859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
26203859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
26213859Sml29623 			goto fail;
26223859Sml29623 	} else {
26233859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
26243859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
26253859Sml29623 			goto fail;
26263859Sml29623 	}
26273859Sml29623 
26283859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
26293859Sml29623 			portn));
26303859Sml29623 
26313859Sml29623 	return (NXGE_OK);
26323859Sml29623 fail:
26333859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26343859Sml29623 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
26353859Sml29623 			portn));
26363859Sml29623 
26373859Sml29623 	if (rs != NPI_SUCCESS)
26383859Sml29623 		return (NXGE_ERROR | rs);
26393859Sml29623 	else
26403859Sml29623 		return (status);
26413859Sml29623 }
26423859Sml29623 
26433859Sml29623 /* Disable RXMAC */
26443859Sml29623 
26453859Sml29623 nxge_status_t
26463859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
26473859Sml29623 {
26483859Sml29623 	npi_handle_t	handle;
26493859Sml29623 	uint8_t		portn;
26503859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
26513859Sml29623 
26523859Sml29623 	handle = nxgep->npi_handle;
26533859Sml29623 	portn = nxgep->mac.portnum;
26543859Sml29623 
26553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
26563859Sml29623 			portn));
26573859Sml29623 
26583859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
26593859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
26603859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
26613859Sml29623 			goto fail;
26623859Sml29623 	} else {
26633859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
26643859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
26653859Sml29623 			goto fail;
26663859Sml29623 	}
26673859Sml29623 
26683859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
26693859Sml29623 			portn));
26703859Sml29623 	return (NXGE_OK);
26713859Sml29623 fail:
26723859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26733859Sml29623 			"nxgep_rx_mac_disable: ",
26743859Sml29623 			"Failed to disable port<%d> RxMAC",
26753859Sml29623 			portn));
26763859Sml29623 
26773859Sml29623 	return (NXGE_ERROR | rs);
26783859Sml29623 }
26793859Sml29623 
26803859Sml29623 /* Reset TXMAC */
26813859Sml29623 
26823859Sml29623 nxge_status_t
26833859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
26843859Sml29623 {
26853859Sml29623 	npi_handle_t	handle;
26863859Sml29623 	uint8_t		portn;
26873859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
26883859Sml29623 
26893859Sml29623 	handle = nxgep->npi_handle;
26903859Sml29623 	portn = nxgep->mac.portnum;
26913859Sml29623 
26923859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
26933859Sml29623 			portn));
26943859Sml29623 
26953859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
26963859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
26973859Sml29623 		    != NPI_SUCCESS)
26983859Sml29623 			goto fail;
26993859Sml29623 	} else {
27003859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
27013859Sml29623 					!= NPI_SUCCESS)
27023859Sml29623 			goto fail;
27033859Sml29623 	}
27043859Sml29623 
27053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
27063859Sml29623 			portn));
27073859Sml29623 
27083859Sml29623 	return (NXGE_OK);
27093859Sml29623 fail:
27103859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27113859Sml29623 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
27123859Sml29623 			portn));
27133859Sml29623 
27143859Sml29623 	return (NXGE_ERROR | rs);
27153859Sml29623 }
27163859Sml29623 
27173859Sml29623 /* Reset RXMAC */
27183859Sml29623 
27193859Sml29623 nxge_status_t
27203859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
27213859Sml29623 {
27223859Sml29623 	npi_handle_t	handle;
27233859Sml29623 	uint8_t		portn;
27243859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
27253859Sml29623 
27263859Sml29623 	handle = nxgep->npi_handle;
27273859Sml29623 	portn = nxgep->mac.portnum;
27283859Sml29623 
27293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
27303859Sml29623 			portn));
27313859Sml29623 
27323859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
27333859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
27343859Sml29623 		    != NPI_SUCCESS)
27353859Sml29623 		goto fail;
27363859Sml29623 	} else {
27373859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
27383859Sml29623 					!= NPI_SUCCESS)
27393859Sml29623 		goto fail;
27403859Sml29623 	}
27413859Sml29623 
27423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
27433859Sml29623 			portn));
27443859Sml29623 
27453859Sml29623 	return (NXGE_OK);
27463859Sml29623 fail:
27473859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27483859Sml29623 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
27493859Sml29623 			portn));
27503859Sml29623 	return (NXGE_ERROR | rs);
27513859Sml29623 }
27523859Sml29623 
27534732Sdavemq /* 10G fiber link interrupt start routine */
27544732Sdavemq 
27554732Sdavemq static nxge_status_t
27564732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
27574732Sdavemq {
27584732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
27594732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
27604732Sdavemq 
27614732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
27624732Sdavemq 
27634732Sdavemq 	if (rs != NPI_SUCCESS)
27644732Sdavemq 		return (NXGE_ERROR | rs);
27654732Sdavemq 	else
27664732Sdavemq 		return (NXGE_OK);
27674732Sdavemq }
27684732Sdavemq 
27694732Sdavemq /* 10G fiber link interrupt stop routine */
27704732Sdavemq 
27714732Sdavemq static nxge_status_t
27724732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
27734732Sdavemq {
27744732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
27754732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
27764732Sdavemq 
27774732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
27784732Sdavemq 
27794732Sdavemq 	if (rs != NPI_SUCCESS)
27804732Sdavemq 		return (NXGE_ERROR | rs);
27814732Sdavemq 	else
27824732Sdavemq 		return (NXGE_OK);
27834732Sdavemq }
27844732Sdavemq 
27854732Sdavemq /* 1G fiber link interrupt start routine */
27864732Sdavemq 
27874732Sdavemq static nxge_status_t
27884732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
27894732Sdavemq {
27904732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
27914732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
27924732Sdavemq 
27934732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
27944732Sdavemq 	if (rs != NPI_SUCCESS)
27954732Sdavemq 		return (NXGE_ERROR | rs);
27964732Sdavemq 	else
27974732Sdavemq 		return (NXGE_OK);
27984732Sdavemq }
27994732Sdavemq 
28004732Sdavemq /* 1G fiber link interrupt stop routine */
28014732Sdavemq 
28024732Sdavemq static nxge_status_t
28034732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
28044732Sdavemq {
28054732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
28064732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
28074732Sdavemq 
28084732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
28094732Sdavemq 
28104732Sdavemq 	if (rs != NPI_SUCCESS)
28114732Sdavemq 		return (NXGE_ERROR | rs);
28124732Sdavemq 	else
28134732Sdavemq 		return (NXGE_OK);
28144732Sdavemq }
28154732Sdavemq 
28164732Sdavemq /* 1G copper link interrupt start routine */
28174732Sdavemq 
28184732Sdavemq static nxge_status_t
28194732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
28204732Sdavemq {
28214732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
28224732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
28234732Sdavemq 
28244732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
28255203Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
28264732Sdavemq 
28274732Sdavemq 	if (rs != NPI_SUCCESS)
28284732Sdavemq 		return (NXGE_ERROR | rs);
28294732Sdavemq 	else
28304732Sdavemq 		return (NXGE_OK);
28314732Sdavemq }
28324732Sdavemq 
28334732Sdavemq /* 1G copper link interrupt stop routine */
28344732Sdavemq 
28354732Sdavemq static nxge_status_t
28364732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
28374732Sdavemq {
28384732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
28394732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
28404732Sdavemq 
28414732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
28424732Sdavemq 
28434732Sdavemq 	if (rs != NPI_SUCCESS)
28444732Sdavemq 		return (NXGE_ERROR | rs);
28454732Sdavemq 	else
28464732Sdavemq 		return (NXGE_OK);
28474732Sdavemq }
28484732Sdavemq 
28494732Sdavemq /* Enable/Disable Link Status change interrupt */
28503859Sml29623 
28513859Sml29623 nxge_status_t
28523859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
28533859Sml29623 {
28544732Sdavemq 	uint8_t		portn;
28554732Sdavemq 	nxge_status_t	status = NXGE_OK;
28563859Sml29623 
28573859Sml29623 	portn = nxgep->mac.portnum;
28583859Sml29623 
28593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
28604732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
28614732Sdavemq 		return (NXGE_OK);
28624732Sdavemq 
28634732Sdavemq 	if (enable == LINK_INTR_START)
28644732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
28654732Sdavemq 	else if (enable == LINK_INTR_STOP)
28664732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
28674732Sdavemq 	if (status != NXGE_OK)
28684732Sdavemq 		goto fail;
28693859Sml29623 
28703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
28713859Sml29623 
28723859Sml29623 	return (NXGE_OK);
28733859Sml29623 fail:
28743859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
28753859Sml29623 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
28763859Sml29623 			portn));
28773859Sml29623 
28784732Sdavemq 	return (status);
28793859Sml29623 }
28803859Sml29623 
28813859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
28823859Sml29623 
28833859Sml29623 nxge_status_t
28843859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
28853859Sml29623 {
28863859Sml29623 	p_nxge_param_t	param_arr;
28873859Sml29623 	p_nxge_stats_t	statsp;
28883859Sml29623 	uint8_t		xcvr_portn;
28893859Sml29623 	p_mii_regs_t	mii_regs;
28903859Sml29623 	mii_bmcr_t	bmcr;
28913859Sml29623 	mii_bmsr_t	bmsr;
28923859Sml29623 	mii_anar_t	anar;
28933859Sml29623 	mii_gcr_t	gcr;
28943859Sml29623 	mii_esr_t	esr;
28953859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
28963859Sml29623 	int		status = NXGE_OK;
28973859Sml29623 
28983859Sml29623 	uint_t delay;
28993859Sml29623 
29003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
29013859Sml29623 
29023859Sml29623 	param_arr = nxgep->param_arr;
29033859Sml29623 	statsp = nxgep->statsp;
29043859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
29053859Sml29623 
29063859Sml29623 	mii_regs = NULL;
29073859Sml29623 
29083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29093859Sml29623 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
29103859Sml29623 
29113859Sml29623 	/*
29125196Ssbehera 	 * The mif phy mode may be connected to either a copper link
29135196Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
29145196Ssbehera 	 * configuration if it is hard-wired to fiber link.
29155196Ssbehera 	 */
29165196Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
29175196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
29185196Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
29195196Ssbehera 	}
29205196Ssbehera 
29215196Ssbehera 	/*
29223859Sml29623 	 * Reset the transceiver.
29233859Sml29623 	 */
29243859Sml29623 	delay = 0;
29253859Sml29623 	bmcr.value = 0;
29263859Sml29623 	bmcr.bits.reset = 1;
29273859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
29285125Sjoycey #if defined(__i386)
29295125Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
29305125Sjoycey #else
29313859Sml29623 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
29325125Sjoycey #endif
29333859Sml29623 		goto fail;
29343859Sml29623 	do {
29353859Sml29623 		drv_usecwait(500);
29363859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
29375125Sjoycey #if defined(__i386)
29385125Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
29395125Sjoycey #else
29403859Sml29623 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
29415125Sjoycey #endif
29423859Sml29623 				!= NXGE_OK)
29433859Sml29623 			goto fail;
29443859Sml29623 		delay++;
29453859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
29463859Sml29623 	if (delay == 1000) {
29473859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
29483859Sml29623 		goto fail;
29493859Sml29623 	}
29503859Sml29623 
29513859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
29525125Sjoycey #if defined(__i386)
29535125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
29545125Sjoycey #else
29553859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
29565125Sjoycey #endif
29573859Sml29623 			&bmsr.value)) != NXGE_OK)
29583859Sml29623 		goto fail;
29593859Sml29623 
29603859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
29613859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
29623859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
29633859Sml29623 	param_arr[param_anar_100hdx].value = 0;
29643859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
29653859Sml29623 	param_arr[param_anar_10hdx].value = 0;
29663859Sml29623 
29673859Sml29623 	/*
29683859Sml29623 	 * Initialize the xcvr statistics.
29693859Sml29623 	 */
29703859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
29713859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
29723859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
29733859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
29743859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
29753859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
29763859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
29773859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
29783859Sml29623 
29793859Sml29623 	/*
29803859Sml29623 	 * Initialise the xcvr advertised capability statistics.
29813859Sml29623 	 */
29823859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
29833859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
29843859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
29853859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
29863859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
29873859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
29883859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
29893859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
29903859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
29913859Sml29623 					param_arr[param_anar_asmpause].value;
29923859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
29933859Sml29623 
29943859Sml29623 
29953859Sml29623 	/*
29963859Sml29623 	 * Check for extended status just in case we're
29973859Sml29623 	 * running a Gigibit phy.
29983859Sml29623 	 */
29993859Sml29623 	if (bmsr.bits.extend_status) {
30003859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
30015125Sjoycey #if defined(__i386)
30025125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
30035125Sjoycey #else
30043859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
30055125Sjoycey #endif
30063859Sml29623 				!= NXGE_OK)
30073859Sml29623 			goto fail;
30083859Sml29623 		param_arr[param_anar_1000fdx].value &=
30093859Sml29623 					esr.bits.link_1000fdx;
30103859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
30113859Sml29623 
30123859Sml29623 		statsp->mac_stats.cap_1000fdx =
30133859Sml29623 			(esr.bits.link_1000Xfdx ||
30143859Sml29623 				esr.bits.link_1000fdx);
30153859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
30163859Sml29623 	} else {
30173859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
30183859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
30193859Sml29623 	}
30203859Sml29623 
30213859Sml29623 	/*
30223859Sml29623 	 * Initialize 1G Statistics once the capability is established.
30233859Sml29623 	 */
30243859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
30253859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
30263859Sml29623 
30273859Sml29623 	/*
30283859Sml29623 	 * Initialise the link statistics.
30293859Sml29623 	 */
30303859Sml29623 	statsp->mac_stats.link_T4 = 0;
30313859Sml29623 	statsp->mac_stats.link_asmpause = 0;
30323859Sml29623 	statsp->mac_stats.link_pause = 0;
30333859Sml29623 	statsp->mac_stats.link_speed = 0;
30343859Sml29623 	statsp->mac_stats.link_duplex = 0;
30353859Sml29623 	statsp->mac_stats.link_up = 0;
30363859Sml29623 
30373859Sml29623 	/*
30383859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
30393859Sml29623 	 */
30403859Sml29623 	bmcr.value = 0;
30413859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
30425125Sjoycey #if defined(__i386)
30435125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
30445125Sjoycey #else
30453859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
30465125Sjoycey #endif
30473859Sml29623 		goto fail;
30483859Sml29623 
30493859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
30503859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
30513859Sml29623 		bmcr.bits.loopback = 1;
30523859Sml29623 		bmcr.bits.enable_autoneg = 0;
30533859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
30543859Sml29623 			bmcr.bits.speed_1000_sel = 1;
30553859Sml29623 		bmcr.bits.duplex_mode = 1;
30563859Sml29623 		param_arr[param_autoneg].value = 0;
30573859Sml29623 	} else {
30583859Sml29623 		bmcr.bits.loopback = 0;
30593859Sml29623 	}
30603859Sml29623 
30613859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
30623859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
30633859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
30643859Sml29623 		param_arr[param_autoneg].value = 0;
30653859Sml29623 		bcm5464r_aux.value = 0;
30663859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
30673859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
30683859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
30693859Sml29623 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
30703859Sml29623 				!= NXGE_OK)
30713859Sml29623 			goto fail;
30723859Sml29623 	}
30733859Sml29623 
30743859Sml29623 	if (param_arr[param_autoneg].value) {
30753859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30763859Sml29623 				"Restarting Auto-negotiation."));
30773859Sml29623 		/*
30783859Sml29623 		 * Setup our Auto-negotiation advertisement register.
30793859Sml29623 		 */
30803859Sml29623 		anar.value = 0;
30813859Sml29623 		anar.bits.selector = 1;
30823859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
30833859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
30843859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
30853859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
30863859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
30873859Sml29623 		anar.bits.cap_asmpause = 0;
30883859Sml29623 		anar.bits.cap_pause = 0;
30893859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
30903859Sml29623 			param_arr[param_anar_100fdx].value ||
30913859Sml29623 			param_arr[param_anar_10fdx].value) {
30923859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
30933859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
30943859Sml29623 		}
30953859Sml29623 
30963859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
30975125Sjoycey #if defined(__i386)
30985125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
30995125Sjoycey #else
31003859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
31015125Sjoycey #endif
31023859Sml29623 				!= NXGE_OK)
31033859Sml29623 			goto fail;
31043859Sml29623 		if (bmsr.bits.extend_status) {
31053859Sml29623 			gcr.value = 0;
31063859Sml29623 			gcr.bits.ms_mode_en =
31073859Sml29623 				param_arr[param_master_cfg_enable].value;
31083859Sml29623 			gcr.bits.master =
31093859Sml29623 				param_arr[param_master_cfg_value].value;
31103859Sml29623 			gcr.bits.link_1000fdx =
31113859Sml29623 				param_arr[param_anar_1000fdx].value;
31123859Sml29623 			gcr.bits.link_1000hdx =
31133859Sml29623 				param_arr[param_anar_1000hdx].value;
31143859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
31155125Sjoycey #if defined(__i386)
31165125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
31175125Sjoycey #else
31183859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
31195125Sjoycey #endif
31203859Sml29623 				!= NXGE_OK)
31213859Sml29623 				goto fail;
31223859Sml29623 		}
31233859Sml29623 
31243859Sml29623 		bmcr.bits.enable_autoneg = 1;
31253859Sml29623 		bmcr.bits.restart_autoneg = 1;
31263859Sml29623 
31273859Sml29623 	} else {
31283859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
31293859Sml29623 		bmcr.bits.speed_1000_sel =
31303859Sml29623 			param_arr[param_anar_1000fdx].value |
31313859Sml29623 				param_arr[param_anar_1000hdx].value;
31323859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
31333859Sml29623 			(param_arr[param_anar_100fdx].value |
31343859Sml29623 				param_arr[param_anar_100hdx].value);
31353859Sml29623 		if (bmcr.bits.speed_1000_sel) {
31363859Sml29623 			statsp->mac_stats.link_speed = 1000;
31373859Sml29623 			gcr.value = 0;
31383859Sml29623 			gcr.bits.ms_mode_en =
31393859Sml29623 				param_arr[param_master_cfg_enable].value;
31403859Sml29623 			gcr.bits.master =
31413859Sml29623 				param_arr[param_master_cfg_value].value;
31423859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
31435125Sjoycey #if defined(__i386)
31445125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
31455125Sjoycey #else
31463859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr),
31475125Sjoycey #endif
31483859Sml29623 				gcr.value))
31493859Sml29623 				!= NXGE_OK)
31503859Sml29623 				goto fail;
31513859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
31523859Sml29623 				bmcr.bits.duplex_mode = 1;
31533859Sml29623 				statsp->mac_stats.link_duplex = 2;
31543859Sml29623 			} else
31553859Sml29623 				statsp->mac_stats.link_duplex = 1;
31563859Sml29623 		} else if (bmcr.bits.speed_sel) {
31573859Sml29623 			statsp->mac_stats.link_speed = 100;
31583859Sml29623 			if (param_arr[param_anar_100fdx].value) {
31593859Sml29623 				bmcr.bits.duplex_mode = 1;
31603859Sml29623 				statsp->mac_stats.link_duplex = 2;
31613859Sml29623 			} else
31623859Sml29623 				statsp->mac_stats.link_duplex = 1;
31633859Sml29623 		} else {
31643859Sml29623 			statsp->mac_stats.link_speed = 10;
31653859Sml29623 			if (param_arr[param_anar_10fdx].value) {
31663859Sml29623 				bmcr.bits.duplex_mode = 1;
31673859Sml29623 				statsp->mac_stats.link_duplex = 2;
31683859Sml29623 			} else
31693859Sml29623 				statsp->mac_stats.link_duplex = 1;
31703859Sml29623 		}
31713859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
31723859Sml29623 			statsp->mac_stats.link_asmpause =
31733859Sml29623 						statsp->mac_stats.cap_asmpause;
31743859Sml29623 			statsp->mac_stats.link_pause =
31753859Sml29623 						statsp->mac_stats.cap_pause;
31763859Sml29623 		}
31773859Sml29623 
31783859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
31793859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
31803859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
31813859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
31823859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
31833859Sml29623 				gcr.value = 0;
31843859Sml29623 				gcr.bits.ms_mode_en = 1;
31853859Sml29623 				gcr.bits.master = 1;
31863859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
31875125Sjoycey #if defined(__i386)
31885125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
31895125Sjoycey #else
31903859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gcr),
31915125Sjoycey #endif
31923859Sml29623 					gcr.value))
31933859Sml29623 					!= NXGE_OK)
31943859Sml29623 					goto fail;
31953859Sml29623 				bmcr.value = 0;
31963859Sml29623 				bmcr.bits.speed_1000_sel = 1;
31973859Sml29623 				statsp->mac_stats.link_speed = 1000;
31983859Sml29623 			} else if (statsp->port_stats.lb_mode
31993859Sml29623 			    == nxge_lb_ext100) {
32003859Sml29623 				/* BCM5464R 100mbps external loopback mode */
32013859Sml29623 				bmcr.value = 0;
32023859Sml29623 				bmcr.bits.speed_sel = 1;
32033859Sml29623 				bmcr.bits.duplex_mode = 1;
32043859Sml29623 				statsp->mac_stats.link_speed = 100;
32053859Sml29623 			} else if (statsp->port_stats.lb_mode
32063859Sml29623 			    == nxge_lb_ext10) {
32073859Sml29623 				/* BCM5464R 10mbps external loopback mode */
32083859Sml29623 				bmcr.value = 0;
32093859Sml29623 				bmcr.bits.duplex_mode = 1;
32103859Sml29623 				statsp->mac_stats.link_speed = 10;
32113859Sml29623 			}
32123859Sml29623 		}
32133859Sml29623 	}
32143859Sml29623 
32153859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
32165125Sjoycey #if defined(__i386)
32175125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
32185125Sjoycey #else
32193859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
32205125Sjoycey #endif
32213859Sml29623 			bmcr.value)) != NXGE_OK)
32223859Sml29623 		goto fail;
32233859Sml29623 
32243859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
32255125Sjoycey #if defined(__i386)
32265125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
32275125Sjoycey #else
32283859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
32295125Sjoycey #endif
32303859Sml29623 		goto fail;
32313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
32323859Sml29623 
32333859Sml29623 	/*
32343859Sml29623 	 * Initialize the xcvr status kept in the context structure.
32353859Sml29623 	 */
32363859Sml29623 	nxgep->soft_bmsr.value = 0;
32373859Sml29623 
32383859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
32395125Sjoycey #if defined(__i386)
32405125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
32415125Sjoycey #else
32423859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
32435125Sjoycey #endif
32443859Sml29623 			&nxgep->bmsr.value)) != NXGE_OK)
32453859Sml29623 		goto fail;
32463859Sml29623 
32473859Sml29623 	statsp->mac_stats.xcvr_inits++;
32483859Sml29623 	nxgep->bmsr.value = 0;
32493859Sml29623 
32503859Sml29623 fail:
32513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
32523859Sml29623 			"<== nxge_mii_xcvr_init status 0x%x", status));
32533859Sml29623 	return (status);
32543859Sml29623 }
32553859Sml29623 
32565196Ssbehera nxge_status_t
32575196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
32585196Ssbehera {
32595196Ssbehera 	p_nxge_param_t	param_arr;
32605196Ssbehera 	p_nxge_stats_t	statsp;
32615196Ssbehera 	uint8_t		xcvr_portn;
32625196Ssbehera 	p_mii_regs_t	mii_regs;
32635196Ssbehera 	mii_bmcr_t	bmcr;
32645196Ssbehera 	mii_bmsr_t	bmsr;
32655196Ssbehera 	mii_gcr_t	gcr;
32665196Ssbehera 	mii_esr_t	esr;
32675196Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
32685196Ssbehera 	int		status = NXGE_OK;
32695196Ssbehera 
32705196Ssbehera 	uint_t delay;
32715196Ssbehera 
32725196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
32735196Ssbehera 
32745196Ssbehera 	param_arr = nxgep->param_arr;
32755196Ssbehera 	statsp = nxgep->statsp;
32765196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
32775196Ssbehera 
32785196Ssbehera 	mii_regs = NULL;
32795196Ssbehera 
32805196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
32815196Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
32825196Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
32835196Ssbehera 
32845196Ssbehera 	/*
32855196Ssbehera 	 * Reset the transceiver.
32865196Ssbehera 	 */
32875196Ssbehera 	delay = 0;
32885196Ssbehera 	bmcr.value = 0;
32895196Ssbehera 	bmcr.bits.reset = 1;
32905196Ssbehera 
32915196Ssbehera #if defined(__i386)
32925196Ssbehera 
32935196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
32945196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
32955196Ssbehera 		goto fail;
32965196Ssbehera #else
32975196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
32985196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
32995196Ssbehera 		goto fail;
33005196Ssbehera #endif
33015196Ssbehera 	do {
33025196Ssbehera 		drv_usecwait(500);
33035196Ssbehera #if defined(__i386)
33045196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
33055196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
33065196Ssbehera 		    != NXGE_OK)
33075196Ssbehera 			goto fail;
33085196Ssbehera #else
33095196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
33105196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
33115196Ssbehera 		    != NXGE_OK)
33125196Ssbehera 			goto fail;
33135196Ssbehera #endif
33145196Ssbehera 		delay++;
33155196Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
33165196Ssbehera 	if (delay == 1000) {
33175196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
33185196Ssbehera 		goto fail;
33195196Ssbehera 	}
33205196Ssbehera 
33215196Ssbehera #if defined(__i386)
33225196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
33235196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
33245196Ssbehera 		goto fail;
33255196Ssbehera #else
33265196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
33275196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
33285196Ssbehera 		goto fail;
33295196Ssbehera #endif
33305196Ssbehera 
33315196Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
33325196Ssbehera 	param_arr[param_anar_100T4].value = 0;
33335196Ssbehera 	param_arr[param_anar_100fdx].value = 0;
33345196Ssbehera 	param_arr[param_anar_100hdx].value = 0;
33355196Ssbehera 	param_arr[param_anar_10fdx].value = 0;
33365196Ssbehera 	param_arr[param_anar_10hdx].value = 0;
33375196Ssbehera 
33385196Ssbehera 	/*
33395196Ssbehera 	 * Initialize the xcvr statistics.
33405196Ssbehera 	 */
33415196Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
33425196Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
33435196Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
33445196Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
33455196Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
33465196Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
33475196Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
33485196Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
33495196Ssbehera 
33505196Ssbehera 	/*
33515196Ssbehera 	 * Initialize the xcvr advertised capability statistics.
33525196Ssbehera 	 */
33535196Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
33545196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
33555196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
33565196Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
33575196Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
33585196Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
33595196Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
33605196Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
33615196Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
33625196Ssbehera 	    param_arr[param_anar_asmpause].value;
33635196Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
33645196Ssbehera 
33655196Ssbehera 	/*
33665196Ssbehera 	 * Check for extended status just in case we're
33675196Ssbehera 	 * running a Gigibit phy.
33685196Ssbehera 	 */
33695196Ssbehera 	if (bmsr.bits.extend_status) {
33705196Ssbehera #if defined(__i386)
33715196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
33725196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
33735196Ssbehera 		    NXGE_OK)
33745196Ssbehera 			goto fail;
33755196Ssbehera #else
33765196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
33775196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
33785196Ssbehera 		    NXGE_OK)
33795196Ssbehera 			goto fail;
33805196Ssbehera #endif
33815196Ssbehera 		param_arr[param_anar_1000fdx].value &=
33825196Ssbehera 		    esr.bits.link_1000fdx;
33835196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
33845196Ssbehera 
33855196Ssbehera 		statsp->mac_stats.cap_1000fdx =
33865196Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
33875196Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
33885196Ssbehera 	} else {
33895196Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
33905196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
33915196Ssbehera 	}
33925196Ssbehera 
33935196Ssbehera 	/*
33945196Ssbehera 	 * Initialize 1G Statistics once the capability is established.
33955196Ssbehera 	 */
33965196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
33975196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
33985196Ssbehera 
33995196Ssbehera 	/*
34005196Ssbehera 	 * Initialize the link statistics.
34015196Ssbehera 	 */
34025196Ssbehera 	statsp->mac_stats.link_T4 = 0;
34035196Ssbehera 	statsp->mac_stats.link_asmpause = 0;
34045196Ssbehera 	statsp->mac_stats.link_pause = 0;
34055196Ssbehera 	statsp->mac_stats.link_speed = 0;
34065196Ssbehera 	statsp->mac_stats.link_duplex = 0;
34075196Ssbehera 	statsp->mac_stats.link_up = 0;
34085196Ssbehera 
34095196Ssbehera 	/*
34105196Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
34115196Ssbehera 	 */
34125196Ssbehera 	bmcr.value = 0;
34135196Ssbehera #if defined(__i386)
34145196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
34155196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
34165196Ssbehera 		goto fail;
34175196Ssbehera #else
34185196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
34195196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
34205196Ssbehera 		goto fail;
34215196Ssbehera #endif
34225196Ssbehera 
34235196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
34245196Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
34255196Ssbehera 		bmcr.bits.loopback = 1;
34265196Ssbehera 		bmcr.bits.enable_autoneg = 0;
34275196Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
34285196Ssbehera 			bmcr.bits.speed_1000_sel = 1;
34295196Ssbehera 		bmcr.bits.duplex_mode = 1;
34305196Ssbehera 		param_arr[param_autoneg].value = 0;
34315196Ssbehera 	} else {
34325196Ssbehera 		bmcr.bits.loopback = 0;
34335196Ssbehera 	}
34345196Ssbehera 
34355196Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
34365196Ssbehera 		param_arr[param_autoneg].value = 0;
34375196Ssbehera 		bcm5464r_aux.value = 0;
34385196Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
34395196Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
34405196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
34415196Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
34425196Ssbehera 			goto fail;
34435196Ssbehera 	}
34445196Ssbehera 
34455196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
34465196Ssbehera 	bmcr.bits.speed_1000_sel = 1;
34475196Ssbehera 	bmcr.bits.speed_sel = 0;
34485196Ssbehera 	bmcr.bits.duplex_mode = 1;
34495196Ssbehera 	statsp->mac_stats.link_speed = 1000;
34505196Ssbehera 	statsp->mac_stats.link_duplex = 2;
34515196Ssbehera 
34525196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
34535196Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
34545196Ssbehera 		gcr.value = 0;
34555196Ssbehera 		gcr.bits.ms_mode_en = 1;
34565196Ssbehera 		gcr.bits.master = 1;
34575196Ssbehera #if defined(__i386)
34585196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
34595196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
34605196Ssbehera 		    gcr.value)) != NXGE_OK)
34615196Ssbehera 			goto fail;
34625196Ssbehera #else
34635196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
34645196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
34655196Ssbehera 		    gcr.value)) != NXGE_OK)
34665196Ssbehera 			goto fail;
34675196Ssbehera #endif
34685196Ssbehera 		bmcr.value = 0;
34695196Ssbehera 		bmcr.bits.speed_1000_sel = 1;
34705196Ssbehera 		statsp->mac_stats.link_speed = 1000;
34715196Ssbehera 	}
34725196Ssbehera 
34735196Ssbehera #if defined(__i386)
34745196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
34755196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
34765196Ssbehera 	    bmcr.value)) != NXGE_OK)
34775196Ssbehera 		goto fail;
34785196Ssbehera #else
34795196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
34805196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
34815196Ssbehera 	    bmcr.value)) != NXGE_OK)
34825196Ssbehera 		goto fail;
34835196Ssbehera #endif
34845196Ssbehera 
34855196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
34865196Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
34875196Ssbehera 	    bmcr.value));
34885196Ssbehera 
34895196Ssbehera #if defined(__i386)
34905196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
34915196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
34925196Ssbehera 		goto fail;
34935196Ssbehera #else
34945196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
34955196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
34965196Ssbehera 		goto fail;
34975196Ssbehera #endif
34985196Ssbehera 
34995196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35005196Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
35015196Ssbehera 
35025196Ssbehera 	/*
35035196Ssbehera 	 * Initialize the xcvr status kept in the context structure.
35045196Ssbehera 	 */
35055196Ssbehera 	nxgep->soft_bmsr.value = 0;
35065196Ssbehera #if defined(__i386)
35075196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
35085196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
35095196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
35105196Ssbehera 		goto fail;
35115196Ssbehera #else
35125196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
35135196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
35145196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
35155196Ssbehera 		goto fail;
35165196Ssbehera #endif
35175196Ssbehera 
35185196Ssbehera 	statsp->mac_stats.xcvr_inits++;
35195196Ssbehera 	nxgep->bmsr.value = 0;
35205196Ssbehera 
35215196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35225196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
35235196Ssbehera 	return (status);
35245196Ssbehera 
35255196Ssbehera fail:
35265196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
35275196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
35285196Ssbehera 	return (status);
35295196Ssbehera }
35305196Ssbehera 
35313859Sml29623 /* Read from a MII compliant register */
35323859Sml29623 
35333859Sml29623 nxge_status_t
35343859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
35353859Sml29623 		uint16_t *value)
35363859Sml29623 {
35373859Sml29623 	npi_status_t rs = NPI_SUCCESS;
35383859Sml29623 
35393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
35403859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
35413859Sml29623 
35425780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock);
35433859Sml29623 
35445196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
35455196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
35463859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
35473859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
35483859Sml29623 			goto fail;
35494977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
35504977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
35513859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
35523859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
35533859Sml29623 			goto fail;
35543859Sml29623 	} else
35553859Sml29623 		goto fail;
35563859Sml29623 
35575780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
35583859Sml29623 
35593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
35603859Sml29623 			"xcvr_reg<%d> value=0x%x",
35613859Sml29623 			xcvr_portn, xcvr_reg, *value));
35623859Sml29623 	return (NXGE_OK);
35633859Sml29623 fail:
35645780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
35653859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
35663859Sml29623 			"nxge_mii_read: Failed to read mii on xcvr %d",
35673859Sml29623 			xcvr_portn));
35683859Sml29623 
35693859Sml29623 	return (NXGE_ERROR | rs);
35703859Sml29623 }
35713859Sml29623 
35723859Sml29623 /* Write to a MII compliant Register */
35733859Sml29623 
35743859Sml29623 nxge_status_t
35753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
35763859Sml29623 		uint16_t value)
35773859Sml29623 {
35783859Sml29623 	npi_status_t rs = NPI_SUCCESS;
35793859Sml29623 
35803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
35813859Sml29623 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
35823859Sml29623 			value));
35833859Sml29623 
35845780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock);
35853859Sml29623 
35865196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
35875196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
35883859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
35893859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
35903859Sml29623 			goto fail;
35914977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
35924977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
35933859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
35943859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
35953859Sml29623 			goto fail;
35963859Sml29623 	} else
35973859Sml29623 		goto fail;
35983859Sml29623 
35995780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
36003859Sml29623 
36013859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
36023859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
36033859Sml29623 	return (NXGE_OK);
36043859Sml29623 fail:
36055780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
36063859Sml29623 
36073859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
36083859Sml29623 			"nxge_mii_write: Failed to write mii on xcvr %d",
36093859Sml29623 			xcvr_portn));
36103859Sml29623 
36113859Sml29623 	return (NXGE_ERROR | rs);
36123859Sml29623 }
36133859Sml29623 
36143859Sml29623 /* Perform read from Clause45 serdes / transceiver device */
36153859Sml29623 
36163859Sml29623 nxge_status_t
36173859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
36183859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
36193859Sml29623 {
36203859Sml29623 	npi_status_t rs = NPI_SUCCESS;
36213859Sml29623 
36223859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
36233859Sml29623 			xcvr_portn));
36243859Sml29623 
36255780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
36263859Sml29623 
36273859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
36283859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
36293859Sml29623 		goto fail;
36303859Sml29623 
36315780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
36323859Sml29623 
36333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
36343859Sml29623 			xcvr_portn));
36353859Sml29623 	return (NXGE_OK);
36363859Sml29623 fail:
36375780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
36383859Sml29623 
36393859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
36403859Sml29623 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
36413859Sml29623 			xcvr_portn));
36423859Sml29623 
36433859Sml29623 	return (NXGE_ERROR | rs);
36443859Sml29623 }
36453859Sml29623 
36463859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
36473859Sml29623 
36483859Sml29623 nxge_status_t
36493859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
36503859Sml29623 		uint16_t xcvr_reg, uint16_t value)
36513859Sml29623 {
36523859Sml29623 	npi_status_t rs = NPI_SUCCESS;
36533859Sml29623 
36543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
36553859Sml29623 			xcvr_portn));
36563859Sml29623 
36575780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
36583859Sml29623 
36593859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
36603859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
36613859Sml29623 		goto fail;
36623859Sml29623 
36635780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
36643859Sml29623 
36653859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
36663859Sml29623 			xcvr_portn));
36673859Sml29623 	return (NXGE_OK);
36683859Sml29623 fail:
36695780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
36703859Sml29623 
36713859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
36723859Sml29623 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
36733859Sml29623 			xcvr_portn));
36743859Sml29623 
36753859Sml29623 	return (NXGE_ERROR | rs);
36763859Sml29623 }
36773859Sml29623 
36783859Sml29623 
36793859Sml29623 /* Check MII to see if there is any link status change */
36803859Sml29623 
36813859Sml29623 nxge_status_t
36823859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
36833859Sml29623 		nxge_link_state_t *link_up)
36843859Sml29623 {
36853859Sml29623 	p_nxge_param_t	param_arr;
36863859Sml29623 	p_nxge_stats_t	statsp;
36873859Sml29623 	p_mii_regs_t	mii_regs;
36883859Sml29623 	p_mii_bmsr_t	soft_bmsr;
36893859Sml29623 	mii_anar_t	anar;
36903859Sml29623 	mii_anlpar_t	anlpar;
36913859Sml29623 	mii_anar_t	an_common;
36923859Sml29623 	mii_aner_t	aner;
36933859Sml29623 	mii_gsr_t	gsr;
36943859Sml29623 	nxge_status_t	status = NXGE_OK;
36953859Sml29623 
36963859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
36973859Sml29623 
36983859Sml29623 	mii_regs = NULL;
36993859Sml29623 	param_arr = nxgep->param_arr;
37003859Sml29623 	statsp = nxgep->statsp;
37013859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
37023859Sml29623 	*link_up = LINK_NO_CHANGE;
37033859Sml29623 
37045196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37055196Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
37065196Ssbehera 	    bmsr.value, bmsr_ints.value));
37075196Ssbehera 
37083859Sml29623 	if (bmsr_ints.bits.link_status) {
37095196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37105196Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
37115196Ssbehera 		    bmsr.value, bmsr_ints.value));
37123859Sml29623 		if (bmsr.bits.link_status) {
37133859Sml29623 			soft_bmsr->bits.link_status = 1;
37145196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37155196Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
37165196Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
37173859Sml29623 		} else {
37183859Sml29623 			statsp->mac_stats.link_up = 0;
37193859Sml29623 			soft_bmsr->bits.link_status = 0;
37203859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37213859Sml29623 					"Link down cable problem"));
37223859Sml29623 			*link_up = LINK_IS_DOWN;
37233859Sml29623 		}
37243859Sml29623 	}
37253859Sml29623 
37265196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
37275196Ssbehera 	    param_arr[param_autoneg].value) {
37283859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
37293859Sml29623 			if (bmsr.bits.auto_neg_complete)
37303859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
37313859Sml29623 			else
37323859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
37333859Sml29623 		}
37343859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
37353859Sml29623 			statsp->mac_stats.link_T4 = 0;
37363859Sml29623 			statsp->mac_stats.link_speed = 0;
37373859Sml29623 			statsp->mac_stats.link_duplex = 0;
37383859Sml29623 			statsp->mac_stats.link_asmpause = 0;
37393859Sml29623 			statsp->mac_stats.link_pause = 0;
37403859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
37413859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
37423859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
37433859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
37443859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
37453859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
37463859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
37473859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
37483859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
37493859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
37503859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
37513859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
37523859Sml29623 		}
37533859Sml29623 	} else
37543859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
37553859Sml29623 
37563859Sml29623 	if ((bmsr_ints.bits.link_status ||
37573859Sml29623 		bmsr_ints.bits.auto_neg_complete) &&
37583859Sml29623 		soft_bmsr->bits.link_status &&
37593859Sml29623 		soft_bmsr->bits.auto_neg_complete) {
37603859Sml29623 		statsp->mac_stats.link_up = 1;
37615196Ssbehera 
37625196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37635196Ssbehera 		    "==> nxge_mii_check "
37645196Ssbehera 		    "(auto negotiation complete or link up) "
37655196Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
37665196Ssbehera 		    bmsr.value, bmsr_ints.value));
37675196Ssbehera 
37685196Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
37695196Ssbehera 		    param_arr[param_autoneg].value) {
37703859Sml29623 			if ((status = nxge_mii_read(nxgep,
37713859Sml29623 				statsp->mac_stats.xcvr_portn,
37725125Sjoycey #if defined(__i386)
37735125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
37745125Sjoycey #else
37753859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anar),
37765125Sjoycey #endif
37773859Sml29623 					&anar.value)) != NXGE_OK)
37783859Sml29623 				goto fail;
37793859Sml29623 			if ((status = nxge_mii_read(nxgep,
37803859Sml29623 				statsp->mac_stats.xcvr_portn,
37815125Sjoycey #if defined(__i386)
37825125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
37835125Sjoycey #else
37843859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
37855125Sjoycey #endif
37863859Sml29623 					&anlpar.value)) != NXGE_OK)
37873859Sml29623 				goto fail;
37883859Sml29623 			if ((status = nxge_mii_read(nxgep,
37893859Sml29623 				statsp->mac_stats.xcvr_portn,
37905125Sjoycey #if defined(__i386)
37915125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
37925125Sjoycey #else
37933859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->aner),
37945125Sjoycey #endif
37953859Sml29623 					&aner.value)) != NXGE_OK)
37963859Sml29623 				goto fail;
37973859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
37983859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
37993859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
38003859Sml29623 							anlpar.bits.cap_100fdx;
38013859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
38023859Sml29623 							anlpar.bits.cap_100hdx;
38033859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
38043859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
38053859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
38063859Sml29623 						anlpar.bits.cap_asmpause;
38073859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
38083859Sml29623 			an_common.value = anar.value & anlpar.value;
38093859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
38103859Sml29623 				param_arr[param_anar_1000hdx].value) {
38113859Sml29623 				if ((status = nxge_mii_read(nxgep,
38123859Sml29623 					statsp->mac_stats.xcvr_portn,
38135125Sjoycey #if defined(__i386)
38145125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
38155125Sjoycey #else
38163859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gsr),
38175125Sjoycey #endif
38183859Sml29623 						&gsr.value))
38193859Sml29623 						!= NXGE_OK)
38203859Sml29623 					goto fail;
38213859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
38223859Sml29623 					gsr.bits.link_1000fdx;
38233859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
38243859Sml29623 					gsr.bits.link_1000hdx;
38253859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
38263859Sml29623 					gsr.bits.link_1000fdx) {
38273859Sml29623 					statsp->mac_stats.link_speed = 1000;
38283859Sml29623 					statsp->mac_stats.link_duplex = 2;
38293859Sml29623 				} else if (
38303859Sml29623 					param_arr[param_anar_1000hdx].value &&
38313859Sml29623 						gsr.bits.link_1000hdx) {
38323859Sml29623 					statsp->mac_stats.link_speed = 1000;
38333859Sml29623 					statsp->mac_stats.link_duplex = 1;
38343859Sml29623 				}
38353859Sml29623 			}
38363859Sml29623 			if ((an_common.value != 0) &&
38373859Sml29623 					!(statsp->mac_stats.link_speed)) {
38383859Sml29623 				if (an_common.bits.cap_100T4) {
38393859Sml29623 					statsp->mac_stats.link_T4 = 1;
38403859Sml29623 					statsp->mac_stats.link_speed = 100;
38413859Sml29623 					statsp->mac_stats.link_duplex = 1;
38423859Sml29623 				} else if (an_common.bits.cap_100fdx) {
38433859Sml29623 					statsp->mac_stats.link_speed = 100;
38443859Sml29623 					statsp->mac_stats.link_duplex = 2;
38453859Sml29623 				} else if (an_common.bits.cap_100hdx) {
38463859Sml29623 					statsp->mac_stats.link_speed = 100;
38473859Sml29623 					statsp->mac_stats.link_duplex = 1;
38483859Sml29623 				} else if (an_common.bits.cap_10fdx) {
38493859Sml29623 					statsp->mac_stats.link_speed = 10;
38503859Sml29623 					statsp->mac_stats.link_duplex = 2;
38513859Sml29623 				} else if (an_common.bits.cap_10hdx) {
38523859Sml29623 					statsp->mac_stats.link_speed = 10;
38533859Sml29623 					statsp->mac_stats.link_duplex = 1;
38543859Sml29623 				} else {
38553859Sml29623 					goto fail;
38563859Sml29623 				}
38573859Sml29623 			}
38583859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
38593859Sml29623 				statsp->mac_stats.link_asmpause =
38603859Sml29623 					an_common.bits.cap_asmpause;
38613859Sml29623 				if (statsp->mac_stats.link_asmpause)
38623859Sml29623 				if ((statsp->mac_stats.cap_pause == 0) &&
38633859Sml29623 						(statsp->mac_stats.lp_cap_pause
38643859Sml29623 						== 1))
38653859Sml29623 						statsp->mac_stats.link_pause
38663859Sml29623 						= 0;
38673859Sml29623 					else
38683859Sml29623 						statsp->mac_stats.link_pause
38693859Sml29623 						= 1;
38703859Sml29623 				else
38713859Sml29623 					statsp->mac_stats.link_pause =
38723859Sml29623 						an_common.bits.cap_pause;
38733859Sml29623 			}
38745196Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
38755196Ssbehera 			statsp->mac_stats.link_speed = 1000;
38765196Ssbehera 			statsp->mac_stats.link_duplex = 2;
38773859Sml29623 		}
38783859Sml29623 		*link_up = LINK_IS_UP;
38793859Sml29623 	}
38803859Sml29623 
38813859Sml29623 	if (nxgep->link_notify) {
38823859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
38833859Sml29623 				LINK_IS_DOWN);
38843859Sml29623 		nxgep->link_notify = B_FALSE;
38853859Sml29623 	}
38863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
38873859Sml29623 	return (NXGE_OK);
38883859Sml29623 fail:
38893859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
38903859Sml29623 			"nxge_mii_check: Unable to check MII"));
38913859Sml29623 	return (status);
38923859Sml29623 }
38933859Sml29623 
38944977Sraghus /* Check PCS to see if there is any link status change */
38954977Sraghus nxge_status_t
38964977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
38974977Sraghus {
38984977Sraghus 	p_nxge_stats_t	statsp;
38994977Sraghus 	nxge_status_t	status = NXGE_OK;
39004977Sraghus 	boolean_t	linkup;
39014977Sraghus 
39024977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
39034977Sraghus 
39044977Sraghus 	statsp = nxgep->statsp;
39054977Sraghus 	*link_up = LINK_NO_CHANGE;
39064977Sraghus 
39074977Sraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
39084977Sraghus 	if (linkup) {
39094977Sraghus 		if (nxgep->link_notify ||
39104977Sraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
39114977Sraghus 			statsp->mac_stats.link_up = 1;
39124977Sraghus 			statsp->mac_stats.link_speed = 1000;
39134977Sraghus 			statsp->mac_stats.link_duplex = 2;
39144977Sraghus 			*link_up = LINK_IS_UP;
39154977Sraghus 			nxgep->link_notify = B_FALSE;
39164977Sraghus 		}
39174977Sraghus 	} else {
39184977Sraghus 		if (nxgep->link_notify ||
39194977Sraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
39204977Sraghus 			statsp->mac_stats.link_up = 0;
39214977Sraghus 			statsp->mac_stats.link_speed = 0;
39224977Sraghus 			statsp->mac_stats.link_duplex = 0;
39234977Sraghus 			*link_up = LINK_IS_DOWN;
39244977Sraghus 			nxgep->link_notify = B_FALSE;
39254977Sraghus 		}
39264977Sraghus 	}
39274977Sraghus 
39284977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
39294977Sraghus 	return (NXGE_OK);
39304977Sraghus fail:
39314977Sraghus 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
39324977Sraghus 	    "nxge_pcs_check: Unable to check PCS"));
39334977Sraghus 	return (status);
39344977Sraghus }
39354977Sraghus 
39363859Sml29623 /* Add a multicast address entry into the HW hash table */
39373859Sml29623 
39383859Sml29623 nxge_status_t
39393859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
39403859Sml29623 {
39413859Sml29623 	uint32_t mchash;
39423859Sml29623 	p_hash_filter_t hash_filter;
39433859Sml29623 	uint16_t hash_bit;
39443859Sml29623 	boolean_t rx_init = B_FALSE;
39453859Sml29623 	uint_t j;
39463859Sml29623 	nxge_status_t status = NXGE_OK;
39473859Sml29623 
39483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
39493859Sml29623 
39503859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
39513859Sml29623 	mchash = crc32_mchash(addrp);
39523859Sml29623 	if (nxgep->hash_filter == NULL) {
39533859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
39543859Sml29623 			"Allocating hash filter storage."));
39553859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
39563859Sml29623 					KM_SLEEP);
39573859Sml29623 	}
39583859Sml29623 	hash_filter = nxgep->hash_filter;
39593859Sml29623 	j = mchash / HASH_REG_WIDTH;
39603859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
39613859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
39623859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
39633859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
39643859Sml29623 		hash_filter->hash_ref_cnt++;
39653859Sml29623 		rx_init = B_TRUE;
39663859Sml29623 	}
39673859Sml29623 	if (rx_init) {
39683859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
39693859Sml29623 			goto fail;
39703859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
39713859Sml29623 			goto fail;
39723859Sml29623 	}
39733859Sml29623 
39743859Sml29623 	RW_EXIT(&nxgep->filter_lock);
39753859Sml29623 
39763859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
39773859Sml29623 
39783859Sml29623 	return (NXGE_OK);
39793859Sml29623 fail:
39803859Sml29623 	RW_EXIT(&nxgep->filter_lock);
39813859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
39823859Sml29623 					"Unable to add multicast address"));
39833859Sml29623 	return (status);
39843859Sml29623 }
39853859Sml29623 
39863859Sml29623 /* Remove a multicast address entry from the HW hash table */
39873859Sml29623 
39883859Sml29623 nxge_status_t
39893859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
39903859Sml29623 {
39913859Sml29623 	uint32_t mchash;
39923859Sml29623 	p_hash_filter_t hash_filter;
39933859Sml29623 	uint16_t hash_bit;
39943859Sml29623 	boolean_t rx_init = B_FALSE;
39953859Sml29623 	uint_t j;
39963859Sml29623 	nxge_status_t status = NXGE_OK;
39973859Sml29623 
39983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
39993859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
40003859Sml29623 	mchash = crc32_mchash(addrp);
40013859Sml29623 	if (nxgep->hash_filter == NULL) {
40023859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
40033859Sml29623 			"Hash filter already de_allocated."));
40043859Sml29623 		RW_EXIT(&nxgep->filter_lock);
40053859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
40063859Sml29623 		return (NXGE_OK);
40073859Sml29623 	}
40083859Sml29623 	hash_filter = nxgep->hash_filter;
40093859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
40103859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
40113859Sml29623 		j = mchash / HASH_REG_WIDTH;
40123859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
40133859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
40143859Sml29623 		hash_filter->hash_ref_cnt--;
40153859Sml29623 		rx_init = B_TRUE;
40163859Sml29623 	}
40173859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
40183859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
40193859Sml29623 			"De-allocating hash filter storage."));
40203859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
40213859Sml29623 		nxgep->hash_filter = NULL;
40223859Sml29623 	}
40233859Sml29623 
40243859Sml29623 	if (rx_init) {
40253859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
40263859Sml29623 			goto fail;
40273859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
40283859Sml29623 			goto fail;
40293859Sml29623 	}
40303859Sml29623 	RW_EXIT(&nxgep->filter_lock);
40313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
40323859Sml29623 
40333859Sml29623 	return (NXGE_OK);
40343859Sml29623 fail:
40353859Sml29623 	RW_EXIT(&nxgep->filter_lock);
40363859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
40373859Sml29623 			"Unable to remove multicast address"));
40383859Sml29623 
40393859Sml29623 	return (status);
40403859Sml29623 }
40413859Sml29623 
40423859Sml29623 /* Set MAC address into MAC address HW registers */
40433859Sml29623 
40443859Sml29623 nxge_status_t
40453859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
40463859Sml29623 {
40473859Sml29623 	nxge_status_t status = NXGE_OK;
40483859Sml29623 
40493859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
40503859Sml29623 
40513859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
40523859Sml29623 	/*
40533859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
40543859Sml29623 	 */
40553859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
40563859Sml29623 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
40573859Sml29623 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
40583859Sml29623 		goto nxge_set_mac_addr_exit;
40593859Sml29623 	}
40603859Sml29623 	nxgep->ouraddr = *addrp;
40613859Sml29623 	/*
40623859Sml29623 	 * Set new interface local address and re-init device.
40633859Sml29623 	 * This is destructive to any other streams attached
40643859Sml29623 	 * to this device.
40653859Sml29623 	 */
40663859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
40673859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
40683859Sml29623 		goto fail;
40693859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
40703859Sml29623 		goto fail;
40713859Sml29623 
40723859Sml29623 	RW_EXIT(&nxgep->filter_lock);
40733859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
40743859Sml29623 	goto nxge_set_mac_addr_end;
40753859Sml29623 nxge_set_mac_addr_exit:
40763859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
40773859Sml29623 nxge_set_mac_addr_end:
40783859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
40793859Sml29623 
40803859Sml29623 	return (NXGE_OK);
40813859Sml29623 fail:
40823859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
40833859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
40843859Sml29623 			"Unable to set mac address"));
40853859Sml29623 	return (status);
40863859Sml29623 }
40873859Sml29623 
40884693Stm144005 static
40894693Stm144005 check_link_state_t
40904693Stm144005 nxge_check_link_stop(
40914693Stm144005 	nxge_t *nxge)
40924693Stm144005 {
40934693Stm144005 	/* If the poll has been cancelled, return STOP. */
40944693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
40954693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
40964693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
40974693Stm144005 		nxge->nxge_link_poll_timerid = 0;
40984693Stm144005 		cv_broadcast(&nxge->poll_cv);
40994693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
41004693Stm144005 
41014693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
41024693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
41034693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
41044693Stm144005 		    nxge->mac.portnum));
41054693Stm144005 		return (CHECK_LINK_STOP);
41064693Stm144005 	}
41074693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
41084693Stm144005 
41094693Stm144005 	return (CHECK_LINK_RESCHEDULE);
41104693Stm144005 }
41114693Stm144005 
41123859Sml29623 /* Check status of MII (MIF or PCS) link */
41133859Sml29623 
41144732Sdavemq static nxge_status_t
41153859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
41163859Sml29623 {
41173859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
41183859Sml29623 	mii_anlpar_t anlpar;
41193859Sml29623 	mii_gsr_t gsr;
41203859Sml29623 	p_mii_regs_t mii_regs;
41213859Sml29623 	nxge_status_t status = NXGE_OK;
41223859Sml29623 	uint8_t portn;
41233859Sml29623 	nxge_link_state_t link_up;
41243859Sml29623 
41254693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
41264693Stm144005 		return (NXGE_ERROR);
41274693Stm144005 
41284693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
41294693Stm144005 		return (NXGE_OK);
41304693Stm144005 
41313859Sml29623 	portn = nxgep->mac.portnum;
41323859Sml29623 
41333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
41344693Stm144005 	    portn));
41353859Sml29623 
41363859Sml29623 	mii_regs = NULL;
41373859Sml29623 
41383859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
41393859Sml29623 
41403859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
41413859Sml29623 		goto nxge_check_mii_link_exit;
41423859Sml29623 
41434977Sraghus 	switch (nxgep->mac.portmode) {
41444977Sraghus 	default:
41455196Ssbehera 		bmsr_data.value = 0;
41463859Sml29623 		if ((status = nxge_mii_read(nxgep,
41474977Sraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
41485125Sjoycey #if defined(__i386)
41495125Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
41505125Sjoycey #else
41514977Sraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
41525125Sjoycey #endif
41534977Sraghus 		    &bmsr_data.value)) != NXGE_OK) {
41543859Sml29623 			goto fail;
41553859Sml29623 		}
41564977Sraghus 
41575196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41585196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
41595196Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
41605572Ssbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
41615196Ssbehera 
41624977Sraghus 		if (nxgep->param_arr[param_autoneg].value) {
41634977Sraghus 			if ((status = nxge_mii_read(nxgep,
41644977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
41655125Sjoycey #if defined(__i386)
41665125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
41675125Sjoycey #else
41684977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
41695125Sjoycey #endif
41704977Sraghus 				&gsr.value)) != NXGE_OK)
41714977Sraghus 				goto fail;
41724977Sraghus 			if ((status = nxge_mii_read(nxgep,
41734977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
41745125Sjoycey #if defined(__i386)
41755125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
41765125Sjoycey #else
41774977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
41785125Sjoycey #endif
41794977Sraghus 				&anlpar.value)) != NXGE_OK)
41804977Sraghus 				goto fail;
41815196Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
41825196Ssbehera 
41835196Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
41845196Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
41855196Ssbehera 				    gsr.bits.link_1000fdx) ||
41865196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
41875196Ssbehera 				    gsr.bits.link_1000hdx) ||
41885196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
41895196Ssbehera 				    anlpar.bits.cap_100T4) ||
41905196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
41915196Ssbehera 				    anlpar.bits.cap_100fdx) ||
41925196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
41935196Ssbehera 				    anlpar.bits.cap_100hdx) ||
41945196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
41955196Ssbehera 				    anlpar.bits.cap_10fdx) ||
41965196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
41975196Ssbehera 				    anlpar.bits.cap_10hdx))) {
41985196Ssbehera 					bmsr_data.bits.link_status = 0;
41995196Ssbehera 				}
42004977Sraghus 			}
42014977Sraghus 		}
42024977Sraghus 
42034977Sraghus 		/* Workaround for link down issue */
42044977Sraghus 		if (bmsr_data.value == 0) {
42054977Sraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
42064977Sraghus 			goto nxge_check_mii_link_exit;
42074977Sraghus 		}
42084977Sraghus 
42095196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42105196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
42115196Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
42125572Ssbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
42135196Ssbehera 
42144977Sraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
42154977Sraghus 		nxgep->bmsr.value = bmsr_data.value;
42165196Ssbehera 
42175196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42185196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
42195196Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
42205572Ssbehera 		    portn, bmsr_data.value, bmsr_ints.value));
42215196Ssbehera 
42224977Sraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
42234977Sraghus 		    &link_up)) != NXGE_OK) {
42244977Sraghus 			goto fail;
42254977Sraghus 		}
42264977Sraghus 		break;
42274977Sraghus 
42284977Sraghus 	case PORT_1G_SERDES:
42294977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42304977Sraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
42314977Sraghus 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
42324977Sraghus 		    != NXGE_OK) {
42334977Sraghus 			goto fail;
42344977Sraghus 		}
42354977Sraghus 		break;
42363859Sml29623 	}
42373859Sml29623 
42383859Sml29623 nxge_check_mii_link_exit:
42393859Sml29623 	RW_EXIT(&nxgep->filter_lock);
42403859Sml29623 	if (link_up == LINK_IS_UP) {
42413859Sml29623 		nxge_link_is_up(nxgep);
42423859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
42433859Sml29623 		nxge_link_is_down(nxgep);
42443859Sml29623 	}
42453859Sml29623 
42463859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
42473859Sml29623 
42483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
42494977Sraghus 				portn));
42503859Sml29623 	return (NXGE_OK);
42513859Sml29623 
42523859Sml29623 fail:
42533859Sml29623 	RW_EXIT(&nxgep->filter_lock);
42543859Sml29623 
42553859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
42563859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42574977Sraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
42584977Sraghus 			portn));
42593859Sml29623 	return (status);
42603859Sml29623 }
42613859Sml29623 
42623859Sml29623 
42633859Sml29623 /*ARGSUSED*/
42644732Sdavemq static nxge_status_t
42653859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
42663859Sml29623 {
42673859Sml29623 	uint8_t		portn;
42683859Sml29623 	nxge_status_t	status = NXGE_OK;
42695422Ssbehera 	boolean_t	link_up;
42704977Sraghus 	uint32_t	val;
42714977Sraghus 	npi_status_t	rs;
42723859Sml29623 
42734693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
42744693Stm144005 		return (NXGE_ERROR);
42754693Stm144005 
42764693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
42774693Stm144005 		return (NXGE_OK);
42784693Stm144005 
42793859Sml29623 	portn = nxgep->mac.portnum;
42805196Ssbehera 	val = 0;
42815196Ssbehera 	rs = NPI_SUCCESS;
42823859Sml29623 
42833859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
42844693Stm144005 	    portn));
42853859Sml29623 
42864977Sraghus 	switch (nxgep->mac.portmode) {
42874977Sraghus 	default:
42885572Ssbehera 		/*
42895572Ssbehera 		 * Check if the phy is present in case of hot swappable phy
42905572Ssbehera 		 */
42915572Ssbehera 		if (nxgep->hot_swappable_phy) {
42925572Ssbehera 			boolean_t phy_present_now = B_FALSE;
42935572Ssbehera 
42945572Ssbehera 			/*
42955572Ssbehera 			 * If this is the 2nd Goa port, then check 2 addresses
42965572Ssbehera 			 * to take care of the Goa NEM card requirements.
42975572Ssbehera 			 */
42985572Ssbehera 			if (portn == 1) {
42995572Ssbehera 				if (nxge_is_phy_present(nxgep,
43005572Ssbehera 				    BCM8706_ALT_GOA_PORT1_ADDR,
43015572Ssbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
43025572Ssbehera 					phy_present_now = B_TRUE;
43035572Ssbehera 					nxgep->xcvr_addr =
43045572Ssbehera 					    BCM8706_ALT_GOA_PORT1_ADDR;
43055572Ssbehera 					goto phy_check_done;
43065572Ssbehera 				}
43075572Ssbehera 			}
43085572Ssbehera 			if (nxge_is_phy_present(nxgep,
43095572Ssbehera 			    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
43105572Ssbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
43115572Ssbehera 				nxgep->xcvr_addr =
43125572Ssbehera 				    (BCM8706_GOA_PORT_ADDR_BASE) + portn;
43135572Ssbehera 				phy_present_now = B_TRUE;
43145572Ssbehera 			}
43155572Ssbehera 
43165572Ssbehera phy_check_done:
43175572Ssbehera 			if (nxgep->phy_absent) {
43185572Ssbehera 				if (phy_present_now) {
43195572Ssbehera 				/*
43205572Ssbehera 				 * Detect, Initialize phy and do link up
43215572Ssbehera 				 * set xcvr vals, link_init, nxge_init
43225572Ssbehera 				 */
43235572Ssbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43245572Ssbehera 					    "Hot swappable phy DETECTED!!"));
43255572Ssbehera 					nxgep->phy_absent = B_FALSE;
43265572Ssbehera 					(void) nxge_xcvr_find(nxgep);
43275572Ssbehera 					(void) nxge_link_init(nxgep);
43285572Ssbehera 					if (!(nxgep->drv_state &
43295572Ssbehera 					    STATE_HW_INITIALIZED)) {
43305572Ssbehera 						status = nxge_init(nxgep);
43315572Ssbehera 						if (status != NXGE_OK) {
43325572Ssbehera 							NXGE_ERROR_MSG((nxgep,
43335572Ssbehera 							    NXGE_ERR_CTL,
43345572Ssbehera 							    "Hot swappable "
43355572Ssbehera 							    "phy present, but"
43365572Ssbehera 							    " driver init"
43375572Ssbehera 							    "  failed..."));
43385572Ssbehera 							goto fail;
43395572Ssbehera 						}
43405572Ssbehera 					}
43415572Ssbehera 				}
43425572Ssbehera 
43435572Ssbehera 				goto start_link_check;
43445572Ssbehera 
43455572Ssbehera 			} else if (!phy_present_now) {
43465572Ssbehera 				/*
43475572Ssbehera 				 * Phy gone, bring link down reset xcvr vals
43485572Ssbehera 				 */
43495572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43505572Ssbehera 				    "Hot swappable phy REMOVED!!"));
43515572Ssbehera 				nxgep->phy_absent = B_TRUE;
43525572Ssbehera 				nxgep->statsp->mac_stats.link_up = 0;
43535572Ssbehera 				nxgep->statsp->mac_stats.link_speed = 0;
43545572Ssbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
43555572Ssbehera 				nxge_link_is_down(nxgep);
43565572Ssbehera 				nxgep->link_notify = B_FALSE;
43575572Ssbehera 
43585572Ssbehera 				(void) nxge_xcvr_find(nxgep);
43595572Ssbehera 
43605572Ssbehera 				goto start_link_check;
43615572Ssbehera 
43625572Ssbehera 			}
43635572Ssbehera 		}
43645572Ssbehera 
43654977Sraghus 		status = nxge_check_bcm8704_link(nxgep, &link_up);
43664977Sraghus 		if (status != NXGE_OK)
43674977Sraghus 			goto fail;
43684977Sraghus 		break;
43694977Sraghus 	case PORT_10G_SERDES:
43704977Sraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
43715422Ssbehera 		    XPCS_REG_STATUS, &val);
43724977Sraghus 		if (rs != 0)
43734977Sraghus 			goto fail;
43744977Sraghus 
43754977Sraghus 		link_up = B_FALSE;
43765422Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
43775422Ssbehera 			link_up = B_TRUE;
43784977Sraghus 		}
43794977Sraghus 
43804977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43814977Sraghus 		    "==> nxge_check_10g_link port<%d> "
43825422Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
43835422Ssbehera 		    portn, val, link_up));
43845422Ssbehera 
43854977Sraghus 		break;
43864977Sraghus 	}
43873859Sml29623 
43883859Sml29623 	if (link_up) {
43893859Sml29623 		if (nxgep->link_notify ||
43903859Sml29623 			nxgep->statsp->mac_stats.link_up == 0) {
43913859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
43923859Sml29623 				goto fail;
43933859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
43943859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
43953859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
43963859Sml29623 
43973859Sml29623 			nxge_link_is_up(nxgep);
43983859Sml29623 			nxgep->link_notify = B_FALSE;
43993859Sml29623 		}
44003859Sml29623 	} else {
44013859Sml29623 		if (nxgep->link_notify ||
44023859Sml29623 			nxgep->statsp->mac_stats.link_up == 1) {
44033859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
44043859Sml29623 				goto fail;
44053859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44064977Sraghus 					"Link down cable problem"));
44073859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
44083859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
44093859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
44103859Sml29623 
44113859Sml29623 			nxge_link_is_down(nxgep);
44123859Sml29623 			nxgep->link_notify = B_FALSE;
44133859Sml29623 		}
44143859Sml29623 	}
44153859Sml29623 
44165572Ssbehera start_link_check:
44173859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
44183859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
44194693Stm144005 	    portn));
44203859Sml29623 	return (NXGE_OK);
44213859Sml29623 
44223859Sml29623 fail:
44234693Stm144005 	(void) nxge_check_link_stop(nxgep);
44244693Stm144005 
44253859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
44264693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
44274693Stm144005 	    portn));
44283859Sml29623 	return (status);
44293859Sml29623 }
44303859Sml29623 
44313859Sml29623 
44323859Sml29623 /* Declare link down */
44333859Sml29623 
44343859Sml29623 void
44353859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
44363859Sml29623 {
44374732Sdavemq 	p_nxge_stats_t statsp;
44384732Sdavemq 	char link_stat_msg[64];
44394732Sdavemq 
44403859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
44413859Sml29623 
44424732Sdavemq 	statsp = nxgep->statsp;
44434732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
44444732Sdavemq 	    statsp->mac_stats.xcvr_portn);
44454732Sdavemq 
44464732Sdavemq 	if (nxge_no_msg == B_FALSE) {
44474732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
44484732Sdavemq 	}
44494732Sdavemq 
44503859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
44513859Sml29623 
44523859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
44533859Sml29623 }
44543859Sml29623 
44553859Sml29623 /* Declare link up */
44563859Sml29623 
44573859Sml29623 void
44583859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
44593859Sml29623 {
44604732Sdavemq 	p_nxge_stats_t statsp;
44614732Sdavemq 	char link_stat_msg[64];
44623859Sml29623 	uint32_t val;
44633859Sml29623 
44643859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
44653859Sml29623 
44664732Sdavemq 	statsp = nxgep->statsp;
44674732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
44684732Sdavemq 	    statsp->mac_stats.xcvr_portn,
44694732Sdavemq 	    statsp->mac_stats.link_speed);
44704732Sdavemq 
44714732Sdavemq 	if (statsp->mac_stats.link_T4)
44724732Sdavemq 		(void) strcat(link_stat_msg, "T4");
44734732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
44744732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
44754732Sdavemq 	else
44764732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
44774732Sdavemq 
44783859Sml29623 	(void) nxge_xif_init(nxgep);
44793859Sml29623 
44803859Sml29623 	/* Clean up symbol errors incurred during link transition */
44814977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
44824977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
44833859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
44843859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
44853859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
44863859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
44873859Sml29623 	}
44883859Sml29623 
44894732Sdavemq 	if (nxge_no_msg == B_FALSE) {
44904732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
44914732Sdavemq 	}
44924732Sdavemq 
44933859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
44943859Sml29623 
44953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
44963859Sml29623 }
44973859Sml29623 
44983859Sml29623 /*
44993859Sml29623  * Calculate the bit in the multicast address filter
45003859Sml29623  * that selects the given * address.
45013859Sml29623  * Note: For GEM, the last 8-bits are used.
45023859Sml29623  */
45033859Sml29623 uint32_t
45043859Sml29623 crc32_mchash(p_ether_addr_t addr)
45053859Sml29623 {
45063859Sml29623 	uint8_t *cp;
45073859Sml29623 	uint32_t crc;
45083859Sml29623 	uint32_t c;
45093859Sml29623 	int byte;
45103859Sml29623 	int bit;
45113859Sml29623 
45123859Sml29623 	cp = (uint8_t *)addr;
45133859Sml29623 	crc = (uint32_t)0xffffffff;
45143859Sml29623 	for (byte = 0; byte < 6; byte++) {
45153859Sml29623 		c = (uint32_t)cp[byte];
45163859Sml29623 		for (bit = 0; bit < 8; bit++) {
45173859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
45183859Sml29623 				crc = (crc >> 1)^0xedb88320;
45193859Sml29623 			else
45203859Sml29623 				crc = (crc >> 1);
45213859Sml29623 			c >>= 1;
45223859Sml29623 		}
45233859Sml29623 	}
45243859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
45253859Sml29623 }
45263859Sml29623 
45273859Sml29623 /* Reset serdes */
45283859Sml29623 
45293859Sml29623 nxge_status_t
45303859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
45313859Sml29623 {
45323859Sml29623 	npi_handle_t		handle;
45333859Sml29623 
45343859Sml29623 	handle = nxgep->npi_handle;
45353859Sml29623 
45363859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
45373859Sml29623 	drv_usecwait(500);
45383859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
45393859Sml29623 
45403859Sml29623 	return (NXGE_OK);
45413859Sml29623 }
45423859Sml29623 
45433859Sml29623 /* Monitor link status using interrupt or polling */
45443859Sml29623 
45453859Sml29623 nxge_status_t
45463859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
45473859Sml29623 {
45483859Sml29623 	nxge_status_t status = NXGE_OK;
45493859Sml29623 
45503859Sml29623 	/*
45514693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
45524693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
45533859Sml29623 	 */
45544977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
45554977Sraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
45564977Sraghus 	    (nxgep->mac.portnum > 1))
45573859Sml29623 		return (NXGE_OK);
45583859Sml29623 
45593859Sml29623 	if (nxgep->statsp == NULL) {
45603859Sml29623 		/* stats has not been allocated. */
45613859Sml29623 		return (NXGE_OK);
45623859Sml29623 	}
45633859Sml29623 	/* Don't check link if we're not in internal loopback mode */
45643859Sml29623 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
45653859Sml29623 		return (NXGE_OK);
45663859Sml29623 
45673859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45684693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
45694693Stm144005 	    nxgep->mac.portnum, enable));
45703859Sml29623 	if (enable == LINK_MONITOR_START) {
45713859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
45723859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
45734693Stm144005 			    != NXGE_OK)
45743859Sml29623 				goto fail;
45753859Sml29623 		} else {
45764693Stm144005 			timeout_id_t timerid;
45774693Stm144005 
45784693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
45794693Stm144005 				return (NXGE_OK);
45804693Stm144005 
45814732Sdavemq 			if (nxgep->xcvr.check_link) {
45824732Sdavemq 				timerid = timeout(
45834732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
45844693Stm144005 				    nxgep,
45854693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
45864732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
45874732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
45884732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
45894732Sdavemq 			} else {
45904693Stm144005 				return (NXGE_ERROR);
45913859Sml29623 			}
45923859Sml29623 		}
45933859Sml29623 	} else {
45943859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
45953859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
45964693Stm144005 			    != NXGE_OK)
45973859Sml29623 				goto fail;
45983859Sml29623 		} else {
45994693Stm144005 			clock_t rv;
46004693Stm144005 
46014693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
46024693Stm144005 
46034693Stm144005 			/* If <timerid> == 0, the link monitor has */
46044693Stm144005 			/* never been started, or just now stopped. */
46054693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
46064693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
46074693Stm144005 				return (NXGE_OK);
46084693Stm144005 			}
46094693Stm144005 
46104693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
46114693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
46124693Stm144005 			    &nxgep->poll_lock,
46134693Stm144005 			    ddi_get_lbolt() +
46144693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
46154693Stm144005 			    LINK_MONITOR_PERIOD));
46164693Stm144005 			if (rv == -1) {
46174693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46184693Stm144005 				    "==> stopping port %d: "
46194693Stm144005 				    "cv_timedwait(%d) timed out",
46204693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
46214693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
46223859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
46233859Sml29623 			}
46244693Stm144005 
46254693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
46263859Sml29623 		}
46273859Sml29623 	}
46283859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46294693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
46304693Stm144005 	    nxgep->mac.portnum, enable));
46313859Sml29623 	return (NXGE_OK);
46323859Sml29623 fail:
46333859Sml29623 	return (status);
46343859Sml29623 }
46353859Sml29623 
46363859Sml29623 /* Set promiscous mode */
46373859Sml29623 
46383859Sml29623 nxge_status_t
46393859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
46403859Sml29623 {
46413859Sml29623 	nxge_status_t status = NXGE_OK;
46423859Sml29623 
46434732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
46443859Sml29623 
46453859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
46463859Sml29623 
46473859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
46483859Sml29623 
46493859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
46503859Sml29623 		goto fail;
46513859Sml29623 	}
46523859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
46533859Sml29623 		goto fail;
46543859Sml29623 	}
46553859Sml29623 
46563859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46573859Sml29623 
46583859Sml29623 	if (on)
46593859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
46603859Sml29623 	else
46613859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
46623859Sml29623 
46633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
46643859Sml29623 
46653859Sml29623 	return (NXGE_OK);
46663859Sml29623 fail:
46673859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46683859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
46694732Sdavemq 	    "Unable to set promisc (%d)", on));
46703859Sml29623 
46713859Sml29623 	return (status);
46723859Sml29623 }
46733859Sml29623 
46743859Sml29623 /*ARGSUSED*/
46753859Sml29623 uint_t
46763859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
46773859Sml29623 {
46783859Sml29623 #ifdef	NXGE_DEBUG
46793859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
46803859Sml29623 #endif
46813859Sml29623 #if NXGE_MIF
46823859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
46833859Sml29623 	uint32_t		status;
46843859Sml29623 	npi_handle_t		handle;
46853859Sml29623 	uint8_t			portn;
46863859Sml29623 	p_nxge_stats_t		statsp;
46873859Sml29623 #endif
46883859Sml29623 
46893859Sml29623 #ifdef	NXGE_MIF
46903859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
46913859Sml29623 		nxgep = ldvp->nxgep;
46923859Sml29623 	}
46933859Sml29623 	nxgep = ldvp->nxgep;
46943859Sml29623 #endif
46953859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
46963859Sml29623 
46973859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
46983859Sml29623 	return (DDI_INTR_CLAIMED);
46993859Sml29623 
47003859Sml29623 mif_intr_fail:
47013859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
47023859Sml29623 	return (DDI_INTR_UNCLAIMED);
47033859Sml29623 }
47043859Sml29623 
47053859Sml29623 /*ARGSUSED*/
47063859Sml29623 uint_t
47073859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
47083859Sml29623 {
47093859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
47103859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
47113859Sml29623 	p_nxge_ldg_t		ldgp;
47123859Sml29623 	uint32_t		status;
47133859Sml29623 	npi_handle_t		handle;
47143859Sml29623 	uint8_t			portn;
47153859Sml29623 	p_nxge_stats_t		statsp;
47163859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
47173859Sml29623 
47183859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
47193859Sml29623 		nxgep = ldvp->nxgep;
47203859Sml29623 	}
47213859Sml29623 
47223859Sml29623 	ldgp = ldvp->ldgp;
47233859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
47244732Sdavemq 	    "group %d", ldgp->ldg));
47253859Sml29623 
47263859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
47273859Sml29623 	/*
47283859Sml29623 	 * This interrupt handler is for a specific
47293859Sml29623 	 * mac port.
47303859Sml29623 	 */
47313859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
47323859Sml29623 	portn = nxgep->mac.portnum;
47333859Sml29623 
47343859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
47354732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
47363859Sml29623 
47373859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
47383859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
47393859Sml29623 					(xmac_tx_iconfig_t *)&status);
47403859Sml29623 		if (rs != NPI_SUCCESS)
47413859Sml29623 			goto npi_fail;
47423859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
47433859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
47443859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
47453859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
47463859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
47473859Sml29623 			}
47483859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
47493859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
47505523Syc148097 				/*
47515523Syc148097 				 * Do not send FMA ereport because this
47525523Syc148097 				 * error does not indicate HW failure.
47535523Syc148097 				 */
47543859Sml29623 			}
47553859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
47563859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
47573859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
47583859Sml29623 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
47593859Sml29623 			}
47603859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
47613859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
47623859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
47633859Sml29623 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
47643859Sml29623 			}
47653859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
47663859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
47673859Sml29623 							XTXMAC_BYTE_CNT_MASK;
47683859Sml29623 			}
47693859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
47703859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
47713859Sml29623 							XTXMAC_FRM_CNT_MASK;
47723859Sml29623 			}
47733859Sml29623 		}
47743859Sml29623 
47753859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
47763859Sml29623 					(xmac_rx_iconfig_t *)&status);
47773859Sml29623 		if (rs != NPI_SUCCESS)
47783859Sml29623 			goto npi_fail;
47793859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
47803859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
47813859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
47823859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
47833859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
47843859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
47853859Sml29623 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
47863859Sml29623 			}
47875523Syc148097 			/*
47885523Syc148097 			 * Do not send FMA ereport for the following 3 errors
47895523Syc148097 			 * because they do not indicate HW failures.
47905523Syc148097 			 */
47913859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
47923859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
47933859Sml29623 							XRXMAC_CRC_ER_CNT_MASK;
47943859Sml29623 			}
47953859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
47963859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
47973859Sml29623 							MAC_LEN_ER_CNT_MASK;
47983859Sml29623 			}
47993859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
48003859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
48013859Sml29623 							XRXMAC_CD_VIO_CNT_MASK;
48023859Sml29623 			}
48033859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
48043859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
48053859Sml29623 							XRXMAC_BT_CNT_MASK;
48063859Sml29623 			}
48073859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
48083859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
48093859Sml29623 							XRXMAC_HIST_CNT1_MASK;
48103859Sml29623 			}
48113859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
48123859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
48133859Sml29623 							XRXMAC_HIST_CNT2_MASK;
48143859Sml29623 			}
48153859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
48163859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
48173859Sml29623 							XRXMAC_HIST_CNT3_MASK;
48183859Sml29623 			}
48193859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
48203859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
48213859Sml29623 							XRXMAC_HIST_CNT4_MASK;
48223859Sml29623 			}
48233859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
48243859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
48253859Sml29623 							XRXMAC_HIST_CNT5_MASK;
48263859Sml29623 			}
48273859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
48283859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
48293859Sml29623 							XRXMAC_HIST_CNT6_MASK;
48303859Sml29623 			}
48313859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
48323859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
48333859Sml29623 							XRXMAC_BC_FRM_CNT_MASK;
48343859Sml29623 			}
48353859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
48363859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
48373859Sml29623 							XRXMAC_MC_FRM_CNT_MASK;
48383859Sml29623 			}
48395523Syc148097 			/*
48405523Syc148097 			 * Do not send FMA ereport for the following 3 errors
48415523Syc148097 			 * because they do not indicate HW failures.
48425523Syc148097 			 */
48433859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
48443859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
48453859Sml29623 							XRXMAC_FRAG_CNT_MASK;
48463859Sml29623 			}
48473859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
48483859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
48493859Sml29623 							XRXMAC_AL_ER_CNT_MASK;
48503859Sml29623 			}
48513859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
48523859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
48533859Sml29623 							XMAC_LINK_FLT_CNT_MASK;
48543859Sml29623 			}
48553859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
48563859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
48573859Sml29623 			}
48583859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
48593859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
48603859Sml29623 			}
48613859Sml29623 		}
48623859Sml29623 
48633859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
48643859Sml29623 						(xmac_ctl_iconfig_t *)&status);
48653859Sml29623 		if (rs != NPI_SUCCESS)
48663859Sml29623 			goto npi_fail;
48673859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
48683859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
48693859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
48703859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
48713859Sml29623 				statsp->xmac_stats.tx_pause_state++;
48723859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
48733859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
48743859Sml29623 		}
48753859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
48763859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
48773859Sml29623 						(bmac_tx_iconfig_t *)&status);
48783859Sml29623 		if (rs != NPI_SUCCESS)
48793859Sml29623 			goto npi_fail;
48803859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
48813859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
48823859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
48833859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
48843859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
48853859Sml29623 			}
48863859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
48873859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
48883859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
48893859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
48903859Sml29623 			}
48913859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
48923859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
48933859Sml29623 							BTXMAC_BYTE_CNT_MASK;
48943859Sml29623 			}
48953859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
48963859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
48973859Sml29623 							BTXMAC_FRM_CNT_MASK;
48983859Sml29623 			}
48993859Sml29623 		}
49003859Sml29623 
49013859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
49023859Sml29623 						(bmac_rx_iconfig_t *)&status);
49033859Sml29623 		if (rs != NPI_SUCCESS)
49043859Sml29623 			goto npi_fail;
49053859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
49063859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
49073859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
49083859Sml29623 			}
49093859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
49103859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
49113859Sml29623 							RXMAC_FRM_CNT_MASK;
49123859Sml29623 			}
49133859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
49143859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
49153859Sml29623 							BMAC_CRC_ER_CNT_MASK;
49163859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
49173859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
49183859Sml29623 			}
49193859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
49203859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
49213859Sml29623 							MAC_LEN_ER_CNT_MASK;
49223859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
49233859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
49243859Sml29623 			}
49253859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
49263859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
49273859Sml29623 							BMAC_CD_VIO_CNT_MASK;
49283859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
49293859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
49303859Sml29623 			}
49313859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
49323859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
49333859Sml29623 							BRXMAC_BYTE_CNT_MASK;
49343859Sml29623 			}
49353859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
49363859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
49373859Sml29623 							BMAC_AL_ER_CNT_MASK;
49383859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
49393859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
49403859Sml29623 			}
49413859Sml29623 
49423859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
49433859Sml29623 						(bmac_ctl_iconfig_t *)&status);
49443859Sml29623 			if (rs != NPI_SUCCESS)
49453859Sml29623 				goto npi_fail;
49463859Sml29623 
49473859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
49483859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
49493859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
49503859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
49513859Sml29623 					statsp->bmac_stats.tx_pause_state++;
49523859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
49533859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
49543859Sml29623 			}
49553859Sml29623 		}
49563859Sml29623 
49573859Sml29623 	if (ldgp->nldvs == 1) {
49583859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
49593859Sml29623 			B_TRUE, ldgp->ldg_timer);
49603859Sml29623 	}
49613859Sml29623 
49623859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
49633859Sml29623 	return (DDI_INTR_CLAIMED);
49643859Sml29623 
49653859Sml29623 npi_fail:
49663859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
49673859Sml29623 	return (DDI_INTR_UNCLAIMED);
49683859Sml29623 }
49693859Sml29623 
49703859Sml29623 nxge_status_t
49713859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
49723859Sml29623 {
49733859Sml29623 	uint8_t		phy_port_addr;
49743859Sml29623 	nxge_status_t	status = NXGE_OK;
49753859Sml29623 	boolean_t	rx_sig_ok;
49763859Sml29623 	boolean_t	pcs_blk_lock;
49773859Sml29623 	boolean_t	link_align;
49783859Sml29623 	uint16_t	val1, val2, val3;
49793859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
49803859Sml29623 	uint16_t	val_debug;
49813859Sml29623 	uint16_t	val;
49823859Sml29623 #endif
49833859Sml29623 
49843859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
49853859Sml29623 
49863859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
49873859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
49883859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
49893859Sml29623 	if ((val_debug & ~0x200) != 0) {
49903859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
49913859Sml29623 				nxgep->mac.portnum, val_debug);
49923859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
49933859Sml29623 				&val_debug);
49943859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
49953859Sml29623 				nxgep->mac.portnum, val_debug);
49963859Sml29623 	}
49973859Sml29623 
49983859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
49993859Sml29623 					XPCS_REG_DESCWERR_COUNTER, &val);
50003859Sml29623 	if (val != 0)
50013859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
50023859Sml29623 
50033859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
50043859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
50053859Sml29623 	if (val != 0)
50063859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
50073859Sml29623 
50083859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
50093859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
50103859Sml29623 	if (val != 0)
50113859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
50123859Sml29623 #endif
50133859Sml29623 
50143859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
50153859Sml29623 
50163859Sml29623 	/* Check Device 1 Register 0xA bit0 */
50173859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
50183859Sml29623 			BCM8704_PMA_PMD_DEV_ADDR,
50193859Sml29623 			BCM8704_PMD_RECEIVE_SIG_DETECT,
50203859Sml29623 			&val1);
50213859Sml29623 	if (status != NXGE_OK)
50223859Sml29623 		goto fail;
50233859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
50243859Sml29623 
50253859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
50263859Sml29623 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
50273859Sml29623 			BCM8704_PCS_DEV_ADDR,
50283859Sml29623 			BCM8704_10GBASE_R_PCS_STATUS_REG,
50293859Sml29623 			&val2)) != NPI_SUCCESS)
50303859Sml29623 		goto fail;
50313859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
50323859Sml29623 
50333859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
50343859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
50353859Sml29623 			BCM8704_PHYXS_ADDR,
50363859Sml29623 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
50373859Sml29623 			&val3);
50383859Sml29623 	if (status != NXGE_OK)
50393859Sml29623 		goto fail;
50405572Ssbehera 
50415572Ssbehera 	switch (nxgep->chip_id) {
50425572Ssbehera 	case BCM8704_CHIP_ID:
50435572Ssbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
50445572Ssbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
50455572Ssbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
50465572Ssbehera 		break;
50475572Ssbehera 	case BCM8706_CHIP_ID:
50485572Ssbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
50495572Ssbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
50505572Ssbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
50515572Ssbehera 		    B_TRUE : B_FALSE;
50525572Ssbehera 		break;
50535572Ssbehera 	default:
50545572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
50555572Ssbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
50565572Ssbehera 		goto fail;
50575572Ssbehera 	}
50585572Ssbehera 
50593859Sml29623 
50603859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
50613859Sml29623 	/* Temp workaround for link down issue */
50623859Sml29623 	if (pcs_blk_lock == B_FALSE) {
50633859Sml29623 		if (val2 != 0x4) {
50643859Sml29623 			pcs_blk_lock = B_TRUE;
50653859Sml29623 			cmn_err(CE_NOTE,
50663859Sml29623 				"!LINK DEBUG: port%d PHY Dev3 "
50673859Sml29623 				"Reg 0x20 = 0x%x\n",
50683859Sml29623 				nxgep->mac.portnum, val2);
50693859Sml29623 		}
50703859Sml29623 	}
50713859Sml29623 
50723859Sml29623 	if (link_align == B_FALSE) {
50733859Sml29623 		if (val3 != 0x140f) {
50743859Sml29623 			link_align = B_TRUE;
50753859Sml29623 			cmn_err(CE_NOTE,
50763859Sml29623 				"!LINK DEBUG: port%d PHY Dev4 "
50773859Sml29623 				"Reg 0x18 = 0x%x\n",
50783859Sml29623 				nxgep->mac.portnum, val3);
50793859Sml29623 		}
50803859Sml29623 	}
50813859Sml29623 
50823859Sml29623 	if (rx_sig_ok == B_FALSE) {
50833859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
50843859Sml29623 			rx_sig_ok = B_TRUE;
50853859Sml29623 			cmn_err(CE_NOTE,
50863859Sml29623 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
50873859Sml29623 				nxgep->mac.portnum);
50883859Sml29623 		}
50893859Sml29623 	}
50903859Sml29623 #endif
50913859Sml29623 
50923859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
50933859Sml29623 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
50943859Sml29623 
50953859Sml29623 	return (NXGE_OK);
50963859Sml29623 fail:
50973859Sml29623 	return (status);
50983859Sml29623 }
50993859Sml29623 
51003859Sml29623 nxge_status_t
51013859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
51023859Sml29623 {
51033859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
51044732Sdavemq 	    != NPI_SUCCESS)
51053859Sml29623 		return (NXGE_ERROR);
51063859Sml29623 	else
51073859Sml29623 		return (NXGE_OK);
51083859Sml29623 }
51093859Sml29623 
51103859Sml29623 nxge_status_t
51113859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
51123859Sml29623 {
51133859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
51144732Sdavemq 	    != NPI_SUCCESS)
51153859Sml29623 		return (NXGE_ERROR);
51163859Sml29623 	else
51173859Sml29623 		return (NXGE_OK);
51183859Sml29623 }
51194185Sspeer 
51205572Ssbehera static boolean_t
51215572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
51225572Ssbehera {
51235572Ssbehera 	uint32_t pma_pmd_id = 0;
51245572Ssbehera 	uint32_t pcs_id = 0;
51255572Ssbehera 	uint32_t phy_id = 0;
51265572Ssbehera 
51275572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
51285572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51295572Ssbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
51305572Ssbehera 	if ((pma_pmd_id & mask) == (id & mask))
51315572Ssbehera 		goto found_phy;
51325572Ssbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
51335572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51345572Ssbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
51355572Ssbehera 	if ((pcs_id & mask) == (id & mask))
51365572Ssbehera 		goto found_phy;
51375572Ssbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
51385572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51395572Ssbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
51405572Ssbehera 	if ((phy_id & mask) == (id & mask))
51415572Ssbehera 		goto found_phy;
51425572Ssbehera 
51435572Ssbehera 	return (B_FALSE);
51445572Ssbehera 
51455572Ssbehera found_phy:
51465572Ssbehera 	return (B_TRUE);
51475572Ssbehera }
51485572Ssbehera 
51494732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
51504732Sdavemq 
51514732Sdavemq static boolean_t
51524732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
51534732Sdavemq {
51544732Sdavemq 	int		i;
51554732Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
51564732Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
51574732Sdavemq 	boolean_t	found = B_FALSE;
51584732Sdavemq 
51594732Sdavemq 	switch (type) {
51604732Sdavemq 	case CLAUSE_45_TYPE:
51614732Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
51624782Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
51634782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
51644732Sdavemq 				found = B_TRUE;
51654732Sdavemq 				break;
51664732Sdavemq 			}
51674732Sdavemq 		}
51684732Sdavemq 		break;
51694732Sdavemq 	case CLAUSE_22_TYPE:
51704732Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
51714782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
51724782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
51734732Sdavemq 				found = B_TRUE;
51744732Sdavemq 				break;
51754732Sdavemq 			}
51764732Sdavemq 		}
51774732Sdavemq 		break;
51784732Sdavemq 	default:
51794732Sdavemq 		break;
51804732Sdavemq 	}
51814732Sdavemq 
51824732Sdavemq 	return (found);
51834732Sdavemq }
51844732Sdavemq 
51854977Sraghus static uint32_t
51864977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
51874977Sraghus {
51884977Sraghus 	uint16_t	val1 = 0;
51894977Sraghus 	uint16_t	val2 = 0;
51904977Sraghus 	uint32_t	pma_pmd_dev_id = 0;
51914977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
51924977Sraghus 
51935780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
51944977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
51954977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
51964977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
51974977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
51985780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
51994977Sraghus 
52004977Sraghus 	pma_pmd_dev_id = val1;
52014977Sraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
52024977Sraghus 	pma_pmd_dev_id |= val2;
52034977Sraghus 
52044977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
52054977Sraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
52064977Sraghus 
52074977Sraghus 	return (pma_pmd_dev_id);
52084977Sraghus }
52094977Sraghus 
52104977Sraghus static uint32_t
52114977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
52124977Sraghus {
52134977Sraghus 	uint16_t	val1 = 0;
52144977Sraghus 	uint16_t	val2 = 0;
52154977Sraghus 	uint32_t	pcs_dev_id = 0;
52164977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
52174977Sraghus 
52185780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
52194977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
52204977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
52214977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
52224977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
52235780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
52244977Sraghus 
52254977Sraghus 	pcs_dev_id = val1;
52264977Sraghus 	pcs_dev_id = (pcs_dev_id << 16);
52274977Sraghus 	pcs_dev_id |= val2;
52284977Sraghus 
52294977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
52304977Sraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
52314977Sraghus 
52324977Sraghus 	return (pcs_dev_id);
52334977Sraghus }
52344977Sraghus 
52354977Sraghus static uint32_t
52364977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
52374977Sraghus {
52384977Sraghus 	uint16_t	val1 = 0;
52394977Sraghus 	uint16_t	val2 = 0;
52404977Sraghus 	uint32_t	phy_id = 0;
52414977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
52424977Sraghus 	npi_status_t	npi_status = NPI_SUCCESS;
52434977Sraghus 
52445780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock);
52454977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
52464977Sraghus 	    &val1);
52474977Sraghus 	if (npi_status != NPI_SUCCESS) {
52484977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
52494977Sraghus 		    "clause 22 read to reg 2 failed!!!"));
52504977Sraghus 		goto exit;
52514977Sraghus 	}
52524977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
52534977Sraghus 	    &val2);
52544977Sraghus 	if (npi_status != 0) {
52554977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
52564977Sraghus 		    "clause 22 read to reg 3 failed!!!"));
52574977Sraghus 		goto exit;
52584977Sraghus 	}
52594977Sraghus 	phy_id = val1;
52604977Sraghus 	phy_id = (phy_id << 16);
52614977Sraghus 	phy_id |= val2;
52624977Sraghus 
52634977Sraghus exit:
52645780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
52654977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
52664977Sraghus 	    phy_port, phy_id));
52674977Sraghus 
52684977Sraghus 	return (phy_id);
52694977Sraghus }
52704977Sraghus 
52714732Sdavemq /*
52724732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
52734732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
52744732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
52754732Sdavemq  * and the Neptune type.
52764732Sdavemq  */
52774732Sdavemq 
52784732Sdavemq nxge_status_t
52794732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
52804732Sdavemq {
52814732Sdavemq 	int		i, j, k, l;
52824732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
52834732Sdavemq 	uint32_t	pcs_dev_id = 0;
52844732Sdavemq 	uint32_t	phy_id = 0;
52854782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
52864782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
52874782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
52884732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
52894732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
52905572Ssbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
52915572Ssbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
52924732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
52934732Sdavemq 	nxge_status_t	status = NXGE_OK;
52944732Sdavemq 
52954732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
52964732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
52974732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
52984732Sdavemq 	    nxgep->niu_type));
52994732Sdavemq 
53004732Sdavemq 	j = k = l = 0;
53014732Sdavemq 	total_port_fd = total_phy_fd = 0;
53024732Sdavemq 	/*
53034732Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
53044732Sdavemq 	 * for on chip serdes usages.
53054732Sdavemq 	 */
53064732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
53074977Sraghus 
53084977Sraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
53094732Sdavemq 
53104732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
53114732Sdavemq 			pma_pmd_dev_fd[i] = 1;
53124732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
53134732Sdavemq 			    "PMA/PMD dev found", i));
53144782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
53154782Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
53164782Ssbehera 				    BCM_PHY_ID_MASK;
53175572Ssbehera 				port_fd_arr[j] = (uint8_t)i;
53184732Sdavemq 				j++;
53194732Sdavemq 			}
53204732Sdavemq 		} else {
53214732Sdavemq 			pma_pmd_dev_fd[i] = 0;
53224732Sdavemq 		}
53234732Sdavemq 
53244977Sraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
53254732Sdavemq 
53264732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
53274732Sdavemq 			pcs_dev_fd[i] = 1;
53284732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
53294732Sdavemq 			    "dev found", i));
53304782Ssbehera 			if (k < NXGE_PORTS_NEPTUNE) {
53314782Ssbehera 				port_pcs_dev_id[k] = pcs_dev_id &
53324782Ssbehera 				    BCM_PHY_ID_MASK;
53335572Ssbehera 				port_fd_arr[k] = (uint8_t)i;
53344732Sdavemq 				k++;
53354732Sdavemq 			}
53364732Sdavemq 		} else {
53374732Sdavemq 			pcs_dev_fd[i] = 0;
53384732Sdavemq 		}
53394732Sdavemq 
53405572Ssbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
53415572Ssbehera 			total_port_fd ++;
53425572Ssbehera 		}
53434732Sdavemq 
53444977Sraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
53454732Sdavemq 
53464732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
53475572Ssbehera 			total_phy_fd ++;
53484732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
53494732Sdavemq 			    "found", i));
53504782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
53514782Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
53525572Ssbehera 				phy_fd_arr[l] = (uint8_t)i;
53534732Sdavemq 				l++;
53544732Sdavemq 			}
53554732Sdavemq 		}
53564732Sdavemq 	}
53574732Sdavemq 
53584732Sdavemq 	switch (total_port_fd) {
53594732Sdavemq 	case 2:
53604732Sdavemq 		switch (total_phy_fd) {
53614732Sdavemq 		case 2:
53624977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53634977Sraghus 			    "Unsupported neptune type 1"));
53644977Sraghus 			goto error_exit;
53654732Sdavemq 		case 1:
53664732Sdavemq 			/* TODO - 2 10G, 1 1G */
53674732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53684732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
53694732Sdavemq 			goto error_exit;
53704732Sdavemq 		case 0:
53714732Sdavemq 			/* 2 10G */
53724782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
53734782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
53744782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
53754782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
53764977Sraghus 
53774977Sraghus 				/*
53784977Sraghus 				 * Check the first phy port address against
53794977Sraghus 				 * the known phy start addresses to determine
53804977Sraghus 				 * the platform type.
53814977Sraghus 				 */
53825572Ssbehera 
53835572Ssbehera 				switch (port_fd_arr[0]) {
53845572Ssbehera 				case BCM8704_NEPTUNE_PORT_ADDR_BASE:
53854977Sraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
53864977Sraghus 					hw_p->platform_type =
53874977Sraghus 					    P_NEPTUNE_ATLAS_2PORT;
53885572Ssbehera 					break;
53895572Ssbehera 				case BCM8706_GOA_PORT_ADDR_BASE:
53905572Ssbehera 					if (hw_p->platform_type !=
53915572Ssbehera 					    P_NEPTUNE_NIU) {
53925572Ssbehera 						hw_p->platform_type =
53935572Ssbehera 						    P_NEPTUNE_GENERIC;
53945572Ssbehera 						hw_p->niu_type =
53955572Ssbehera 						    NEPTUNE_2_10GF;
53965572Ssbehera 					}
53975572Ssbehera 					break;
53985572Ssbehera 				default:
53995572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
54004977Sraghus 					    "Unsupported neptune type 2 - 1"));
54014977Sraghus 					goto error_exit;
54024977Sraghus 				}
54035572Ssbehera 
54045572Ssbehera 				for (i = 0; i < 2; i++) {
54055572Ssbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
54065572Ssbehera 				}
54074732Sdavemq 			} else {
54084732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54094732Sdavemq 				    "Unsupported neptune type 2"));
54104732Sdavemq 				goto error_exit;
54114732Sdavemq 			}
54124732Sdavemq 			break;
54134732Sdavemq 		case 4:
54144732Sdavemq 			/* Maramba with 2 XAUI */
54154782Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
54164782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
54174782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
54184782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
54194782Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
54204782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
54214782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
54224782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
54234732Sdavemq 
54244732Sdavemq 				/*
54254732Sdavemq 				 * Check the first phy port address against
54264732Sdavemq 				 * the known phy start addresses to determine
54274732Sdavemq 				 * the platform type.
54284732Sdavemq 				 */
54295572Ssbehera 				switch (phy_fd_arr[0]) {
54305572Ssbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
54314732Sdavemq 					hw_p->platform_type =
54324732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
54335572Ssbehera 					break;
54345572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
54354732Sdavemq 					hw_p->platform_type =
54364732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
54375572Ssbehera 					break;
54385572Ssbehera 				default:
54394732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
54404732Sdavemq 					    "Unknown port %d...Cannot "
54414732Sdavemq 					    "determine platform type", i));
54424977Sraghus 					goto error_exit;
54434732Sdavemq 				}
54445572Ssbehera 
54454977Sraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
54464977Sraghus 
54475572Ssbehera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
54485572Ssbehera 				hw_p->xcvr_addr[1] = port_fd_arr[1];
54495572Ssbehera 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
54505572Ssbehera 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
54515572Ssbehera 
54524732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54534732Sdavemq 				    "Maramba with 2 XAUI"));
54544732Sdavemq 			} else {
54554732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54564732Sdavemq 				    "Unsupported neptune type 3"));
54574732Sdavemq 				goto error_exit;
54584732Sdavemq 			}
54594732Sdavemq 			break;
54604732Sdavemq 		default:
54614732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54624732Sdavemq 			    "Unsupported neptune type 5"));
54634732Sdavemq 			goto error_exit;
54644732Sdavemq 		}
54654782Ssbehera 		break;
54664732Sdavemq 	case 1:
54674732Sdavemq 		switch (total_phy_fd) {
54684732Sdavemq 		case 3:
54694977Sraghus 			/*
54704977Sraghus 			 * TODO 3 1G, 1 10G mode.
54714977Sraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
54724977Sraghus 			 * 1_10G_3_1G
54734977Sraghus 			 */
54744977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54754977Sraghus 			    "Unsupported neptune type 7"));
54764977Sraghus 			goto error_exit;
54774732Sdavemq 		case 2:
54784732Sdavemq 			/*
54794732Sdavemq 			 * TODO 2 1G, 1 10G mode.
54804732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
54814732Sdavemq 			 * 1_10G_2_1G
54824732Sdavemq 			 */
54834732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54844732Sdavemq 			    "Unsupported neptune type 8"));
54854732Sdavemq 			goto error_exit;
54864732Sdavemq 		case 1:
54874732Sdavemq 			/*
54884732Sdavemq 			 * TODO 1 1G, 1 10G mode.
54894732Sdavemq 			 * Differentiate between 1_1G_1_10G and
54904732Sdavemq 			 * 1_10G_1_1G
54914732Sdavemq 			 */
54924732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54934732Sdavemq 			    "Unsupported neptune type 9"));
54944732Sdavemq 			goto error_exit;
54954732Sdavemq 		case 0:
54965572Ssbehera 			/* 1 10G mode, N2 with 1 XAUI */
54975572Ssbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
54985572Ssbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
54995572Ssbehera 
55005572Ssbehera 				/*
55015572Ssbehera 				 * Check the first phy port address against
55025572Ssbehera 				 * the known phy start addresses to determine
55035572Ssbehera 				 * the platform type.
55045572Ssbehera 				 */
55055572Ssbehera 
55065572Ssbehera 				switch (port_fd_arr[0]) {
55075572Ssbehera 				case BCM8704_N2_PORT_ADDR_BASE:
55085572Ssbehera 				case (BCM8704_N2_PORT_ADDR_BASE + 1):
55095572Ssbehera 				case BCM8706_ALT_GOA_PORT1_ADDR:
55105572Ssbehera 					if (hw_p->platform_type !=
55115572Ssbehera 					    P_NEPTUNE_NIU) {
55125572Ssbehera 						hw_p->platform_type =
55135572Ssbehera 						    P_NEPTUNE_GENERIC;
55145572Ssbehera 						hw_p->niu_type =
55155572Ssbehera 						    NEPTUNE_2_10GF;
55165572Ssbehera 					}
55175572Ssbehera 					break;
55185572Ssbehera 				default:
55195572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55205572Ssbehera 					    "Unsupported neptune type 10"));
55215572Ssbehera 					goto error_exit;
55225572Ssbehera 				}
55235572Ssbehera 
5524*6028Ssbehera 				hw_p->xcvr_addr[nxgep->function_num] =
5525*6028Ssbehera 				    port_fd_arr[0];
55265572Ssbehera 			} else {
55275572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55285572Ssbehera 				    "Unsupported neptune type 10 - 1"));
55295572Ssbehera 				goto error_exit;
55305572Ssbehera 			}
55315572Ssbehera 			break;
55324732Sdavemq 		case 4:
55334732Sdavemq 			/* Maramba with 1 XAUI */
55344782Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
55354782Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
55364732Sdavemq 
55374732Sdavemq 				/*
55384732Sdavemq 				 * Check the first phy port address against
55394732Sdavemq 				 * the known phy start addresses to determine
55404732Sdavemq 				 * the platform type.
55414732Sdavemq 				 */
55425572Ssbehera 				switch (phy_fd_arr[0]) {
55435572Ssbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
55444732Sdavemq 					hw_p->platform_type =
55454732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
55465572Ssbehera 					break;
55475572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
55484732Sdavemq 					hw_p->platform_type =
55494732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
55505572Ssbehera 					break;
55515572Ssbehera 				default:
55524732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55534732Sdavemq 					    "Unknown port %d...Cannot "
55545572Ssbehera 					    "determine platform type 10 - 2",
55555572Ssbehera 					    i));
55564977Sraghus 					goto error_exit;
55574977Sraghus 				}
55584977Sraghus 
55595572Ssbehera 				/*
55605572Ssbehera 				 * Check the BCM8704 address to determine
55615572Ssbehera 				 * if XAUI is in port 0 or port 1.
55625572Ssbehera 				 */
55635572Ssbehera 				switch (port_fd_arr[0]) {
55645572Ssbehera 				case BCM8704_MARAMBA_PORT_ADDR_BASE:
55655572Ssbehera 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
55665572Ssbehera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
55675572Ssbehera 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
55685572Ssbehera 						hw_p->xcvr_addr[i] =
55695572Ssbehera 						    phy_fd_arr[i];
55704977Sraghus 					}
55715572Ssbehera 					break;
55725572Ssbehera 				case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1):
55734977Sraghus 					hw_p->niu_type =
55744977Sraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
55755572Ssbehera 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
55765572Ssbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
55775572Ssbehera 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
55785572Ssbehera 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
55795572Ssbehera 					break;
55805572Ssbehera 				default:
55814977Sraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55824977Sraghus 					    "Unsupported neptune type 11"));
55834977Sraghus 					goto error_exit;
55844732Sdavemq 				}
55854732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55864732Sdavemq 				    "Maramba with 1 XAUI"));
55874732Sdavemq 			} else {
55884732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55894732Sdavemq 				    "Unsupported neptune type 12"));
55904732Sdavemq 				goto error_exit;
55914732Sdavemq 			}
55924732Sdavemq 			break;
55934732Sdavemq 		default:
55944732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55954732Sdavemq 			    "Unsupported neptune type 13"));
55964732Sdavemq 			goto error_exit;
55974732Sdavemq 		}
55984732Sdavemq 		break;
55994732Sdavemq 	case 0:
56004732Sdavemq 		switch (total_phy_fd) {
56014732Sdavemq 		case 4:
56024782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
56034782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
56044782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
56054782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
56064732Sdavemq 
56074732Sdavemq 				/*
56084732Sdavemq 				 * Check the first phy port address against
56094732Sdavemq 				 * the known phy start addresses to determine
56104732Sdavemq 				 * the platform type.
56114732Sdavemq 				 */
56125572Ssbehera 				switch (phy_fd_arr[0]) {
56135572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
56144732Sdavemq 					hw_p->platform_type =
56154732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
56165572Ssbehera 					break;
56175572Ssbehera 				case BCM5464_NEPTUNE_PORT_ADDR_BASE:
56184977Sraghus 					hw_p->platform_type =
56194977Sraghus 					    P_NEPTUNE_ATLAS_4PORT;
56205572Ssbehera 					break;
56215572Ssbehera 				default:
56224977Sraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
56234977Sraghus 					    "Unknown port %d...Cannot "
56244977Sraghus 					    "determine platform type", i));
56254977Sraghus 					goto error_exit;
56264732Sdavemq 				}
56274977Sraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
56285572Ssbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
56295572Ssbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
56305572Ssbehera 				}
56314732Sdavemq 			} else {
56324732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56334732Sdavemq 				    "Unsupported neptune type 14"));
56344732Sdavemq 				goto error_exit;
56354732Sdavemq 			}
56364732Sdavemq 			break;
56374732Sdavemq 		case 3:
56384732Sdavemq 			/* TODO 3 1G mode */
56394732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56404732Sdavemq 			    "Unsupported neptune type 15"));
56414732Sdavemq 			goto error_exit;
56424732Sdavemq 		case 2:
56434732Sdavemq 			/* TODO 2 1G mode */
56444732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56454732Sdavemq 			    "Unsupported neptune type 16"));
56464732Sdavemq 			goto error_exit;
56474732Sdavemq 		case 1:
56484732Sdavemq 			/* TODO 1 1G mode */
56494732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56504732Sdavemq 			    "Unsupported neptune type 17"));
56514732Sdavemq 			goto error_exit;
56524732Sdavemq 		default:
56534732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56544732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
56554732Sdavemq 			    total_phy_fd));
56564732Sdavemq 			goto error_exit;
56574732Sdavemq 		}
56584732Sdavemq 		break;
56594732Sdavemq 	default:
56604732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56614732Sdavemq 		    "Unsupported neptune type 19"));
56624732Sdavemq 		goto error_exit;
56634732Sdavemq 	}
56644732Sdavemq 
56654732Sdavemq scan_exit:
56664732Sdavemq 
56674732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
56684732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
56694732Sdavemq 	return (status);
56704732Sdavemq 
56714732Sdavemq error_exit:
56724732Sdavemq 	return (NXGE_ERROR);
56734732Sdavemq }
56744732Sdavemq 
56754185Sspeer boolean_t
56764185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
56774185Sspeer {
56784185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
56794185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
56804185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
56814185Sspeer 		return (B_FALSE);
56824185Sspeer 	else
56834185Sspeer 		return (B_TRUE);
56844185Sspeer }
56854732Sdavemq 
56864732Sdavemq static void
56874732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
56884732Sdavemq 
56894732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
56904732Sdavemq 	uint8_t xcvr_portn;
56914732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
56924732Sdavemq 
56934732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
56944732Sdavemq 
56954732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
56964732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
56974732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
56984732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
56994732Sdavemq 	}
57004732Sdavemq 	/*
57014732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
57024732Sdavemq 	 * swapped with ethernet port number. This is
57034732Sdavemq 	 * designed for better signal integrity in routing.
57044732Sdavemq 	 */
57054732Sdavemq 	switch (portn) {
57064732Sdavemq 	case 0:
57074732Sdavemq 		xcvr_portn += 3;
57084732Sdavemq 		break;
57094732Sdavemq 	case 1:
57104732Sdavemq 		xcvr_portn += 2;
57114732Sdavemq 		break;
57124732Sdavemq 	case 2:
57134732Sdavemq 		xcvr_portn += 1;
57144732Sdavemq 		break;
57154732Sdavemq 	case 3:
57164732Sdavemq 	default:
57174732Sdavemq 		break;
57184732Sdavemq 	}
57194732Sdavemq 
57205780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock);
57214732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
57224732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
57234732Sdavemq 	if (rs != NPI_SUCCESS) {
57244732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
57254732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
57264732Sdavemq 		    "returned error 0x[%x]", rs));
57275780Ssbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
57284732Sdavemq 		return;
57294732Sdavemq 	}
57304732Sdavemq 
57314732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
57324732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
57334732Sdavemq 	if (rs != NPI_SUCCESS) {
57344732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
57354732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
57364732Sdavemq 		    "returned error 0x[%x]", rs));
57374732Sdavemq 	}
57384732Sdavemq 
57395780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock);
57404732Sdavemq }
57415196Ssbehera 
57425196Ssbehera static nxge_status_t
57435196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
57445196Ssbehera {
57455196Ssbehera 	p_nxge_stats_t	statsp;
57465196Ssbehera 	uint8_t		xcvr_portn;
57475196Ssbehera 	p_mii_regs_t	mii_regs;
57485196Ssbehera 	mii_mode_control_stat_t	mode;
57495196Ssbehera 	int		status = NXGE_OK;
57505196Ssbehera 
57515196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
57525196Ssbehera 
57535196Ssbehera 	statsp = nxgep->statsp;
57545196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
57555196Ssbehera 	mii_regs = NULL;
57565196Ssbehera 	mode.value = 0;
57575203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
57585196Ssbehera #if defined(__i386)
57595196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
57605196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
57615196Ssbehera 	    mode.value)) != NXGE_OK) {
57625196Ssbehera 		goto fail;
57635196Ssbehera #else
57645196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
57655196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
57665196Ssbehera 	    mode.value)) != NXGE_OK) {
57675196Ssbehera 		goto fail;
57685196Ssbehera #endif
57695196Ssbehera 	}
57705196Ssbehera #if defined(__i386)
57715196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
57725196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
57735196Ssbehera 	    &mode.value)) != NXGE_OK) {
57745196Ssbehera 		goto fail;
57755196Ssbehera 	}
57765196Ssbehera #else
57775196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
57785196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
57795196Ssbehera 	    &mode.value)) != NXGE_OK) {
57805196Ssbehera 		goto fail;
57815196Ssbehera 	}
57825196Ssbehera #endif
57835196Ssbehera 
57845196Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
57855196Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
57865196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
57875196Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
57885196Ssbehera 	}
57895196Ssbehera 
57905196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
57915196Ssbehera 	    "nxge_mii_get_link_mode: "
57925196Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
57935203Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
57945196Ssbehera 	    mode.value, nxgep->mac.portmode));
57955196Ssbehera 
57965196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
57975196Ssbehera 	    "<== nxge_mii_get_link_mode"));
57985196Ssbehera 	return (status);
57995196Ssbehera fail:
58005196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58015196Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
58025196Ssbehera 	return (NXGE_ERROR);
58035196Ssbehera }
58045196Ssbehera 
58055196Ssbehera #ifdef NXGE_DEBUG
58065196Ssbehera static void
58075196Ssbehera nxge_mii_dump(p_nxge_t nxgep)
58085196Ssbehera {
58095196Ssbehera 	p_nxge_stats_t	statsp;
58105196Ssbehera 	uint8_t		xcvr_portn;
58115196Ssbehera 	p_mii_regs_t	mii_regs;
58125196Ssbehera 	mii_bmcr_t	bmcr;
58135196Ssbehera 	mii_bmsr_t	bmsr;
58145196Ssbehera 	mii_idr1_t	idr1;
58155196Ssbehera 	mii_idr2_t	idr2;
58165196Ssbehera 	mii_mode_control_stat_t	mode;
58175196Ssbehera 
58185196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
58195196Ssbehera 
58205196Ssbehera 	statsp = nxgep->statsp;
58215196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
58225196Ssbehera 
58235196Ssbehera 	mii_regs = NULL;
58245196Ssbehera 
58255196Ssbehera #if defined(__i386)
58265196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
58275196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
58285196Ssbehera #else
58295196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
58305196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
58315196Ssbehera #endif
58325196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58335196Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
58345196Ssbehera 	    xcvr_portn, bmcr.value));
58355196Ssbehera 
58365196Ssbehera #if defined(__i386)
58375196Ssbehera 	(void) nxge_mii_read(nxgep,
58385196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58395196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
58405196Ssbehera #else
58415196Ssbehera 	(void) nxge_mii_read(nxgep,
58425196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58435196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
58445196Ssbehera #endif
58455196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58465196Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
58475196Ssbehera 	    xcvr_portn, bmsr.value));
58485196Ssbehera 
58495196Ssbehera #if defined(__i386)
58505196Ssbehera 	(void) nxge_mii_read(nxgep,
58515196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58525196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
58535196Ssbehera #else
58545196Ssbehera 	(void) nxge_mii_read(nxgep,
58555196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58565196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
58575196Ssbehera #endif
58585196Ssbehera 
58595196Ssbehera 
58605196Ssbehera #if defined(__i386)
58615196Ssbehera 	(void) nxge_mii_read(nxgep,
58625196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58635196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
58645196Ssbehera #else
58655196Ssbehera 	(void) nxge_mii_read(nxgep,
58665196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
58675196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
58685196Ssbehera #endif
58695196Ssbehera 
58705196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58715196Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
58725196Ssbehera 	    xcvr_portn, idr1.value));
58735196Ssbehera 
58745196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58755196Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
58765196Ssbehera 	    xcvr_portn, idr2.value));
58775196Ssbehera 
58785196Ssbehera 	mode.value = 0;
58795203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
58805196Ssbehera 
58815196Ssbehera #if defined(__i386)
58825196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
58835196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
58845196Ssbehera 
58855196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
58865196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
58875196Ssbehera #else
58885196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
58895196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
58905196Ssbehera 
58915196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
58925196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
58935196Ssbehera #endif
58945196Ssbehera 
58955196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58965196Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
58975196Ssbehera 	    xcvr_portn, mode.value));
58985196Ssbehera }
58995196Ssbehera #endif
5900