xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 6650:d2ae2b49e26b)
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>
306495Sspeer #include <sys/nxge/nxge_hio.h>
313859Sml29623 
324693Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
334693Stm144005 #define	LM_WAIT_MULTIPLIER	8
344693Stm144005 
356075Ssbehera #define	SERDES_RDY_WT_INTERVAL	50
366075Ssbehera #define	MAX_SERDES_RDY_RETRIES	10
376075Ssbehera 
383859Sml29623 extern uint32_t nxge_no_link_notify;
394732Sdavemq extern boolean_t nxge_no_msg;
403859Sml29623 extern uint32_t nxge_lb_dbg;
413859Sml29623 extern boolean_t nxge_jumbo_enable;
426028Ssbehera extern uint32_t nxge_jumbo_mtu;
433859Sml29623 
446495Sspeer 	/* The following functions may be found in nxge_main.c */
456495Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot,
466495Sspeer 	boolean_t factory);
476495Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
486495Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
496495Sspeer 
504693Stm144005 typedef enum {
514693Stm144005 	CHECK_LINK_RESCHEDULE,
524693Stm144005 	CHECK_LINK_STOP
534693Stm144005 } check_link_state_t;
544693Stm144005 
554693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
564693Stm144005 
573859Sml29623 /*
583859Sml29623  * Ethernet broadcast address definition.
593859Sml29623  */
603859Sml29623 static ether_addr_st etherbroadcastaddr =
613859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
624732Sdavemq /*
634732Sdavemq  * Ethernet zero address definition.
644732Sdavemq  */
654185Sspeer static ether_addr_st etherzeroaddr =
664185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
674732Sdavemq /*
684732Sdavemq  * Supported chip types
694732Sdavemq  */
706604Ssbehera static uint32_t nxge_supported_cl45_ids[] = {
716604Ssbehera 	BCM8704_DEV_ID,
726604Ssbehera 	MARVELL_88X_201X_DEV_ID,
736604Ssbehera 	BCM8706_DEV_ID
746604Ssbehera };
756604Ssbehera 
766604Ssbehera static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
774732Sdavemq 
784732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
794732Sdavemq 				sizeof (uint32_t))
804732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
814732Sdavemq 				sizeof (uint32_t))
824732Sdavemq /*
834732Sdavemq  * static functions
844732Sdavemq  */
854977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
864977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
874977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
884732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
895572Ssbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
904732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
914732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
924732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
934732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
944732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
954732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
964732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
974732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
984732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
994732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
1004732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
1014732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1025572Ssbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1035572Ssbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
1044732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
1054732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
1066604Ssbehera static nxge_status_t nxge_mrvl88x2011_link(p_nxge_t, boolean_t *);
1076604Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
1084732Sdavemq 
1094732Sdavemq /*
1104732Sdavemq  * xcvr tables for supported transceivers
1114732Sdavemq  */
1124732Sdavemq 
1134977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
1144732Sdavemq 	nxge_n2_serdes_init,
1154732Sdavemq 	nxge_10G_xcvr_init,
1164732Sdavemq 	nxge_10G_link_intr_stop,
1174732Sdavemq 	nxge_10G_link_intr_start,
1184732Sdavemq 	nxge_check_10g_link,
1195572Ssbehera 	PCS_XCVR
1204732Sdavemq };
1214732Sdavemq 
1224977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1234977Sraghus 	nxge_n2_serdes_init,
1244977Sraghus 	nxge_1G_xcvr_init,
1254977Sraghus 	nxge_1G_fiber_link_intr_stop,
1264977Sraghus 	nxge_1G_fiber_link_intr_start,
1274977Sraghus 	nxge_check_mii_link,
1285572Ssbehera 	PCS_XCVR
1294977Sraghus };
1304977Sraghus 
1314732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
1324732Sdavemq 	nxge_neptune_10G_serdes_init,
1334732Sdavemq 	nxge_10G_xcvr_init,
1344732Sdavemq 	nxge_10G_link_intr_stop,
1354732Sdavemq 	nxge_10G_link_intr_start,
1364732Sdavemq 	nxge_check_10g_link,
1375572Ssbehera 	PCS_XCVR
1384732Sdavemq };
1394732Sdavemq 
1404732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
1414732Sdavemq 	NULL,
1424732Sdavemq 	nxge_1G_xcvr_init,
1434732Sdavemq 	nxge_1G_copper_link_intr_stop,
1444732Sdavemq 	nxge_1G_copper_link_intr_start,
1454732Sdavemq 	nxge_check_mii_link,
1465572Ssbehera 	INT_MII_XCVR
1474732Sdavemq };
1484732Sdavemq 
1494732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
1504732Sdavemq 	nxge_1G_serdes_init,
1514732Sdavemq 	nxge_1G_xcvr_init,
1524732Sdavemq 	nxge_1G_fiber_link_intr_stop,
1534732Sdavemq 	nxge_1G_fiber_link_intr_start,
1544732Sdavemq 	nxge_check_mii_link,
1555572Ssbehera 	PCS_XCVR
1564732Sdavemq };
1574732Sdavemq 
1584732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
1594732Sdavemq 	nxge_neptune_10G_serdes_init,
1604732Sdavemq 	NULL,
1614732Sdavemq 	NULL,
1624732Sdavemq 	NULL,
1634977Sraghus 	NULL,
1645572Ssbehera 	PCS_XCVR
1654732Sdavemq };
1663859Sml29623 
1673859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
1683859Sml29623 
1695196Ssbehera #ifdef NXGE_DEBUG
1705196Ssbehera static void nxge_mii_dump(p_nxge_t);
1715196Ssbehera #endif
1725196Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
1735196Ssbehera 
1744977Sraghus nxge_status_t
1754977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep)
1764977Sraghus {
1774977Sraghus 	nxge_status_t status = NXGE_OK;
1784977Sraghus 	char *phy_type;
1794977Sraghus 	char *prop_val;
1804977Sraghus 
1814977Sraghus 	nxgep->mac.portmode = 0;
1825572Ssbehera 	nxgep->xcvr_addr = 0;
1835572Ssbehera 
1845572Ssbehera 	/*
1855572Ssbehera 	 * First check for hot swappable phy property.
1865572Ssbehera 	 */
1875572Ssbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
1885572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1895572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1905572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
1915572Ssbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
1925572Ssbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1935572Ssbehera 	    "hot-swappable-phy") == 1) {
1945572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
1955572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
1965572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
1975572Ssbehera 	} else if (nxgep->niu_type == N2_NIU &&
1985572Ssbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
1995572Ssbehera 	    "hot-swappable-phy") == 1) {
2005572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2015572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2025572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
2035572Ssbehera 	}
2045572Ssbehera 
2055572Ssbehera 	/*
2065572Ssbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
2075572Ssbehera 	 */
2085572Ssbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
2095572Ssbehera 
2105572Ssbehera 		uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2115572Ssbehera 
2125572Ssbehera 		nxgep->hot_swappable_phy = B_TRUE;
2135572Ssbehera 		/*
2145572Ssbehera 		 * If this is the 2nd NIU port, then check 2 addresses
2155572Ssbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
2165572Ssbehera 		 * (in the eval board) or 20 (in the P0 board).
2175572Ssbehera 		 */
2185572Ssbehera 		if (portn == 1) {
2195572Ssbehera 			if (nxge_is_phy_present(nxgep,
2205572Ssbehera 			    BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID,
2215572Ssbehera 			    BCM_PHY_ID_MASK)) {
2225572Ssbehera 				nxgep->xcvr_addr =
2235572Ssbehera 				    BCM8706_ALT_GOA_PORT1_ADDR;
2245572Ssbehera 				goto found_phy;
2255572Ssbehera 			}
2265572Ssbehera 		}
2275572Ssbehera 		if (nxge_is_phy_present(nxgep,
2286495Sspeer 		    BCM8706_GOA_PORT_ADDR_BASE + portn,
2295572Ssbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
2306495Sspeer 			nxgep->xcvr_addr = BCM8706_GOA_PORT_ADDR_BASE +
2315572Ssbehera 			    portn;
2325572Ssbehera 			goto found_phy;
2335572Ssbehera 		}
2345572Ssbehera 
2355572Ssbehera 		nxgep->phy_absent = B_TRUE;
2365572Ssbehera 		goto check_phy_done;
2375572Ssbehera found_phy:
2385572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2395572Ssbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
2405572Ssbehera 		nxgep->phy_absent = B_FALSE;
2415572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
2425572Ssbehera 		    "found for hot swappable phy"));
2435572Ssbehera check_phy_done:
2445572Ssbehera 		return (status);
2455572Ssbehera 	}
2465572Ssbehera 
2475572Ssbehera 	/* Get phy-type property from the driver conf. file */
2484977Sraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
2494977Sraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2504977Sraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
2514977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2524977Sraghus 		    "found  conf file: phy-type %s", prop_val));
2534977Sraghus 		if (strcmp("xgsd", prop_val) == 0) {
2544977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2554977Sraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
2564977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2574977Sraghus 			    "found: 10G Serdes"));
2584977Sraghus 		} else if (strcmp("gsd", prop_val) == 0) {
2594977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2604977Sraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
2614977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
2624977Sraghus 		} else if (strcmp("mif", prop_val) == 0) {
2634977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
2644977Sraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
2654977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
2664977Sraghus 		} else if (strcmp("pcs", prop_val) == 0) {
2674977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2684977Sraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
2694977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
2706075Ssbehera 		} else if (strcmp("xgf", prop_val) == 0) {
2716075Ssbehera 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2726075Ssbehera 			nxgep->mac.portmode = PORT_10G_FIBER;
2736075Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr"));
2744977Sraghus 		}
2754977Sraghus 
2764977Sraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
2774977Sraghus 		    "phy-type", prop_val);
2784977Sraghus 		ddi_prop_free(prop_val);
2794977Sraghus 
2804977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
2814977Sraghus 		    "Got phy type [0x%x] from conf file",
2824977Sraghus 		    nxgep->mac.portmode));
2834977Sraghus 
2844977Sraghus 		return (NXGE_OK);
2854977Sraghus 	}
2865572Ssbehera 
2875572Ssbehera 	/* Get phy-type property from OBP */
2884977Sraghus 	if (nxgep->niu_type == N2_NIU) {
2894977Sraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
2904977Sraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
2914977Sraghus 			if (strcmp("xgf", prop_val) == 0) {
2924977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2934977Sraghus 				    XPCS_XCVR;
2944977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
2954977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2964977Sraghus 				    "10G Fiber Xcvr"));
2974977Sraghus 			} else if (strcmp("mif", prop_val) == 0) {
2984977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2994977Sraghus 				    INT_MII_XCVR;
3004977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
3014977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3024977Sraghus 				    "1G Copper Xcvr"));
3034977Sraghus 			} else if (strcmp("pcs", prop_val) == 0) {
3044977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3054977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
3064977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3074977Sraghus 				    "1G Fiber Xcvr"));
3084977Sraghus 			} else if (strcmp("xgc", prop_val) == 0) {
3094977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
3104977Sraghus 				    XPCS_XCVR;
3114977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
3124977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3134977Sraghus 				    "10G Copper Xcvr"));
3144977Sraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
3154977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3164977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
3174977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3184977Sraghus 				    "OBP: 10G Serdes"));
3194977Sraghus 			} else if (strcmp("gsd", prop_val) == 0) {
3204977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3214977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
3224977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3234977Sraghus 				    "OBP: 1G Serdes"));
3244977Sraghus 			} else {
3254977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3264977Sraghus 				    "Unknown phy-type: %s", prop_val));
3274977Sraghus 				ddi_prop_free(prop_val);
3284977Sraghus 				return (NXGE_ERROR);
3294977Sraghus 			}
3304977Sraghus 			status = NXGE_OK;
3314977Sraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3324977Sraghus 			    nxgep->dip, "phy-type", prop_val);
3334977Sraghus 			ddi_prop_free(prop_val);
3344977Sraghus 
3354977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3364977Sraghus 			    "Got phy type [0x%x] from OBP",
3374977Sraghus 			    nxgep->mac.portmode));
3384977Sraghus 
3394977Sraghus 			return (status);
3404977Sraghus 		} else {
3414977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3424977Sraghus 			    "Exiting...phy-type property not found"));
3434977Sraghus 			return (NXGE_ERROR);
3444977Sraghus 		}
3454977Sraghus 	}
3464977Sraghus 
3474977Sraghus 
3484977Sraghus 	if (!nxgep->vpd_info.present) {
3494977Sraghus 		return (NXGE_OK);
3504977Sraghus 	}
3514977Sraghus 
3524977Sraghus 	if (!nxgep->vpd_info.ver_valid) {
3534977Sraghus 		goto read_seeprom;
3544977Sraghus 	}
3554977Sraghus 
3564977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3574977Sraghus 	    "Reading phy type from expansion ROM"));
3584977Sraghus 	/*
3594977Sraghus 	 * Try to read the phy type from the vpd data read off the
3604977Sraghus 	 * expansion ROM.
3614977Sraghus 	 */
3624977Sraghus 	phy_type = nxgep->vpd_info.phy_type;
3634977Sraghus 
3645196Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
3654977Sraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
3664977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3675196Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
3684977Sraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
3694977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3705196Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
3714977Sraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
3724977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3735196Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
3744977Sraghus 		nxgep->mac.portmode = PORT_10G_COPPER;
3754977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3765196Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
3775196Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
3785196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3795196Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
3805196Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
3815196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3824977Sraghus 	} else {
3835196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3844977Sraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
3854977Sraghus 		    phy_type[0], phy_type[1], phy_type[2]));
3864977Sraghus 		goto read_seeprom;
3874977Sraghus 	}
3884977Sraghus 
3894977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3904977Sraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
3914977Sraghus 
3924977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
3934977Sraghus 	return (status);
3944977Sraghus 
3954977Sraghus read_seeprom:
3964977Sraghus 	/*
3974977Sraghus 	 * read the phy type from the SEEPROM - NCR registers
3984977Sraghus 	 */
3994977Sraghus 	status = nxge_espc_phy_type_get(nxgep);
4004977Sraghus 	if (status != NXGE_OK) {
4014977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4024977Sraghus 		    "Failed to get phy type"));
4034977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
4044977Sraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
4054977Sraghus 	}
4064977Sraghus 
4074977Sraghus 	return (status);
4084977Sraghus 
4094977Sraghus }
4104977Sraghus 
4114732Sdavemq /* Set up the PHY specific values. */
4124732Sdavemq 
4134732Sdavemq nxge_status_t
4144732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
4154732Sdavemq {
4164732Sdavemq 	nxge_status_t	status = NXGE_OK;
4174732Sdavemq 	uint32_t	port_type;
4184732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4194977Sraghus 	uint32_t	pcs_id = 0;
4204977Sraghus 	uint32_t	pma_pmd_id = 0;
4214977Sraghus 	uint32_t	phy_id = 0;
4225572Ssbehera 	uint16_t	chip_id = 0;
4234732Sdavemq 
4244732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
4254732Sdavemq 	    portn));
4264732Sdavemq 
4274977Sraghus 	switch (nxgep->niu_type) {
4284977Sraghus 	case N2_NIU:
4294977Sraghus 		switch (nxgep->mac.portmode) {
4304977Sraghus 		case PORT_1G_FIBER:
4314977Sraghus 		case PORT_1G_SERDES:
4324977Sraghus 			nxgep->xcvr = nxge_n2_1G_table;
4335572Ssbehera 			nxgep->xcvr_addr = portn;
4344977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
4354977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
4364977Sraghus 			    "Serdes"));
4374977Sraghus 			break;
4384977Sraghus 		case PORT_10G_FIBER:
4394977Sraghus 		case PORT_10G_SERDES:
4404977Sraghus 			nxgep->xcvr = nxge_n2_10G_table;
4415572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
4425572Ssbehera 				nxgep->xcvr_addr =
4435572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
4445572Ssbehera 			}
4454977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
4464977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
4474977Sraghus 			    "Serdes"));
4484977Sraghus 			break;
4495572Ssbehera 		case PORT_HSP_MODE:
4505572Ssbehera 			nxgep->xcvr = nxge_n2_10G_table;
4515572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
4525572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
4535572Ssbehera 			    "Swappable Xcvr (not present)"));
4545572Ssbehera 			break;
4554977Sraghus 		default:
4564977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4574977Sraghus 			    "<== nxge_setup_xcvr_table: "
4584977Sraghus 			    "Unable to determine NIU portmode"));
4594977Sraghus 			return (NXGE_ERROR);
4604977Sraghus 		}
4614977Sraghus 		break;
4624977Sraghus 	default:
4634977Sraghus 		if (nxgep->mac.portmode == 0) {
4644977Sraghus 			/*
4654977Sraghus 			 * Would be the case for platforms like Maramba
4664977Sraghus 			 * in which the phy type could not be got from conf
4674977Sraghus 			 * file, OBP, VPD or Serial PROM.
4684977Sraghus 			 */
4694977Sraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4704977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4714977Sraghus 				    "<== nxge_setup_xcvr_table:"
4724977Sraghus 				    " Invalid Neptune type [0x%x]",
4734977Sraghus 				    nxgep->niu_type));
4744977Sraghus 				return (NXGE_ERROR);
4754977Sraghus 			}
4764977Sraghus 
4774977Sraghus 			port_type = nxgep->niu_type >>
4784977Sraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
4794977Sraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
4804977Sraghus 
4814977Sraghus 			switch (port_type) {
4824977Sraghus 
4834977Sraghus 			case NXGE_PORT_1G_COPPER:
4844977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4854977Sraghus 				break;
4864977Sraghus 			case NXGE_PORT_10G_COPPER:
4874977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
4884977Sraghus 				break;
4894977Sraghus 			case NXGE_PORT_1G_FIBRE:
4904977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4914977Sraghus 				break;
4924977Sraghus 			case NXGE_PORT_10G_FIBRE:
4934977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
4944977Sraghus 				break;
4954977Sraghus 			case NXGE_PORT_1G_SERDES:
4964977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4974977Sraghus 				break;
4984977Sraghus 			case NXGE_PORT_10G_SERDES:
4994977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
5004977Sraghus 				break;
5014977Sraghus 			case NXGE_PORT_1G_RGMII_FIBER:
5024977Sraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
5034977Sraghus 				break;
5044977Sraghus 			default:
5054977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5064977Sraghus 				    "<== nxge_setup_xcvr_table: "
5074977Sraghus 				    "Unknown port-type: 0x%x", port_type));
5084977Sraghus 				return (NXGE_ERROR);
5094977Sraghus 			}
5104977Sraghus 		}
5114977Sraghus 
5124977Sraghus 		switch (nxgep->mac.portmode) {
5134977Sraghus 		case PORT_1G_COPPER:
5144977Sraghus 		case PORT_1G_RGMII_FIBER:
5154732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
5165572Ssbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
5174732Sdavemq 			/*
5184732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
5194732Sdavemq 			 * swapped with ethernet port number. This is
5204977Sraghus 			 * designed for better signal integrity in
5214977Sraghus 			 * routing. This is also the case for the
5224977Sraghus 			 * on-board Neptune copper ports on the Maramba
5234977Sraghus 			 * platform.
5244732Sdavemq 			 */
5254977Sraghus 			switch (nxgep->platform_type) {
5264977Sraghus 			case P_NEPTUNE_ATLAS_4PORT:
5274977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
5284977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
5294977Sraghus 				switch (portn) {
5304977Sraghus 				case 0:
5315572Ssbehera 					nxgep->xcvr_addr += 3;
5324977Sraghus 					break;
5334977Sraghus 				case 1:
5345572Ssbehera 					nxgep->xcvr_addr += 1;
5354977Sraghus 					break;
5364977Sraghus 				case 2:
5375572Ssbehera 					nxgep->xcvr_addr -= 1;
5384977Sraghus 					break;
5394977Sraghus 				case 3:
5405572Ssbehera 					nxgep->xcvr_addr -= 3;
5414977Sraghus 					break;
5424977Sraghus 				default:
5434977Sraghus 					return (NXGE_ERROR);
5444977Sraghus 				}
5454732Sdavemq 				break;
5464732Sdavemq 			default:
5474977Sraghus 				break;
5484732Sdavemq 			}
5495196Ssbehera 
5504977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5514977Sraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
5524977Sraghus 			    "Copper" : "RGMII Fiber"));
5534732Sdavemq 			break;
5544977Sraghus 		case PORT_10G_COPPER:
5554732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
5564732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
5574732Sdavemq 			break;
5584977Sraghus 		case PORT_1G_FIBER:
5594977Sraghus 		case PORT_1G_SERDES:
5604732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
5615572Ssbehera 			nxgep->xcvr_addr = portn;
5624977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
5634977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
5644977Sraghus 			    "Fiber" : "Serdes"));
5654732Sdavemq 			break;
5664977Sraghus 		case PORT_10G_FIBER:
5674977Sraghus 		case PORT_10G_SERDES:
5684732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
5695572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
5705572Ssbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
5715572Ssbehera 			    "nxgep->xcvr_addr = [%d]",
5725572Ssbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
5735572Ssbehera 			    nxgep->xcvr_addr));
5745572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5755572Ssbehera 				nxgep->xcvr_addr =
5765572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5775572Ssbehera 			}
5784977Sraghus 			switch (nxgep->platform_type) {
5794977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
5804977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
5814732Sdavemq 				/*
5824732Sdavemq 				 * Switch off LED for corresponding copper
5834732Sdavemq 				 * port
5844732Sdavemq 				 */
5854732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
5864977Sraghus 				break;
5874977Sraghus 			default:
5884977Sraghus 				break;
5894732Sdavemq 			}
5904977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
5914977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
5924977Sraghus 			    "Fiber" : "Serdes"));
5934732Sdavemq 			break;
5945572Ssbehera 
5955572Ssbehera 		case PORT_HSP_MODE:
5965572Ssbehera 			nxgep->xcvr = nxge_10G_fiber_table;
5975572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
5985572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
5995572Ssbehera 			    "Swappable Xcvr (not present)"));
6005572Ssbehera 			break;
6014732Sdavemq 		default:
6024732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6034732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
6044732Sdavemq 			return (NXGE_ERROR);
6054732Sdavemq 		}
6064732Sdavemq 	}
6074732Sdavemq 
6085572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
6096604Ssbehera 		uint32_t pma_pmd_id;
6106604Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
6116604Ssbehera 		    nxgep->xcvr_addr);
6126604Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
6136604Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
6146604Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6156604Ssbehera 			    "nxge_setup_xcvr_table: "
6166604Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
6176604Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6185572Ssbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
6195572Ssbehera 		    &chip_id)) == NXGE_OK) {
6205572Ssbehera 
6215572Ssbehera 			switch (chip_id) {
6225572Ssbehera 			case BCM8704_CHIP_ID:
6235572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6245572Ssbehera 				    "nxge_setup_xcvr_table: "
6255572Ssbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
6265572Ssbehera 				    chip_id));
6275572Ssbehera 				break;
6285572Ssbehera 			case BCM8706_CHIP_ID:
6295572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6305572Ssbehera 				    "nxge_setup_xcvr_table: "
6315572Ssbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
6325572Ssbehera 				    chip_id));
6335572Ssbehera 				break;
6345572Ssbehera 			default:
6355572Ssbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6365572Ssbehera 				    "nxge_setup_xcvr_table: "
6375572Ssbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
6385572Ssbehera 				    chip_id));
6395572Ssbehera 				break;
6405572Ssbehera 			}
6415572Ssbehera 		}
6425572Ssbehera 	}
6435572Ssbehera 
6444732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
6455572Ssbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
6465572Ssbehera 	nxgep->chip_id = chip_id;
6474977Sraghus 
6484977Sraghus 	/*
6494977Sraghus 	 * Get the actual device ID value returned by MDIO read.
6504977Sraghus 	 */
6514977Sraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
6524977Sraghus 
6535572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
6544977Sraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
6554977Sraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
6564977Sraghus 	} else {
6575572Ssbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
6584977Sraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
6594977Sraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
6604977Sraghus 		} else {
6614977Sraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
6625572Ssbehera 			    nxgep->xcvr_addr);
6634977Sraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
6644977Sraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
6654977Sraghus 			}
6664977Sraghus 		}
6674977Sraghus 	}
6684977Sraghus 
6694732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
6704732Sdavemq 
6714977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
6725572Ssbehera 	    "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type,
6735572Ssbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
6744977Sraghus 
6754732Sdavemq 	return (status);
6764732Sdavemq }
6774732Sdavemq 
6783859Sml29623 /* Initialize the entire MAC and physical layer */
6793859Sml29623 
6803859Sml29623 nxge_status_t
6813859Sml29623 nxge_mac_init(p_nxge_t nxgep)
6823859Sml29623 {
6833859Sml29623 	uint8_t			portn;
6843859Sml29623 	nxge_status_t		status = NXGE_OK;
6853859Sml29623 
6863859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6873859Sml29623 
6883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
6893859Sml29623 
6903859Sml29623 	nxgep->mac.portnum = portn;
6913859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
6923859Sml29623 
6933859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
6943859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
6953859Sml29623 
6963859Sml29623 	/* Initialize XIF to configure a network mode */
6973859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
6983859Sml29623 		goto fail;
6993859Sml29623 	}
7003859Sml29623 
7013859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
7023859Sml29623 		goto fail;
7033859Sml29623 	}
7043859Sml29623 
7053859Sml29623 	/* Initialize TX and RX MACs */
7063859Sml29623 	/*
7073859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
7083859Sml29623 	 */
7093859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
7103859Sml29623 		goto fail;
7113859Sml29623 
7123859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
7133859Sml29623 		goto fail;
7143859Sml29623 
7153859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
7163859Sml29623 		goto fail;
7173859Sml29623 
7183859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
7193859Sml29623 		goto fail;
7203859Sml29623 
7213859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
7223859Sml29623 		goto fail;
7233859Sml29623 
7243859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
7253859Sml29623 		goto fail;
7263859Sml29623 
7275553Smisaki 	/* Initialize MAC control configuration */
7285553Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
7295553Smisaki 		goto fail;
7305553Smisaki 	}
7315553Smisaki 
7323859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
7333859Sml29623 
7345196Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
7355196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
7365196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
7375196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
7385196Ssbehera 	    ((portn == 0) || (portn == 1))) {
7395196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7405196Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
7415196Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
7425196Ssbehera 			goto fail;
7435196Ssbehera 		}
7445196Ssbehera 	}
7455196Ssbehera 
7464977Sraghus 
7473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
7483859Sml29623 
7493859Sml29623 	return (NXGE_OK);
7503859Sml29623 fail:
7513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7523859Sml29623 			"nxge_mac_init: failed to initialize MAC port<%d>",
7533859Sml29623 			portn));
7543859Sml29623 	return (status);
7553859Sml29623 }
7563859Sml29623 
7573859Sml29623 /* Initialize the Ethernet Link */
7583859Sml29623 
7593859Sml29623 nxge_status_t
7603859Sml29623 nxge_link_init(p_nxge_t nxgep)
7613859Sml29623 {
7623859Sml29623 	nxge_status_t		status = NXGE_OK;
7634977Sraghus 	nxge_port_mode_t	portmode;
7643859Sml29623 #ifdef	NXGE_DEBUG
7653859Sml29623 	uint8_t			portn;
7663859Sml29623 
7673859Sml29623 	portn = nxgep->mac.portnum;
7683859Sml29623 
7693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
7703859Sml29623 #endif
7715572Ssbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
7725572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
7735572Ssbehera 		    "Phy not present, cannot initialize link"));
7745572Ssbehera 		return (status);
7755572Ssbehera 	}
7763859Sml29623 
7774977Sraghus 	portmode = nxgep->mac.portmode;
7785572Ssbehera 
7794977Sraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
7804977Sraghus 	    (portmode != PORT_1G_SERDES)) {
7813859Sml29623 		/* Workaround to get link up in both NIU ports */
7824977Sraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
7833859Sml29623 			goto fail;
7844977Sraghus 		}
7853859Sml29623 	}
7863859Sml29623 	NXGE_DELAY(200000);
7873859Sml29623 	/* Initialize internal serdes */
7883859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
7893859Sml29623 		goto fail;
7903859Sml29623 	NXGE_DELAY(200000);
7913859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
7923859Sml29623 		goto fail;
7933859Sml29623 
7943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
7953859Sml29623 
7963859Sml29623 	return (NXGE_OK);
7973859Sml29623 
7983859Sml29623 fail:
7993859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8003859Sml29623 		"nxge_link_init: ",
8013859Sml29623 		"failed to initialize Ethernet link on port<%d>",
8023859Sml29623 		portn));
8033859Sml29623 
8043859Sml29623 	return (status);
8053859Sml29623 }
8063859Sml29623 
8073859Sml29623 
8083859Sml29623 /* Initialize the XIF sub-block within the MAC */
8093859Sml29623 
8103859Sml29623 nxge_status_t
8113859Sml29623 nxge_xif_init(p_nxge_t nxgep)
8123859Sml29623 {
8133859Sml29623 	uint32_t		xif_cfg = 0;
8143859Sml29623 	npi_attr_t		ap;
8153859Sml29623 	uint8_t			portn;
8163859Sml29623 	nxge_port_t		portt;
8173859Sml29623 	nxge_port_mode_t	portmode;
8183859Sml29623 	p_nxge_stats_t		statsp;
8193859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
8203859Sml29623 	npi_handle_t		handle;
8213859Sml29623 
8223859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8233859Sml29623 
8243859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
8253859Sml29623 
8263859Sml29623 	handle = nxgep->npi_handle;
8273859Sml29623 	portmode = nxgep->mac.portmode;
8283859Sml29623 	portt = nxgep->mac.porttype;
8293859Sml29623 	statsp = nxgep->statsp;
8303859Sml29623 
8315196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
8325196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
8335196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
8345196Ssbehera 	    ((portn == 0) || (portn == 1))) {
8355196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8365196Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
8375196Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
8385196Ssbehera 	}
8395196Ssbehera 
8403859Sml29623 	if (portt == PORT_TYPE_XMAC) {
8413859Sml29623 
8423859Sml29623 		/* Setup XIF Configuration for XMAC */
8433859Sml29623 
8443859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
8454977Sraghus 		    (portmode == PORT_10G_COPPER) ||
8464977Sraghus 		    (portmode == PORT_10G_SERDES))
8473859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
8483859Sml29623 
8493859Sml29623 		if (portmode == PORT_1G_COPPER) {
8503859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
8513859Sml29623 		}
8523859Sml29623 
8533859Sml29623 		/* Set MAC Internal Loopback if necessary */
8543859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
8553859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
8563859Sml29623 
8573859Sml29623 		if (statsp->mac_stats.link_speed == 100)
8583859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
8593859Sml29623 
8603859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
8613859Sml29623 
8624977Sraghus 		if ((portmode == PORT_10G_FIBER) ||
8634977Sraghus 		    (portmode == PORT_10G_SERDES)) {
8643859Sml29623 			if (statsp->mac_stats.link_up) {
8653859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
8663859Sml29623 			} else {
8673859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
8683859Sml29623 			}
8693859Sml29623 		}
8703859Sml29623 
8713859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
8723859Sml29623 		if (rs != NPI_SUCCESS)
8733859Sml29623 			goto fail;
8743859Sml29623 
8753859Sml29623 		nxgep->mac.xif_config = xif_cfg;
8763859Sml29623 
8773859Sml29623 		/* Set Port Mode */
8783859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
8794977Sraghus 		    (portmode == PORT_10G_COPPER) ||
8804977Sraghus 		    (portmode == PORT_10G_SERDES)) {
8813859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
8823859Sml29623 						MAC_XGMII_MODE, rs);
8833859Sml29623 			if (rs != NPI_SUCCESS)
8843859Sml29623 				goto fail;
8853859Sml29623 			if (statsp->mac_stats.link_up) {
8863859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
8873859Sml29623 					goto fail;
8883859Sml29623 			} else {
8893859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
8903859Sml29623 					goto fail;
8913859Sml29623 			}
8923859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
8934977Sraghus 		    (portmode == PORT_1G_COPPER) ||
8945196Ssbehera 		    (portmode == PORT_1G_SERDES) ||
8955196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
8965196Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8975196Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
8985196Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
8993859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
9003859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
9013859Sml29623 							MAC_GMII_MODE, rs);
9023859Sml29623 			} else {
9033859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
9043859Sml29623 							MAC_MII_MODE, rs);
9053859Sml29623 			}
9063859Sml29623 			if (rs != NPI_SUCCESS)
9073859Sml29623 				goto fail;
9083859Sml29623 		} else {
9093859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9103859Sml29623 					"nxge_xif_init: Unknown port mode (%d)"
9113859Sml29623 					" for port<%d>", portmode, portn));
9123859Sml29623 			goto fail;
9133859Sml29623 		}
9143859Sml29623 
9155196Ssbehera 		/* Enable ATCA mode */
9165196Ssbehera 
9173859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
9183859Sml29623 
9193859Sml29623 		/* Setup XIF Configuration for BMAC */
9203859Sml29623 
9215196Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
9225196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
9233859Sml29623 			if (statsp->mac_stats.link_speed == 100)
9243859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
9253859Sml29623 		}
9263859Sml29623 
9273859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
9283859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
9293859Sml29623 
9303859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
9313859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
9323859Sml29623 
9333859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
9343859Sml29623 
9353859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
9363859Sml29623 		if (rs != NPI_SUCCESS)
9373859Sml29623 			goto fail;
9383859Sml29623 		nxgep->mac.xif_config = xif_cfg;
9393859Sml29623 	}
9403859Sml29623 
9413859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
9423859Sml29623 	return (NXGE_OK);
9433859Sml29623 fail:
9443859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9453859Sml29623 			"nxge_xif_init: Failed to initialize XIF port<%d>",
9463859Sml29623 			portn));
9473859Sml29623 	return (NXGE_ERROR | rs);
9483859Sml29623 }
9493859Sml29623 
9503859Sml29623 /* Initialize the PCS sub-block in the MAC */
9513859Sml29623 
9523859Sml29623 nxge_status_t
9533859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
9543859Sml29623 {
9553859Sml29623 	pcs_cfg_t		pcs_cfg;
9563859Sml29623 	uint32_t		val;
9573859Sml29623 	uint8_t			portn;
9583859Sml29623 	nxge_port_mode_t	portmode;
9593859Sml29623 	npi_handle_t		handle;
9603859Sml29623 	p_nxge_stats_t		statsp;
9613859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
9623859Sml29623 
9633859Sml29623 	handle = nxgep->npi_handle;
9643859Sml29623 	portmode = nxgep->mac.portmode;
9653859Sml29623 	portn = nxgep->mac.portnum;
9663859Sml29623 	statsp = nxgep->statsp;
9673859Sml29623 
9683859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
9693859Sml29623 
9704977Sraghus 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
9714977Sraghus 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
9724977Sraghus 			goto fail;
9734977Sraghus 		}
9744977Sraghus 
9753859Sml29623 		/* Initialize port's PCS */
9763859Sml29623 		pcs_cfg.value = 0;
9773859Sml29623 		pcs_cfg.bits.w0.enable = 1;
9783859Sml29623 		pcs_cfg.bits.w0.mask = 1;
9793859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
9803859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
9814977Sraghus 
9824977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9834977Sraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
9844977Sraghus 		    portn, pcs_cfg.value));
9853859Sml29623 	} else if ((portmode == PORT_10G_FIBER) ||
9864977Sraghus 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
9873859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
9883859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
9893859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
9903859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
9913859Sml29623 
9923859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
9933859Sml29623 			goto fail;
9943859Sml29623 
9953859Sml29623 		/* Set XPCS Internal Loopback if necessary */
9963859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
9973859Sml29623 						XPCS_REG_CONTROL1, &val))
9983859Sml29623 						!= NPI_SUCCESS)
9993859Sml29623 			goto fail;
10003859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
10013859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
10023859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
10033859Sml29623 		else
10043859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
10053859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
10063859Sml29623 						XPCS_REG_CONTROL1, val))
10073859Sml29623 						!= NPI_SUCCESS)
10083859Sml29623 			goto fail;
10093859Sml29623 
10103859Sml29623 		/* Clear descw errors */
10113859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
10123859Sml29623 						XPCS_REG_DESCWERR_COUNTER, 0))
10133859Sml29623 						!= NPI_SUCCESS)
10143859Sml29623 			goto fail;
10153859Sml29623 		/* Clear symbol errors */
10163859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
10173859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
10183859Sml29623 					!= NPI_SUCCESS)
10193859Sml29623 			goto fail;
10203859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
10213859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
10223859Sml29623 					!= NPI_SUCCESS)
10233859Sml29623 			goto fail;
10243859Sml29623 
10255196Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
10265196Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
10275196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10285196Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
10293859Sml29623 		if (portn < 4) {
10303859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
10313859Sml29623 					PCS_DATAPATH_MODE_MII);
10323859Sml29623 		}
10333859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
10343859Sml29623 			goto fail;
10353859Sml29623 
10363859Sml29623 	} else {
10373859Sml29623 		goto fail;
10383859Sml29623 	}
10393859Sml29623 pass:
10403859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
10413859Sml29623 	return (NXGE_OK);
10423859Sml29623 fail:
10433859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10443859Sml29623 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
10453859Sml29623 			portn));
10463859Sml29623 	return (NXGE_ERROR | rs);
10473859Sml29623 }
10483859Sml29623 
10495553Smisaki /*
10505553Smisaki  * Initialize the MAC CTRL sub-block within the MAC
10515553Smisaki  * Only the receive-pause-cap is supported.
10525553Smisaki  */
10535553Smisaki nxge_status_t
10545553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
10555553Smisaki {
10565553Smisaki 	uint8_t			portn;
10575553Smisaki 	nxge_port_t		portt;
10585553Smisaki 	p_nxge_stats_t		statsp;
10595553Smisaki 	npi_handle_t		handle;
10605553Smisaki 	uint32_t		val;
10615553Smisaki 
10625553Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
10635553Smisaki 
10645553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
10655553Smisaki 	    portn));
10665553Smisaki 
10675553Smisaki 	handle = nxgep->npi_handle;
10685553Smisaki 	portt = nxgep->mac.porttype;
10695553Smisaki 	statsp = nxgep->statsp;
10705553Smisaki 
10715553Smisaki 	if (portt == PORT_TYPE_XMAC) {
10725553Smisaki 		/* Readin the current XMAC Config Register for XMAC */
10735553Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
10745553Smisaki 
10755553Smisaki 		/*
10765553Smisaki 		 * Setup XMAC Configuration for XMAC
10775553Smisaki 		 * XMAC only supports receive-pause
10785553Smisaki 		 */
10795553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
10805553Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
10815553Smisaki 				/*
10825553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
10835553Smisaki 				 * is 0, enable receive pause.
10845553Smisaki 				 */
10855553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
10865553Smisaki 			} else {
10875553Smisaki 				/*
10885553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
10895553Smisaki 				 * is 1, disable receive pause.  Send pause is
10905553Smisaki 				 * not supported.
10915553Smisaki 				 */
10925553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
10935553Smisaki 			}
10945553Smisaki 		} else {
10956439Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10966439Sml29623 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
10976439Sml29623 			    portn));
10985553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
10996439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11006439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
11016439Sml29623 				    "enable pause", portn));
11025553Smisaki 				/*
11035553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11045553Smisaki 				 * is 1, enable receive pause.
11055553Smisaki 				 */
11065553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
11075553Smisaki 			} else {
11085553Smisaki 				/*
11095553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11105553Smisaki 				 * is 0, disable receive pause. Send pause is
11115553Smisaki 				 * not supported
11125553Smisaki 				 */
11136439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11146439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
11156439Sml29623 				    "disable pause", portn));
11165553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
11175553Smisaki 			}
11185553Smisaki 		}
11195553Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
11205553Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
11215553Smisaki 		/* Readin the current MAC CTRL Config Register for BMAC */
11225553Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
11235553Smisaki 
11245553Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
11255553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
11265553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
11275553Smisaki 				/*
11285553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
11295553Smisaki 				 * is 1, disable receive pause. Send pause
11305553Smisaki 				 * is not supported
11315553Smisaki 				 */
11325553Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
11335553Smisaki 			} else {
11345553Smisaki 				/*
11355553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
11365553Smisaki 				 * is 0, enable receive pause and disable
11375553Smisaki 				 * send pause.
11385553Smisaki 				 */
11395553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
11405553Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
11415553Smisaki 			}
11425553Smisaki 		} else {
11435553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
11445553Smisaki 				/*
11455553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11465553Smisaki 				 * is 1, enable receive pause. Send pause is
11475553Smisaki 				 * not supported.
11485553Smisaki 				 */
11495553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
11505553Smisaki 			} else {
11515553Smisaki 				/*
11525553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
11535553Smisaki 				 * is 0, pause capability is not available in
11545553Smisaki 				 * either direction.
11555553Smisaki 				 */
11565553Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
11575553Smisaki 					~MAC_CTRL_CFG_RECV_PAUSE_EN);
11585553Smisaki 			}
11595553Smisaki 		}
11605553Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
11615553Smisaki 	}
11625553Smisaki 
11635553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
11645553Smisaki 	    portn));
11655553Smisaki 
11665553Smisaki 	return (NXGE_OK);
11675553Smisaki }
11685553Smisaki 
11693859Sml29623 /* Initialize the Internal Serdes */
11703859Sml29623 
11713859Sml29623 nxge_status_t
11723859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
11733859Sml29623 {
11743859Sml29623 	p_nxge_stats_t		statsp;
11753859Sml29623 #ifdef	NXGE_DEBUG
11763859Sml29623 	uint8_t			portn;
11773859Sml29623 #endif
11783859Sml29623 	nxge_status_t		status = NXGE_OK;
11793859Sml29623 
11803859Sml29623 #ifdef	NXGE_DEBUG
11813859Sml29623 	portn = nxgep->mac.portnum;
11823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11834732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
11843859Sml29623 #endif
11853859Sml29623 
11864732Sdavemq 	if (nxgep->xcvr.serdes_init) {
11874732Sdavemq 		statsp = nxgep->statsp;
11884732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
11894732Sdavemq 		if (status != NXGE_OK)
11903859Sml29623 			goto fail;
11914732Sdavemq 		statsp->mac_stats.serdes_inits++;
11923859Sml29623 	}
11933859Sml29623 
11943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
11954732Sdavemq 	    portn));
11963859Sml29623 
11973859Sml29623 	return (NXGE_OK);
11983859Sml29623 
11993859Sml29623 fail:
12003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12014732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
12024732Sdavemq 	    portn));
12033859Sml29623 
12043859Sml29623 	return (status);
12053859Sml29623 }
12063859Sml29623 
12073859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
12083859Sml29623 
12094732Sdavemq static nxge_status_t
12103859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
12113859Sml29623 {
12123859Sml29623 	uint8_t portn;
12133859Sml29623 	int chan;
12143859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
12154977Sraghus 	esr_ti_cfgpll_l_t pll_sts_l;
12163859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
12173859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
12183859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
12193859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
12204977Sraghus #ifdef NXGE_DEBUG
12214977Sraghus 	esr_ti_testcfg_t cfg;
12224977Sraghus #endif
12233859Sml29623 	esr_ti_testcfg_t test_cfg;
12243859Sml29623 	nxge_status_t status = NXGE_OK;
12253859Sml29623 
12263859Sml29623 	portn = nxgep->mac.portnum;
12273859Sml29623 
12283859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
12293859Sml29623 			portn));
12303859Sml29623 
12313859Sml29623 	tx_cfg_l.value = 0;
12323859Sml29623 	tx_cfg_h.value = 0;
12333859Sml29623 	rx_cfg_l.value = 0;
12343859Sml29623 	rx_cfg_h.value = 0;
12353859Sml29623 	pll_cfg_l.value = 0;
12364977Sraghus 	pll_sts_l.value = 0;
12373859Sml29623 	test_cfg.value = 0;
12383859Sml29623 
12394977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
12404977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
12413859Sml29623 		/* 0x0E01 */
12423859Sml29623 		tx_cfg_l.bits.entx = 1;
12433859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
12443859Sml29623 
12453859Sml29623 		/* 0x9101 */
12463859Sml29623 		rx_cfg_l.bits.enrx = 1;
12473859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
12483859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
12493859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
12503859Sml29623 
12513859Sml29623 		/* 0x0008 */
12523859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12533859Sml29623 
12543859Sml29623 		/* Set loopback mode if necessary */
12553859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
12563859Sml29623 			tx_cfg_l.bits.entest = 1;
12573859Sml29623 			rx_cfg_l.bits.entest = 1;
12583859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
12593859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
12603859Sml29623 				ESR_N2_DEV_ADDR,
12613859Sml29623 				ESR_N2_TEST_CFG_REG, test_cfg.value))
12623859Sml29623 				!= NXGE_OK)
12633859Sml29623 			goto fail;
12643859Sml29623 		}
12653859Sml29623 
12663859Sml29623 		/* Use default PLL value */
12673859Sml29623 
12684977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
12694977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
12703859Sml29623 
12713859Sml29623 		/* 0x0E21 */
12723859Sml29623 		tx_cfg_l.bits.entx = 1;
12733859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
12743859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
12753859Sml29623 
12763859Sml29623 		/* 0x9121 */
12773859Sml29623 		rx_cfg_l.bits.enrx = 1;
12783859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
12793859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
12803859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
12813859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
12823859Sml29623 
12834977Sraghus 		if (portn == 0) {
12844977Sraghus 			/* 0x8 */
12854977Sraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
12864977Sraghus 		}
12873859Sml29623 
12883859Sml29623 		/* MPY = 0x100 */
12893859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
12903859Sml29623 
12913859Sml29623 		/* Set PLL */
12923859Sml29623 		pll_cfg_l.bits.enpll = 1;
12934977Sraghus 		pll_sts_l.bits.enpll = 1;
12943859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
12953859Sml29623 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
12963859Sml29623 				!= NXGE_OK)
12973859Sml29623 			goto fail;
12984977Sraghus 
12994977Sraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13004977Sraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
13014977Sraghus 			goto fail;
13024977Sraghus 
13034977Sraghus #ifdef  NXGE_DEBUG
13044977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
13054977Sraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
13064977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13074977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
13084977Sraghus 		    portn, pll_cfg_l.value, cfg.value));
13094977Sraghus 
13104977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
13114977Sraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
13124977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13134977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
13144977Sraghus 		    portn, pll_sts_l.value, cfg.value));
13154977Sraghus #endif
13164977Sraghus 
13174977Sraghus 		/* Set loopback mode if necessary */
13184977Sraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
13194977Sraghus 			tx_cfg_l.bits.entest = 1;
13204977Sraghus 			rx_cfg_l.bits.entest = 1;
13214977Sraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
13224977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13234977Sraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
13244977Sraghus 			    portn, test_cfg.value));
13254977Sraghus 			if ((status = nxge_mdio_write(nxgep, portn,
13264977Sraghus 			    ESR_N2_DEV_ADDR,
13274977Sraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
13284977Sraghus 				goto fail;
13294977Sraghus 			}
13304977Sraghus 		}
13313859Sml29623 	} else {
13323859Sml29623 		goto fail;
13333859Sml29623 	}
13343859Sml29623 
13353859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
13363859Sml29623 
13373859Sml29623 	NXGE_DELAY(20);
13383859Sml29623 
13393859Sml29623 	/* init TX channels */
13403859Sml29623 	for (chan = 0; chan < 4; chan++) {
13413859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13423859Sml29623 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
13433859Sml29623 				!= NXGE_OK)
13443859Sml29623 			goto fail;
13453859Sml29623 
13463859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13473859Sml29623 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
13483859Sml29623 				!= NXGE_OK)
13493859Sml29623 			goto fail;
13504977Sraghus 
13514977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13524977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
13534977Sraghus 		    portn, chan, tx_cfg_l.value));
13544977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13554977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
13564977Sraghus 		    portn, chan, tx_cfg_h.value));
13573859Sml29623 	}
13583859Sml29623 
13593859Sml29623 	/* init RX channels */
13603859Sml29623 	for (chan = 0; chan < 4; chan++) {
13613859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13623859Sml29623 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
13633859Sml29623 				!= NXGE_OK)
13643859Sml29623 			goto fail;
13653859Sml29623 
13663859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
13673859Sml29623 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
13683859Sml29623 				!= NXGE_OK)
13693859Sml29623 			goto fail;
13704977Sraghus 
13714977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13724977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
13734977Sraghus 		    portn, chan, rx_cfg_l.value));
13744977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13754977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
13764977Sraghus 		    portn, chan, rx_cfg_h.value));
13773859Sml29623 	}
13783859Sml29623 
13793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
13803859Sml29623 			portn));
13813859Sml29623 
13823859Sml29623 	return (NXGE_OK);
13833859Sml29623 fail:
13845572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13855572Ssbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
13865572Ssbehera 	    portn));
13873859Sml29623 
13883859Sml29623 	return (status);
13893859Sml29623 }
13903859Sml29623 
13914732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
13924732Sdavemq 
13934732Sdavemq static nxge_status_t
13944732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
13953859Sml29623 {
13963859Sml29623 	npi_handle_t		handle;
13973859Sml29623 	uint8_t			portn;
13986075Ssbehera 	int			chan, i;
13993859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
14003859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
14013859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
14023859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
14033859Sml29623 	uint64_t		val;
14043859Sml29623 	uint16_t		val16l;
14053859Sml29623 	uint16_t		val16h;
14063859Sml29623 	nxge_status_t		status = NXGE_OK;
14073859Sml29623 
14083859Sml29623 	portn = nxgep->mac.portnum;
14093859Sml29623 
14103859Sml29623 	if ((portn != 0) && (portn != 1))
14113859Sml29623 		return (NXGE_OK);
14123859Sml29623 
14134732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14144732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
14153859Sml29623 
14163859Sml29623 	handle = nxgep->npi_handle;
14174732Sdavemq 	switch (portn) {
14184732Sdavemq 	case 0:
14196028Ssbehera 		/* Reset Serdes */
14206028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
14216028Ssbehera 		NXGE_DELAY(20);
14226028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14236028Ssbehera 		NXGE_DELAY(2000);
14246028Ssbehera 
14256028Ssbehera 		/* Configure Serdes to 10G mode */
14266028Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
14276028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
14286028Ssbehera 
14294732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
14304732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
14314732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
14324732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
14334732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
14344732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
14354732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14364732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14374732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
14384732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
14394732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
14404732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
14414732Sdavemq 
14424732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
14434732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
14444732Sdavemq 			ESR_REG_WR(handle,
14454732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
14464732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
14474732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
14484732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
14494732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
14504732Sdavemq 		} else {
14514732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
14523859Sml29623 		}
14534732Sdavemq 		break;
14544732Sdavemq 	case 1:
14556028Ssbehera 		/* Reset Serdes */
14566028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
14576028Ssbehera 		NXGE_DELAY(20);
14586028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
14596028Ssbehera 		NXGE_DELAY(2000);
14606028Ssbehera 
14616028Ssbehera 		/* Configure Serdes to 10G mode */
14626028Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
14636028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
14646028Ssbehera 
14654732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
14664732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
14674732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
14684732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
14694732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
14704732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
14714732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14724732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
14734732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
14744732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
14754732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
14764732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
14774732Sdavemq 
14784732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
14794732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
14804732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
14814732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
14824732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
14834732Sdavemq 		} else {
14844732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
14853859Sml29623 		}
14864732Sdavemq 		break;
14874732Sdavemq 	default:
14884732Sdavemq 		/* Nothing to do here */
14894732Sdavemq 		goto done;
14904732Sdavemq 	}
14914732Sdavemq 
14924732Sdavemq 	/* init TX RX channels */
14934732Sdavemq 	for (chan = 0; chan < 4; chan++) {
14944732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
14954732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
14964732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
14973859Sml29623 			goto fail;
14984732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
14994732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
15004732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
15013859Sml29623 			goto fail;
15023859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
15034732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
15044732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
15053859Sml29623 			goto fail;
15063859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
15074732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
15084732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
15094732Sdavemq 			goto fail;
15104732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
15114732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
15124732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
15134732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
15144732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
15154732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
15164732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
15174732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15184732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
15194732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
15204732Sdavemq 			goto fail;
15214732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15224732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
15234732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
15244732Sdavemq 			goto fail;
15254732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15264732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
15274732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
15284732Sdavemq 			goto fail;
15294732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
15304732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
15314732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
15323859Sml29623 			goto fail;
15333859Sml29623 		}
15343859Sml29623 
15354732Sdavemq 	/* Apply Tx core reset */
15364732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
15374732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
15384732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
15394732Sdavemq 		goto fail;
15404732Sdavemq 
15414732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15424732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
15434732Sdavemq 	    NXGE_OK)
15444732Sdavemq 		goto fail;
15454732Sdavemq 
15464732Sdavemq 	NXGE_DELAY(200);
15474732Sdavemq 
15484732Sdavemq 	/* Apply Rx core reset */
15494732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15504732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
15514732Sdavemq 	    NXGE_OK)
15524732Sdavemq 		goto fail;
15534732Sdavemq 
15544732Sdavemq 	NXGE_DELAY(200);
15554732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15564732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
15574732Sdavemq 		goto fail;
15584732Sdavemq 
15594732Sdavemq 	NXGE_DELAY(200);
15604732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
15614732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
15624732Sdavemq 	    &val16l)) != NXGE_OK)
15634732Sdavemq 		goto fail;
15644732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
15654732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
15664732Sdavemq 		goto fail;
15674732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
15684732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15695196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
15705196Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
15715196Ssbehera 		    portn, val16l, val16h));
15724732Sdavemq 	}
15734732Sdavemq 
15744732Sdavemq 	if (portn == 0) {
15756075Ssbehera 		/* Wait for serdes to be ready */
15766075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
15776075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
15786075Ssbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
15796075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
15806075Ssbehera 			    ESR_SIG_XSERDES_RDY_P0 |
15816075Ssbehera 			    ESR_SIG_XDETECT_P0_CH3 |
15826075Ssbehera 			    ESR_SIG_XDETECT_P0_CH2 |
15836075Ssbehera 			    ESR_SIG_XDETECT_P0_CH1 |
15846075Ssbehera 			    ESR_SIG_XDETECT_P0_CH0))
15856075Ssbehera 
15866075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
15876075Ssbehera 			else
15886075Ssbehera 				break;
15896075Ssbehera 		}
15906075Ssbehera 
15916075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1592*6650Sjoycey 			/*
1593*6650Sjoycey 			 * RDY signal stays low may due to the absent of the
1594*6650Sjoycey 			 * external PHY, it is not an error condition. But still
1595*6650Sjoycey 			 * print the message for the debugging purpose when link
1596*6650Sjoycey 			 * stays down
1597*6650Sjoycey 			 */
15986075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15996075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
16006075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
1601*6650Sjoycey 			goto done;
16024732Sdavemq 		}
16034732Sdavemq 	} else if (portn == 1) {
16046075Ssbehera 		/* Wait for serdes to be ready */
16056075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
16066075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
16076075Ssbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
16086075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
16096075Ssbehera 			    ESR_SIG_XSERDES_RDY_P1 |
16106075Ssbehera 			    ESR_SIG_XDETECT_P1_CH3 |
16116075Ssbehera 			    ESR_SIG_XDETECT_P1_CH2 |
16126075Ssbehera 			    ESR_SIG_XDETECT_P1_CH1 |
16136075Ssbehera 			    ESR_SIG_XDETECT_P1_CH0))
16146075Ssbehera 
16156075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
16166075Ssbehera 			else
16176075Ssbehera 				break;
16186075Ssbehera 		}
16196075Ssbehera 
16206075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1621*6650Sjoycey 			/*
1622*6650Sjoycey 			 * RDY signal stays low may due to the absent of the
1623*6650Sjoycey 			 * external PHY, it is not an error condition. But still
1624*6650Sjoycey 			 * print the message for the debugging purpose when link
1625*6650Sjoycey 			 * stays down
1626*6650Sjoycey 			 */
16276075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16286075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
16296075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
1630*6650Sjoycey 			goto done;
16313859Sml29623 		}
16323859Sml29623 	}
16333859Sml29623 
16343859Sml29623 done:
16354732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16364732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
16374732Sdavemq 
16383859Sml29623 	return (NXGE_OK);
16393859Sml29623 fail:
16405572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16414732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
16424732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
16433859Sml29623 
16443859Sml29623 	return (status);
16453859Sml29623 }
16463859Sml29623 
16474732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
16484732Sdavemq 
16494732Sdavemq static nxge_status_t
16504732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
16513859Sml29623 {
16524732Sdavemq 	npi_handle_t		handle;
16534732Sdavemq 	uint8_t			portn;
16545196Ssbehera 	int			chan;
16555196Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
16565196Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
16575196Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
16585196Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
16594732Sdavemq 	uint64_t		val;
16605196Ssbehera 	uint16_t		val16l;
16615196Ssbehera 	uint16_t		val16h;
16625196Ssbehera 	nxge_status_t		status = NXGE_OK;
16633859Sml29623 
16643859Sml29623 	portn = nxgep->mac.portnum;
16654732Sdavemq 
16664732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16674732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
16684732Sdavemq 
16694732Sdavemq 	handle = nxgep->npi_handle;
16704732Sdavemq 
16714732Sdavemq 	switch (portn) {
16724732Sdavemq 	case 0:
16735196Ssbehera 		/* Assert the reset register */
16745196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16755196Ssbehera 		val |= ESR_RESET_0;
16765196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16775196Ssbehera 
16785196Ssbehera 		/* Set the PLL register to 0x79 */
16795196Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
16805196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
16815196Ssbehera 
16825196Ssbehera 		/* Set the control register to 0x249249f */
16835196Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
16845196Ssbehera 
16855196Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
16865196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16875196Ssbehera 			/* Set pad loopback modes 0xaa */
16885196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
16895196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
16905196Ssbehera 		} else {
16915196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
16925196Ssbehera 		}
16935196Ssbehera 
16945196Ssbehera 		/* Deassert the reset register */
16955196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
16965196Ssbehera 		val &= ~ESR_RESET_0;
16975196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
16984732Sdavemq 		break;
16995196Ssbehera 
17004732Sdavemq 	case 1:
17015196Ssbehera 		/* Assert the reset register */
17025196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
17035196Ssbehera 		val |= ESR_RESET_1;
17045196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
17055196Ssbehera 
17065196Ssbehera 		/* Set PLL register to 0x79 */
17075196Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
17085196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
17095196Ssbehera 
17105196Ssbehera 		/* Set the control register to 0x249249f */
17115196Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
17125196Ssbehera 
17135196Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
17145196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
17155196Ssbehera 			/* Set pad loopback mode 0xaa */
17165196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
17175196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
17185196Ssbehera 		} else {
17195196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
17205196Ssbehera 		}
17215196Ssbehera 
17225196Ssbehera 		/* Deassert the reset register */
17235196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
17245196Ssbehera 		val &= ~ESR_RESET_1;
17255196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
17264732Sdavemq 		break;
17275196Ssbehera 
17284732Sdavemq 	default:
17295196Ssbehera 		/* Nothing to do here */
17305196Ssbehera 		goto done;
17315196Ssbehera 	}
17325196Ssbehera 
17335196Ssbehera 	/* init TX RX channels */
17345196Ssbehera 	for (chan = 0; chan < 4; chan++) {
17355196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
17365196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17375196Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
17385196Ssbehera 			goto fail;
17395196Ssbehera 		}
17405196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
17415196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17425196Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
17435196Ssbehera 			goto fail;
17445196Ssbehera 		}
17455196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
17465196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17475196Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
17485196Ssbehera 			goto fail;
17495196Ssbehera 		}
17505196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
17515196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17525196Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
17535196Ssbehera 			goto fail;
17545196Ssbehera 		}
17555196Ssbehera 
17565196Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
17575196Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
17585196Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
17595196Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
17605196Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
17615196Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
17625196Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
17635196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17645196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17655196Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
17665196Ssbehera 			goto fail;
17675196Ssbehera 		}
17685196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17695196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17705196Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
17715196Ssbehera 			goto fail;
17725196Ssbehera 		}
17735196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17745196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17755196Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
17765196Ssbehera 			goto fail;
17775196Ssbehera 		}
17785196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
17795196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17805196Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
17815196Ssbehera 			goto fail;
17825196Ssbehera 		}
17835196Ssbehera 	}
17845196Ssbehera 
17855196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17865196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
17874732Sdavemq 		goto fail;
17883859Sml29623 	}
17895196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17905196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
17915196Ssbehera 		goto fail;
17925196Ssbehera 	}
17935196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17945196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
17955196Ssbehera 		goto fail;
17965196Ssbehera 	}
17975196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
17985196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
17995196Ssbehera 		goto fail;
18005196Ssbehera 	}
18015196Ssbehera 
18025196Ssbehera 	/* Apply Tx core reset */
18035196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18045196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
18055196Ssbehera 		goto fail;
18065196Ssbehera 	}
18075196Ssbehera 
18085196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18095196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
18105196Ssbehera 	    NXGE_OK) {
18115196Ssbehera 		goto fail;
18125196Ssbehera 	}
18135196Ssbehera 
18145196Ssbehera 	NXGE_DELAY(200);
18155196Ssbehera 
18165196Ssbehera 	/* Apply Rx core reset */
18175196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18185196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
18195196Ssbehera 	    NXGE_OK) {
18205196Ssbehera 		goto fail;
18215196Ssbehera 	}
18225196Ssbehera 
18235196Ssbehera 	NXGE_DELAY(200);
18245196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18255196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
18265196Ssbehera 		goto fail;
18275196Ssbehera 	}
18285196Ssbehera 
18295196Ssbehera 	NXGE_DELAY(200);
18305196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18315196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
18325196Ssbehera 		goto fail;
18335196Ssbehera 	}
18345196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18355196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
18365196Ssbehera 		goto fail;
18375196Ssbehera 	}
18385196Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
18395196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18405196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
18415196Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
18425196Ssbehera 		status = NXGE_ERROR;
18435196Ssbehera 		goto fail;
18445196Ssbehera 	}
18455196Ssbehera 
18465196Ssbehera 	NXGE_DELAY(200);
18475196Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
18485196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18495196Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
18505196Ssbehera 	    "val 0x%x", portn, val));
18515196Ssbehera 	if (portn == 0) {
18525196Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
18535196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
1854*6650Sjoycey 			/*
1855*6650Sjoycey 			 * RDY signal stays low may due to the absent of the
1856*6650Sjoycey 			 * external PHY, it is not an error condition. But still
1857*6650Sjoycey 			 * print the message for the debugging purpose when link
1858*6650Sjoycey 			 * stays down
1859*6650Sjoycey 			 */
18605196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1861*6650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
1862*6650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
1863*6650Sjoycey 			goto done;
18645196Ssbehera 		}
18655196Ssbehera 	} else if (portn == 1) {
18665196Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
18675196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
1868*6650Sjoycey 			/*
1869*6650Sjoycey 			 * RDY signal stays low may due to the absent of the
1870*6650Sjoycey 			 * external PHY, it is not an error condition. But still
1871*6650Sjoycey 			 * print the message for the debugging purpose when link
1872*6650Sjoycey 			 * stays down
1873*6650Sjoycey 			 */
18745196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1875*6650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
1876*6650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
1877*6650Sjoycey 			goto done;
18785196Ssbehera 		}
18795196Ssbehera 	}
18805196Ssbehera done:
18814732Sdavemq 
18824732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18834732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
18843859Sml29623 	return (NXGE_OK);
18854732Sdavemq fail:
18865196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18874732Sdavemq 	    "nxge_1G_serdes_init: "
18884732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
18894732Sdavemq 	    portn));
18904732Sdavemq 
18915196Ssbehera 	return (status);
18923859Sml29623 }
18933859Sml29623 
18945572Ssbehera /* Initialize the BCM 8704 xcvr */
18954732Sdavemq 
18964732Sdavemq static nxge_status_t
18975572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
18983859Sml29623 {
18993859Sml29623 	uint16_t		val;
19003859Sml29623 #ifdef	NXGE_DEBUG
19013859Sml29623 	uint8_t			portn;
19023859Sml29623 	uint16_t		val1;
19033859Sml29623 #endif
19043859Sml29623 	uint8_t			phy_port_addr;
19053859Sml29623 	pmd_tx_control_t	tx_ctl;
19063859Sml29623 	control_t		ctl;
19073859Sml29623 	phyxs_control_t		phyxs_ctl;
19083859Sml29623 	pcs_control_t		pcs_ctl;
19093859Sml29623 	uint32_t		delay = 0;
19103859Sml29623 	optics_dcntr_t		op_ctr;
19113859Sml29623 	nxge_status_t		status = NXGE_OK;
19123859Sml29623 #ifdef	NXGE_DEBUG
19133859Sml29623 	portn = nxgep->mac.portnum;
19143859Sml29623 #endif
19155572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
19164732Sdavemq 	    portn));
19174732Sdavemq 
19184732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
19194732Sdavemq 
19204732Sdavemq 	/* Reset the transceiver */
19214732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
19224732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
19234732Sdavemq 		goto fail;
19244732Sdavemq 
19254732Sdavemq 	phyxs_ctl.bits.reset = 1;
19264732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
19274732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
19284732Sdavemq 		goto fail;
19294732Sdavemq 
19304732Sdavemq 	do {
19314732Sdavemq 		drv_usecwait(500);
19324732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19334732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
19344732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
19354732Sdavemq 			goto fail;
19364732Sdavemq 		delay++;
19374732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
19384732Sdavemq 	if (delay == 100) {
19394732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
19404732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
19414732Sdavemq 		status = NXGE_ERROR;
19424732Sdavemq 		goto fail;
19434732Sdavemq 	}
19444732Sdavemq 
19454732Sdavemq 	/* Set to 0x7FBF */
19464732Sdavemq 	ctl.value = 0;
19474732Sdavemq 	ctl.bits.res1 = 0x3F;
19484732Sdavemq 	ctl.bits.optxon_lvl = 1;
19494732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
19504732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
19514732Sdavemq 	ctl.bits.optxflt_lvl = 1;
19524732Sdavemq 	ctl.bits.opprflt_lvl = 1;
19534732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
19544732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
19554732Sdavemq 	ctl.bits.optxrst_lvl = 1;
19564732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
19574732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
19584732Sdavemq 	    != NXGE_OK)
19594732Sdavemq 		goto fail;
19604732Sdavemq 
19614732Sdavemq 	/* Set to 0x164 */
19624732Sdavemq 	tx_ctl.value = 0;
19634732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
19644732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
19654732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
19664732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
19674732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
19684732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
19694732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
19704732Sdavemq 		goto fail;
19714732Sdavemq 	/*
19724732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
19734732Sdavemq 	 * back these registers twice after written.
19744732Sdavemq 	 */
19754732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19764732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
19774732Sdavemq 	    != NXGE_OK)
19784732Sdavemq 		goto fail;
19794732Sdavemq 
19804732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19814732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
19824732Sdavemq 	    != NXGE_OK)
19834732Sdavemq 		goto fail;
19844732Sdavemq 
19854732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19864732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
19874732Sdavemq 	    != NXGE_OK)
19884732Sdavemq 		goto fail;
19894732Sdavemq 
19904732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19914732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
19924732Sdavemq 	    != NXGE_OK)
19934732Sdavemq 		goto fail;
19944732Sdavemq 
19954732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
19964732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
19974732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
19984732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
19994732Sdavemq 		goto fail;
20005553Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
20015553Smisaki 		op_ctr.bits.gpio_sel = 0x1;
20025553Smisaki 	} else {
20035553Smisaki 		op_ctr.bits.gpio_sel = 0x3;
20045553Smisaki 	}
20054732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
20064732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
20074732Sdavemq 	    op_ctr.value)) != NXGE_OK)
20084732Sdavemq 		goto fail;
20094732Sdavemq 
20104732Sdavemq 	NXGE_DELAY(1000000);
20114732Sdavemq 
20124732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
20134732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
20144732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
20154732Sdavemq 	    != NXGE_OK)
20164732Sdavemq 		goto fail;
20174732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
20184732Sdavemq 		pcs_ctl.bits.loopback = 1;
20194732Sdavemq 	else
20204732Sdavemq 		pcs_ctl.bits.loopback = 0;
20214732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
20224732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
20234732Sdavemq 	    != NXGE_OK)
20244732Sdavemq 		goto fail;
20254732Sdavemq 
20264732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
20274732Sdavemq 	if (status != NXGE_OK)
20284732Sdavemq 		goto fail;
20294732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20304732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
20314732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
20324732Sdavemq 	if (status != NXGE_OK)
20334732Sdavemq 		goto fail;
20344732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20354732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
20364732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
20374732Sdavemq 	if (status != NXGE_OK)
20384732Sdavemq 		goto fail;
20394732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20404732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
20414732Sdavemq 
20424732Sdavemq #ifdef	NXGE_DEBUG
20434732Sdavemq 	/* Diagnose link issue if link is not up */
20444732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
20454732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
20464732Sdavemq 	    &val);
20474732Sdavemq 	if (status != NXGE_OK)
20484732Sdavemq 		goto fail;
20494732Sdavemq 
20504732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
20514732Sdavemq 				BCM8704_USER_DEV3_ADDR,
20524732Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
20534732Sdavemq 				&val);
20544732Sdavemq 	if (status != NXGE_OK)
20554732Sdavemq 		goto fail;
20564732Sdavemq 
20574732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
20584732Sdavemq 				BCM8704_USER_DEV3_ADDR,
20594732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
20604732Sdavemq 				&val1);
20614732Sdavemq 	if (status != NXGE_OK)
20624732Sdavemq 		goto fail;
20634732Sdavemq 
20644732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
20654732Sdavemq 				BCM8704_USER_DEV3_ADDR,
20664732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
20674732Sdavemq 				&val1);
20684732Sdavemq 	if (status != NXGE_OK)
20694732Sdavemq 		goto fail;
20704732Sdavemq 
20714732Sdavemq 	if (val != 0x3FC) {
20724732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
20734732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20744732Sdavemq 			    "Cable not connected to peer or bad"
20754732Sdavemq 			    " cable on port<%d>\n", portn));
20764732Sdavemq 		} else if (val == 0x639C) {
20774732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20784732Sdavemq 			    "Optical module (XFP) is bad or absent"
20794732Sdavemq 			    " on port<%d>\n", portn));
20804732Sdavemq 		}
20814732Sdavemq 	}
20824732Sdavemq #endif
20834732Sdavemq 
20845572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
20855572Ssbehera 	    portn));
20865572Ssbehera 	return (NXGE_OK);
20875572Ssbehera 
20885572Ssbehera fail:
20895572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20905572Ssbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
20915572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
20925572Ssbehera 	return (NXGE_ERROR);
20935572Ssbehera }
20945572Ssbehera 
20955572Ssbehera /* Initialize the BCM 8706 Transceiver */
20965572Ssbehera 
20975572Ssbehera static nxge_status_t
20985572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
20995572Ssbehera {
21005572Ssbehera 	uint8_t			phy_port_addr;
21015572Ssbehera 	phyxs_control_t		phyxs_ctl;
21025572Ssbehera 	pcs_control_t		pcs_ctl;
21035572Ssbehera 	uint32_t		delay = 0;
21045572Ssbehera 	optics_dcntr_t		op_ctr;
21055572Ssbehera 	nxge_status_t		status = NXGE_OK;
21065572Ssbehera #ifdef	NXGE_DEBUG
21075572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
21085572Ssbehera #endif
21095572Ssbehera 
21105572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
21115572Ssbehera 	    portn));
21125572Ssbehera 
21135572Ssbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
21145572Ssbehera 
21155572Ssbehera 	/* Reset the transceiver */
21165572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
21175572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
21185572Ssbehera 		goto fail;
21195572Ssbehera 
21205572Ssbehera 	phyxs_ctl.bits.reset = 1;
21215572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
21225572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
21235572Ssbehera 		goto fail;
21245572Ssbehera 	do {
21255572Ssbehera 		drv_usecwait(500);
21265572Ssbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21275572Ssbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
21285572Ssbehera 		    &phyxs_ctl.value)) != NXGE_OK)
21295572Ssbehera 			goto fail;
21305572Ssbehera 		delay++;
21315572Ssbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
21325572Ssbehera 
21335572Ssbehera 	if (delay == 100) {
21345572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
21355572Ssbehera 		    "failed to reset Transceiver on port<%d>", portn));
21365572Ssbehera 		status = NXGE_ERROR;
21375572Ssbehera 		goto fail;
21385572Ssbehera 	}
21395572Ssbehera 
21405572Ssbehera 	NXGE_DELAY(1000000);
21415572Ssbehera 
21425572Ssbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
21435572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21445572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
21455572Ssbehera 	    != NXGE_OK)
21465572Ssbehera 		goto fail;
21475572Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
21485572Ssbehera 		pcs_ctl.bits.loopback = 1;
21495572Ssbehera 	else
21505572Ssbehera 		pcs_ctl.bits.loopback = 0;
21515572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21525572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
21535572Ssbehera 	    != NXGE_OK)
21545572Ssbehera 		goto fail;
21555572Ssbehera 
21565572Ssbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
21575572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21585572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21595572Ssbehera 	    &op_ctr.value)) != NXGE_OK)
21605572Ssbehera 		goto fail;
21615572Ssbehera 	op_ctr.bits.gpio_sel = 0x3;
21625572Ssbehera 	op_ctr.bits.res2 = 0x1;
21635572Ssbehera 
21645572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
21655572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
21665572Ssbehera 	    op_ctr.value)) != NXGE_OK)
21675572Ssbehera 		goto fail;
21685572Ssbehera 
21695572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
21705572Ssbehera 	    portn));
21715572Ssbehera 	return (NXGE_OK);
21725572Ssbehera 
21735572Ssbehera fail:
21745572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21755572Ssbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
21765572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
21775572Ssbehera 	return (status);
21785572Ssbehera }
21795572Ssbehera 
21806604Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
21816604Ssbehera 
21826604Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
21836604Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
21846604Ssbehera 
21856604Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
21866604Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
21876604Ssbehera 
21886604Ssbehera 
21896604Ssbehera static void
21906604Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
21916604Ssbehera {
21926604Ssbehera 	uint16_t	value;
21936604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
21946604Ssbehera 
21956604Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
21966604Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
21976604Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
21986604Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
21996604Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
22006604Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
22016604Ssbehera 		    value);
22026604Ssbehera 	}
22036604Ssbehera }
22046604Ssbehera 
22056604Ssbehera static nxge_status_t
22066604Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
22076604Ssbehera {
22086604Ssbehera 	nxge_status_t	status;
22096604Ssbehera 	pcs_control_t	pcs_ctl;
22106604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
22116604Ssbehera 
22126604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
22136604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
22146604Ssbehera 
22156604Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
22166604Ssbehera 		pcs_ctl.bits.loopback = 1;
22176604Ssbehera 	else
22186604Ssbehera 		pcs_ctl.bits.loopback = 0;
22196604Ssbehera 
22206604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
22216604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
22226604Ssbehera 
22236604Ssbehera fail:
22246604Ssbehera 	return (status);
22256604Ssbehera }
22266604Ssbehera 
22276604Ssbehera 
22286604Ssbehera static void
22296604Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
22306604Ssbehera {
22316604Ssbehera 	uint16_t	val2;
22326604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
22336604Ssbehera 
22346604Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
22356604Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
22366604Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
22376604Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
22386604Ssbehera 
22396604Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
22406604Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
22416604Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
22426604Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
22436604Ssbehera 	}
22446604Ssbehera }
22456604Ssbehera 
22466604Ssbehera 
22476604Ssbehera static nxge_status_t
22486604Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
22496604Ssbehera {
22506604Ssbehera 	uint8_t		phy;
22516604Ssbehera 	nxge_status_t	status;
22526604Ssbehera 	uint16_t	clk;
22536604Ssbehera 
22546604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
22556604Ssbehera 
22566604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
22576604Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
22586604Ssbehera 	    nxgep->mac.portnum, phy));
22596604Ssbehera 
22606604Ssbehera 	/* Set LED functions	*/
22616604Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
22626604Ssbehera 	/* PCS activity */
22636604Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
22646604Ssbehera 
22656604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
22666604Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
22676604Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
22686604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
22696604Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
22706604Ssbehera 
22716604Ssbehera 	/* Set internal loopback mode if necessary */
22726604Ssbehera 
22736604Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
22746604Ssbehera 
22756604Ssbehera 	/* Enable PMD */
22766604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
22776604Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
22786604Ssbehera 
22796604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
22806604Ssbehera 
22816604Ssbehera fail:
22826604Ssbehera 	return (status);
22836604Ssbehera }
22846604Ssbehera 
22856604Ssbehera 
22866604Ssbehera 
22875572Ssbehera /* Initialize the 10G Transceiver */
22885572Ssbehera 
22895572Ssbehera static nxge_status_t
22905572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
22915572Ssbehera {
22925572Ssbehera 	p_nxge_stats_t		statsp;
22936439Sml29623 	p_nxge_param_t		param_arr = nxgep->param_arr;
22945572Ssbehera 	nxge_status_t		status = NXGE_OK;
22955572Ssbehera #ifdef	NXGE_DEBUG
22965572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
22975572Ssbehera #endif
22985572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
22995572Ssbehera 	    portn));
23005572Ssbehera 
23015572Ssbehera 	statsp = nxgep->statsp;
23025572Ssbehera 
23035572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
23045572Ssbehera 		goto done;
23055572Ssbehera 	}
23065572Ssbehera 
23075572Ssbehera 	/* Disable Link LEDs */
23085572Ssbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
23095572Ssbehera 		goto fail;
23105572Ssbehera 
23115572Ssbehera 	/* Set Clause 45 */
23125572Ssbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
23135572Ssbehera 
23145572Ssbehera 	switch (nxgep->chip_id) {
23155572Ssbehera 	case BCM8704_CHIP_ID:
23165572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
23175572Ssbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
23185572Ssbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
23195572Ssbehera 		break;
23205572Ssbehera 	case BCM8706_CHIP_ID:
23215572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
23225572Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
23235572Ssbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
23245572Ssbehera 		break;
23256604Ssbehera 	case MRVL88X201X_CHIP_ID:
23266604Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
23276604Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
23286604Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
23296604Ssbehera 		break;
23305572Ssbehera 	default:
23315572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
23325572Ssbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
23335572Ssbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
23345572Ssbehera 		goto fail;
23355572Ssbehera 	}
23365572Ssbehera 
23375572Ssbehera 	if (status != NXGE_OK) {
23385572Ssbehera 		goto fail;
23395572Ssbehera 	}
23404977Sraghus done:
23414732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
23424732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
23436439Sml29623 	statsp->mac_stats.adv_cap_asmpause =
23446439Sml29623 	    param_arr[param_anar_asmpause].value;
23456439Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
23464732Sdavemq 
23474732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
23484732Sdavemq 	    portn));
23494732Sdavemq 	return (NXGE_OK);
23504732Sdavemq 
23514732Sdavemq fail:
23525572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23534732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
23545572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
23555572Ssbehera 	return (NXGE_ERROR);
23564732Sdavemq }
23574732Sdavemq 
23584732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
23594732Sdavemq 
23604732Sdavemq static nxge_status_t
23614732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
23624732Sdavemq {
23634732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
23644732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
23654732Sdavemq 	nxge_status_t		status = NXGE_OK;
23664732Sdavemq 
23674977Sraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
23684977Sraghus 		statsp->mac_stats.cap_1000fdx =
23694977Sraghus 		    param_arr[param_anar_1000fdx].value;
23704977Sraghus 		goto done;
23714977Sraghus 	}
23724977Sraghus 
23734732Sdavemq 	/* Set Clause 22 */
23744732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
23754732Sdavemq 
23764732Sdavemq 	/* Set capability flags */
23774732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
23784977Sraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
23794977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
23804977Sraghus 		statsp->mac_stats.cap_100fdx =
23814977Sraghus 		    param_arr[param_anar_100fdx].value;
23824977Sraghus 		statsp->mac_stats.cap_10fdx =
23834977Sraghus 		    param_arr[param_anar_10fdx].value;
23844977Sraghus 	}
23854732Sdavemq 
23864732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
23874977Sraghus done:
23884732Sdavemq 	return (status);
23894732Sdavemq }
23904732Sdavemq 
23914732Sdavemq /* Initialize transceiver */
23924732Sdavemq 
23934732Sdavemq nxge_status_t
23944732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
23954732Sdavemq {
23964732Sdavemq 	p_nxge_stats_t		statsp;
23974732Sdavemq #ifdef	NXGE_DEBUG
23984732Sdavemq 	uint8_t			portn;
23994732Sdavemq #endif
24004732Sdavemq 
24014732Sdavemq 	nxge_status_t		status = NXGE_OK;
24024732Sdavemq #ifdef	NXGE_DEBUG
24034732Sdavemq 	portn = nxgep->mac.portnum;
24044732Sdavemq #endif
24053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
24063859Sml29623 	statsp = nxgep->statsp;
24073859Sml29623 
24083859Sml29623 	/*
24093859Sml29623 	 * Initialize the xcvr statistics.
24103859Sml29623 	 */
24113859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
24123859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
24133859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
24143859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
24153859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
24163859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
24173859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
24183859Sml29623 	statsp->mac_stats.cap_pause = 0;
24193859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
24203859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
24213859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
24223859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
24233859Sml29623 
24243859Sml29623 	/*
24253859Sml29623 	 * Initialize the link statistics.
24263859Sml29623 	 */
24273859Sml29623 	statsp->mac_stats.link_T4 = 0;
24283859Sml29623 	statsp->mac_stats.link_asmpause = 0;
24293859Sml29623 	statsp->mac_stats.link_pause = 0;
24303859Sml29623 
24314732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
24324732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
24333859Sml29623 		if (status != NXGE_OK)
24343859Sml29623 			goto fail;
24354732Sdavemq 		statsp->mac_stats.xcvr_inits++;
24363859Sml29623 	}
24373859Sml29623 
24384732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
24394732Sdavemq 	    portn));
24403859Sml29623 	return (NXGE_OK);
24413859Sml29623 
24423859Sml29623 fail:
24433859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
24444732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
24454732Sdavemq 	    portn));
24463859Sml29623 	return (status);
24473859Sml29623 }
24483859Sml29623 
24494977Sraghus /* Look for transceiver type */
24504977Sraghus 
24514977Sraghus nxge_status_t
24524977Sraghus nxge_xcvr_find(p_nxge_t nxgep)
24534977Sraghus {
24545196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
24555196Ssbehera 	    nxgep->mac.portnum));
24564977Sraghus 
24574977Sraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
24584977Sraghus 		return (NXGE_ERROR);
24594977Sraghus 
24604977Sraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
24614977Sraghus 		return (NXGE_ERROR);
24624977Sraghus 
24634977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
24644977Sraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
24654977Sraghus 	return (NXGE_OK);
24664977Sraghus }
24673859Sml29623 
24683859Sml29623 /* Initialize the TxMAC sub-block */
24693859Sml29623 
24703859Sml29623 nxge_status_t
24713859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
24723859Sml29623 {
24733859Sml29623 	npi_attr_t		ap;
24743859Sml29623 	uint8_t			portn;
24753859Sml29623 	nxge_port_mode_t	portmode;
24763859Sml29623 	nxge_port_t		portt;
24773859Sml29623 	npi_handle_t		handle;
24783859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
24793859Sml29623 
24803859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
24813859Sml29623 	portt    = nxgep->mac.porttype;
24823859Sml29623 	handle   = nxgep->npi_handle;
24833859Sml29623 	portmode = nxgep->mac.portmode;
24843859Sml29623 
24853859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
24863859Sml29623 			portn));
24873859Sml29623 	/* Set Max and Min Frame Size */
24886439Sml29623 	/*
24896439Sml29623 	 * Use maxframesize to configure the hardware maxframe size
24906439Sml29623 	 * and minframesize to configure the hardwae minframe size.
24916439Sml29623 	 */
24926439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
24936439Sml29623 	    "==> nxge_tx_mac_init: port<%d> "
24946439Sml29623 	    "min framesize %d max framesize %d ",
24956439Sml29623 	    nxgep->mac.minframesize,
24966439Sml29623 	    nxgep->mac.maxframesize,
24976439Sml29623 	    portn));
24986439Sml29623 
24996439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
25006439Sml29623 	    MAC_PORT_FRAME_SIZE,
25016439Sml29623 	    nxgep->mac.minframesize,
25026439Sml29623 	    nxgep->mac.maxframesize,
25036439Sml29623 	    rs);
25043859Sml29623 	if (rs != NPI_SUCCESS)
25053859Sml29623 		goto fail;
25063859Sml29623 
25073859Sml29623 	if (portt == PORT_TYPE_XMAC) {
25083859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
25093859Sml29623 				0)) != NPI_SUCCESS)
25103859Sml29623 			goto fail;
25113859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
25123859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
25134977Sraghus 		    (portmode == PORT_10G_COPPER) ||
25144977Sraghus 		    (portmode == PORT_10G_SERDES)) {
25153859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
25163859Sml29623 					XGMII_IPG_12_15, rs);
25173859Sml29623 			if (rs != NPI_SUCCESS)
25183859Sml29623 				goto fail;
25193859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
25203859Sml29623 		} else {
25213859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
25223859Sml29623 					MII_GMII_IPG_12, rs);
25233859Sml29623 			if (rs != NPI_SUCCESS)
25243859Sml29623 				goto fail;
25253859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
25263859Sml29623 		}
25273859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
25283859Sml29623 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
25293859Sml29623 			goto fail;
25303859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
25313859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
25323859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
25333859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
25343859Sml29623 
25353859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
25363859Sml29623 							!= NPI_SUCCESS)
25373859Sml29623 			goto fail;
25383859Sml29623 
25393859Sml29623 	} else {
25403859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
25413859Sml29623 				0)) != NPI_SUCCESS)
25423859Sml29623 			goto fail;
25433859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
25443859Sml29623 
25453859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
25463859Sml29623 				rs);
25473859Sml29623 		if (rs != NPI_SUCCESS)
25483859Sml29623 			goto fail;
25493859Sml29623 		nxgep->mac.ctrltype = 0x8808;
25503859Sml29623 
25513859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
25523859Sml29623 		if (rs != NPI_SUCCESS)
25533859Sml29623 			goto fail;
25543859Sml29623 		nxgep->mac.pa_size = 0x7;
25553859Sml29623 
25563859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
25573859Sml29623 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
25583859Sml29623 			goto fail;
25593859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
25603859Sml29623 	}
25613859Sml29623 
25623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
25633859Sml29623 			portn));
25643859Sml29623 
25653859Sml29623 	return (NXGE_OK);
25663859Sml29623 fail:
25673859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
25683859Sml29623 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
25693859Sml29623 					portn));
25703859Sml29623 
25713859Sml29623 	return (NXGE_ERROR | rs);
25723859Sml29623 }
25733859Sml29623 
25746495Sspeer int
25756495Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep)
25766495Sspeer {
25776495Sspeer 	int rdc_tbl;
25786495Sspeer 
25796495Sspeer 	/*
25806495Sspeer 	 * Get an RDC table (version 0).
25816495Sspeer 	 */
25826495Sspeer 	if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) {
25836495Sspeer 		NXGE_ERROR_MSG((nxgep, OBP_CTL,
25846495Sspeer 		    "nxge_hio_hostinfo_get_rdc_table: "
25856495Sspeer 		    "there are no free RDC tables!"));
25866495Sspeer 		return (EBUSY);
25876495Sspeer 	}
25886495Sspeer 
25896495Sspeer 	return (rdc_tbl);
25906495Sspeer }
25916495Sspeer 
25926495Sspeer /*
25936495Sspeer  * nxge_hio_hostinfo_init
25946495Sspeer  *
25956495Sspeer  *	Initialize an alternate MAC address, and bind a macrdctbln to it.
25966495Sspeer  *
25976495Sspeer  * Arguments:
25986495Sspeer  * 	nxge
25996495Sspeer  * 	vr	The Virtualization Region
26006495Sspeer  * 	macaddr	The alternate MAC address
26016495Sspeer  *
26026495Sspeer  * Notes:
26036495Sspeer  *	1. Find & bind an RDC table to <nxge>.
26046495Sspeer  *	2. Program an alternate MAC address (<macaddr>).
26056495Sspeer  *	3. Bind the RDC table to <macaddr>.
26066495Sspeer  *
26076495Sspeer  * Context:
26086495Sspeer  *	Service domain
26096495Sspeer  *
26106495Sspeer  * Side Effects:
26116495Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
26126495Sspeer  *	vr->slot & vr->altmac
26136495Sspeer  *
26146495Sspeer  */
26156495Sspeer int
26166495Sspeer nxge_hio_hostinfo_init(
26176495Sspeer 	nxge_t *nxge,
26186495Sspeer 	nxge_hio_vr_t *vr,	/* Virtualization Region */
26196495Sspeer 	ether_addr_t *macaddr)	/* The alternate MAC address */
26206495Sspeer {
26216495Sspeer 	int rdc_tbl, slot;
26226495Sspeer 
26236495Sspeer 	nxge_class_pt_cfg_t *class;
26246495Sspeer 	hostinfo_t mac_rdc;
26256495Sspeer 	npi_mac_addr_t altmac;
26266495Sspeer 	nxge_mmac_t *mmac_info;
26276495Sspeer 	nxge_rdc_grp_t	*group;
26286495Sspeer 	uint8_t *addr = (uint8_t *)macaddr;
26296495Sspeer 
26306495Sspeer 	mutex_enter(nxge->genlock);
26316495Sspeer 
26326495Sspeer 	rdc_tbl = vr->rdc_tbl;
26336495Sspeer 
26346495Sspeer 	/* Initialize the NXGE RDC table data structure. */
26356495Sspeer 	group = &nxge->pt_config.rdc_grps[rdc_tbl];
26366495Sspeer 	group->port = NXGE_GET_PORT_NUM(nxge->function_num);
26376495Sspeer 	group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
26386495Sspeer 	group->flag = 1;	/* This group has been configured. */
26396495Sspeer 
26406495Sspeer 	mmac_info = &nxge->nxge_mmac_info;
26416495Sspeer 
26426495Sspeer 	/*
26436495Sspeer 	 * Are there free slots.
26446495Sspeer 	 */
26456495Sspeer 	if (mmac_info->naddrfree == 0) {
26466495Sspeer 		mutex_exit(nxge->genlock);
26476495Sspeer 		return (ENOSPC);
26486495Sspeer 	}
26496495Sspeer 
26506495Sspeer 	/*
26516495Sspeer 	 * The vswitch has already added this MAC address.
26526495Sspeer 	 * Find its assigned slot.
26536495Sspeer 	 */
26546495Sspeer 	if (mmac_info->num_factory_mmac < mmac_info->num_mmac) {
26556495Sspeer 		for (slot = mmac_info->num_factory_mmac + 1;
26566495Sspeer 		    slot <= mmac_info->num_mmac; slot++) {
26576495Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
26586495Sspeer 				break;
26596495Sspeer 		}
26606495Sspeer 		if (slot > mmac_info->num_mmac) {
26616495Sspeer 			for (slot = 1; slot <= mmac_info->num_factory_mmac;
26626495Sspeer 			    slot++) {
26636495Sspeer 				if (!(mmac_info->mac_pool[slot].flags
26646495Sspeer 				    & MMAC_SLOT_USED))
26656495Sspeer 					break;
26666495Sspeer 			}
26676495Sspeer 		}
26686495Sspeer 	} else {
26696495Sspeer 		for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
26706495Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
26716495Sspeer 				break;
26726495Sspeer 		}
26736495Sspeer 	}
26746495Sspeer 
26756495Sspeer 	ASSERT(slot <= mmac_info->num_mmac);
26766495Sspeer 	vr->slot = slot;
26776495Sspeer 	slot = vr->slot - 1;
26786495Sspeer 
26796495Sspeer 	/*
26806495Sspeer 	 * Programm the mac address.
26816495Sspeer 	 */
26826495Sspeer 	altmac.w2 = (((uint16_t)addr[0]) << 8) |
26836495Sspeer 	    (((uint16_t)addr[1]) & 0x0ff);
26846495Sspeer 	altmac.w1 = (((uint16_t)addr[2]) << 8) |
26856495Sspeer 	    (((uint16_t)addr[3]) & 0x0ff);
26866495Sspeer 	altmac.w0 = (((uint16_t)addr[4]) << 8) |
26876495Sspeer 	    (((uint16_t)addr[5]) & 0x0ff);
26886495Sspeer 
26896495Sspeer 	if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET,
26906495Sspeer 	    nxge->function_num, slot, &altmac) != NPI_SUCCESS) {
26916495Sspeer 		mutex_exit(nxge->genlock);
26926495Sspeer 		return (EIO);
26936495Sspeer 	}
26946495Sspeer 
26956495Sspeer 	/*
26966495Sspeer 	 * Associate <rdc_tbl> with this MAC address slot.
26976495Sspeer 	 */
26986495Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
26996495Sspeer 
27006495Sspeer 	/* Update this variable. */
27016495Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
27026495Sspeer 	class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl;
27036495Sspeer 
27046495Sspeer 	mac_rdc.value = 0;
27056495Sspeer 	mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl;
27066495Sspeer 	mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr;
27076495Sspeer 	/* <mpr_npr> had better be 1! */
27086495Sspeer 
27096495Sspeer 	/* Program the RDC table. */
27106495Sspeer 	if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET,
27116495Sspeer 		nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) {
27126495Sspeer 		mutex_exit(nxge->genlock);
27136495Sspeer 		(void) nxge_m_mmac_remove(nxge, vr->slot);
27146495Sspeer 		return (EIO);
27156495Sspeer 	}
27166495Sspeer 
27176495Sspeer 	if (nxge->mac.portnum != XMAC_PORT_0 &&
27186495Sspeer 	    nxge->mac.portnum != XMAC_PORT_1)
27196495Sspeer 		slot++;
27206495Sspeer 
27216495Sspeer 	/* (Re-)enable the MAC address. */
27226495Sspeer 	(void) npi_mac_altaddr_enable(
27236495Sspeer 		nxge->npi_handle, nxge->mac.portnum, slot);
27246495Sspeer 
27256495Sspeer 	bcopy(macaddr, vr->altmac, sizeof (vr->altmac));
27266495Sspeer 
27276495Sspeer 	/*
27286495Sspeer 	 * Update mmac
27296495Sspeer 	 */
27306495Sspeer 	bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL);
27316495Sspeer 	mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED;
27326495Sspeer 	mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR;
27336495Sspeer 	mmac_info->naddrfree--;
27346495Sspeer 	nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE);
27356495Sspeer 
27366495Sspeer 	mutex_exit(nxge->genlock);
27376495Sspeer 	return (0);
27386495Sspeer }
27396495Sspeer 
27406495Sspeer /*
27416495Sspeer  * nxge_hio_hostinfo_uninit
27426495Sspeer  *
27436495Sspeer  *	Uninitialize an alternate MAC address.
27446495Sspeer  *
27456495Sspeer  * Arguments:
27466495Sspeer  * 	nxge
27476495Sspeer  * 	vr	The Virtualization Region
27486495Sspeer  *
27496495Sspeer  * Notes:
27506495Sspeer  *	1. Remove the VR's alternate MAC address.
27516495Sspeer  *	1. Free (unbind) the RDC table allocated to this VR.
27526495Sspeer  *
27536495Sspeer  * Context:
27546495Sspeer  *	Service domain
27556495Sspeer  *
27566495Sspeer  * Side Effects:
27576495Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
27586495Sspeer  *
27596495Sspeer  */
27606495Sspeer void
27616495Sspeer nxge_hio_hostinfo_uninit(
27626495Sspeer 	nxge_t *nxge,
27636495Sspeer 	nxge_hio_vr_t *vr)
27646495Sspeer {
27656495Sspeer 	nxge_class_pt_cfg_t *class;
27666495Sspeer 
27676495Sspeer 	(void) npi_mac_altaddr_disable(
27686495Sspeer 		nxge->npi_handle, nxge->mac.portnum, vr->slot);
27696495Sspeer 
27706495Sspeer 	/* Set this variable to its default. */
27716495Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
27726495Sspeer 	class->mac_host_info[vr->slot].rdctbl =
27736495Sspeer 	    nxge->pt_config.hw_config.def_mac_rxdma_grpid;
27746495Sspeer 
27756495Sspeer 	(void) nxge_m_mmac_remove(nxge, vr->slot);
27766495Sspeer 	vr->slot = -1;
27776495Sspeer 
27786495Sspeer 	(void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl);
27796495Sspeer 	vr->rdc_tbl = -1;
27806495Sspeer }
27816495Sspeer 
27823859Sml29623 /* Initialize the RxMAC sub-block */
27833859Sml29623 
27843859Sml29623 nxge_status_t
27853859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
27863859Sml29623 {
27873859Sml29623 	npi_attr_t		ap;
27883859Sml29623 	uint32_t		i;
27893859Sml29623 	uint16_t		hashtab_e;
27903859Sml29623 	p_hash_filter_t		hash_filter;
27913859Sml29623 	nxge_port_t		portt;
27923859Sml29623 	uint8_t			portn;
27933859Sml29623 	npi_handle_t		handle;
27943859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
27953859Sml29623 	uint16_t 		*addr16p;
27963859Sml29623 	uint16_t 		addr0, addr1, addr2;
27973859Sml29623 	xmac_rx_config_t	xconfig;
27983859Sml29623 	bmac_rx_config_t	bconfig;
27993859Sml29623 
28003859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
28013859Sml29623 
28023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
28033859Sml29623 			portn));
28043859Sml29623 	handle = nxgep->npi_handle;
28053859Sml29623 	portt = nxgep->mac.porttype;
28063859Sml29623 
28073859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
28083859Sml29623 	addr0 = ntohs(addr16p[2]);
28093859Sml29623 	addr1 = ntohs(addr16p[1]);
28103859Sml29623 	addr2 = ntohs(addr16p[0]);
28113859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
28123859Sml29623 		rs);
28133859Sml29623 
28143859Sml29623 	if (rs != NPI_SUCCESS)
28153859Sml29623 		goto fail;
28163859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
28173859Sml29623 	if (rs != NPI_SUCCESS)
28183859Sml29623 		goto fail;
28193859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
28203859Sml29623 	if (rs != NPI_SUCCESS)
28213859Sml29623 		goto fail;
28223859Sml29623 
28233859Sml29623 	/*
28243859Sml29623 	 * Load the multicast hash filter bits.
28253859Sml29623 	 */
28263859Sml29623 	hash_filter = nxgep->hash_filter;
28273859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
28283859Sml29623 		if (hash_filter != NULL) {
28293859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
28303859Sml29623 				(NMCFILTER_REGS - 1) - i];
28313859Sml29623 		} else {
28323859Sml29623 			hashtab_e = 0;
28333859Sml29623 		}
28343859Sml29623 
28353859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
28363859Sml29623 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
28373859Sml29623 			goto fail;
28383859Sml29623 	}
28393859Sml29623 
28403859Sml29623 	if (portt == PORT_TYPE_XMAC) {
28413859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
28423859Sml29623 				0)) != NPI_SUCCESS)
28433859Sml29623 			goto fail;
28443859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
28453859Sml29623 
28463859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
28473859Sml29623 
28483859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
28493859Sml29623 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
28503859Sml29623 			~CFG_XMAC_RX_STRIP_CRC;
28513859Sml29623 
28523859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
28533859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
28543859Sml29623 
28553859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
28563859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
28573859Sml29623 
28583859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
28593859Sml29623 
28603859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
28613859Sml29623 					xconfig)) != NPI_SUCCESS)
28623859Sml29623 			goto fail;
28633859Sml29623 		nxgep->mac.rx_config = xconfig;
28643859Sml29623 
28653859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
28663859Sml29623 
28673859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
28683859Sml29623 							!= NPI_SUCCESS)
28693859Sml29623 			goto fail;
28703859Sml29623 	} else {
28713859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
28723859Sml29623 
28733859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
28743859Sml29623 					0) != NPI_SUCCESS)
28753859Sml29623 			goto fail;
28763859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
28773859Sml29623 
28783859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
28793859Sml29623 			~CFG_BMAC_RX_STRIP_CRC;
28803859Sml29623 
28813859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
28823859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
28833859Sml29623 
28843859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
28853859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
28863859Sml29623 
28873859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
28883859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
28893859Sml29623 					bconfig)) != NPI_SUCCESS)
28903859Sml29623 			goto fail;
28913859Sml29623 		nxgep->mac.rx_config = bconfig;
28923859Sml29623 
28933859Sml29623 		/* Always enable comparison of mac unique address */
28943859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
28953859Sml29623 					!= NPI_SUCCESS)
28963859Sml29623 			goto fail;
28973859Sml29623 	}
28983859Sml29623 
28993859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
29003859Sml29623 			portn));
29013859Sml29623 
29023859Sml29623 	return (NXGE_OK);
29033859Sml29623 
29043859Sml29623 fail:
29053859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
29063859Sml29623 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
29073859Sml29623 				portn));
29083859Sml29623 
29093859Sml29623 	return (NXGE_ERROR | rs);
29103859Sml29623 }
29113859Sml29623 
29123859Sml29623 /* Enable TXMAC */
29133859Sml29623 
29143859Sml29623 nxge_status_t
29153859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
29163859Sml29623 {
29173859Sml29623 	npi_handle_t	handle;
29183859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
29193859Sml29623 	nxge_status_t	status = NXGE_OK;
29203859Sml29623 
29213859Sml29623 	handle = nxgep->npi_handle;
29223859Sml29623 
29233859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
29243859Sml29623 			nxgep->mac.portnum));
29253859Sml29623 
29263859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
29273859Sml29623 		goto fail;
29283859Sml29623 
29293859Sml29623 	/* based on speed */
29303859Sml29623 	nxgep->msg_min = ETHERMIN;
29313859Sml29623 
29323859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
29333859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
29343859Sml29623 						CFG_XMAC_TX)) != NPI_SUCCESS)
29353859Sml29623 			goto fail;
29363859Sml29623 	} else {
29373859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
29383859Sml29623 						CFG_BMAC_TX)) != NPI_SUCCESS)
29393859Sml29623 			goto fail;
29403859Sml29623 	}
29413859Sml29623 
29423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
29433859Sml29623 			nxgep->mac.portnum));
29443859Sml29623 
29453859Sml29623 	return (NXGE_OK);
29463859Sml29623 fail:
29473859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
29483859Sml29623 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
29493859Sml29623 			nxgep->mac.portnum));
29503859Sml29623 	if (rs != NPI_SUCCESS)
29513859Sml29623 		return (NXGE_ERROR | rs);
29523859Sml29623 	else
29533859Sml29623 		return (status);
29543859Sml29623 }
29553859Sml29623 
29563859Sml29623 /* Disable TXMAC */
29573859Sml29623 
29583859Sml29623 nxge_status_t
29593859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
29603859Sml29623 {
29613859Sml29623 	npi_handle_t	handle;
29623859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
29633859Sml29623 
29646495Sspeer 	if (isLDOMguest(nxgep))
29656495Sspeer 		return (NXGE_OK);
29666495Sspeer 
29673859Sml29623 	handle = nxgep->npi_handle;
29683859Sml29623 
29693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
29703859Sml29623 			nxgep->mac.portnum));
29713859Sml29623 
29723859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
29733859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
29743859Sml29623 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
29753859Sml29623 			goto fail;
29763859Sml29623 	} else {
29773859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
29783859Sml29623 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
29793859Sml29623 			goto fail;
29803859Sml29623 	}
29813859Sml29623 
29823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
29833859Sml29623 			nxgep->mac.portnum));
29843859Sml29623 	return (NXGE_OK);
29853859Sml29623 fail:
29863859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
29873859Sml29623 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
29883859Sml29623 			nxgep->mac.portnum));
29893859Sml29623 	return (NXGE_ERROR | rs);
29903859Sml29623 }
29913859Sml29623 
29923859Sml29623 /* Enable RXMAC */
29933859Sml29623 
29943859Sml29623 nxge_status_t
29953859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
29963859Sml29623 {
29973859Sml29623 	npi_handle_t	handle;
29983859Sml29623 	uint8_t 	portn;
29993859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
30003859Sml29623 	nxge_status_t	status = NXGE_OK;
30013859Sml29623 
30026495Sspeer 	/* This is a service-domain-only activity. */
30036495Sspeer 	if (isLDOMguest(nxgep))
30046495Sspeer 		return (status);
30056495Sspeer 
30063859Sml29623 	handle = nxgep->npi_handle;
30073859Sml29623 	portn = nxgep->mac.portnum;
30083859Sml29623 
30093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
30103859Sml29623 			portn));
30113859Sml29623 
30123859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
30133859Sml29623 		goto fail;
30143859Sml29623 
30153859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
30163859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
30176495Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
30183859Sml29623 			goto fail;
30193859Sml29623 	} else {
30203859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
30216495Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
30223859Sml29623 			goto fail;
30233859Sml29623 	}
30243859Sml29623 
30256495Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30266495Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
30273859Sml29623 
30283859Sml29623 	return (NXGE_OK);
30293859Sml29623 fail:
30303859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
30316495Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
30323859Sml29623 
30333859Sml29623 	if (rs != NPI_SUCCESS)
30343859Sml29623 		return (NXGE_ERROR | rs);
30353859Sml29623 	else
30363859Sml29623 		return (status);
30373859Sml29623 }
30383859Sml29623 
30393859Sml29623 /* Disable RXMAC */
30403859Sml29623 
30413859Sml29623 nxge_status_t
30423859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
30433859Sml29623 {
30443859Sml29623 	npi_handle_t	handle;
30453859Sml29623 	uint8_t		portn;
30463859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
30473859Sml29623 
30486495Sspeer 	/* If we are a guest domain driver, don't bother. */
30496495Sspeer 	if (isLDOMguest(nxgep))
30506495Sspeer 		return (NXGE_OK);
30516495Sspeer 
30523859Sml29623 	handle = nxgep->npi_handle;
30533859Sml29623 	portn = nxgep->mac.portnum;
30543859Sml29623 
30553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
30563859Sml29623 			portn));
30573859Sml29623 
30583859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
30593859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
30603859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
30613859Sml29623 			goto fail;
30623859Sml29623 	} else {
30633859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
30643859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
30653859Sml29623 			goto fail;
30663859Sml29623 	}
30673859Sml29623 
30683859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
30693859Sml29623 			portn));
30703859Sml29623 	return (NXGE_OK);
30713859Sml29623 fail:
30723859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
30733859Sml29623 			"nxgep_rx_mac_disable: ",
30743859Sml29623 			"Failed to disable port<%d> RxMAC",
30753859Sml29623 			portn));
30763859Sml29623 
30773859Sml29623 	return (NXGE_ERROR | rs);
30783859Sml29623 }
30793859Sml29623 
30803859Sml29623 /* Reset TXMAC */
30813859Sml29623 
30823859Sml29623 nxge_status_t
30833859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
30843859Sml29623 {
30853859Sml29623 	npi_handle_t	handle;
30863859Sml29623 	uint8_t		portn;
30873859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
30883859Sml29623 
30893859Sml29623 	handle = nxgep->npi_handle;
30903859Sml29623 	portn = nxgep->mac.portnum;
30913859Sml29623 
30923859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
30933859Sml29623 			portn));
30943859Sml29623 
30953859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
30963859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
30973859Sml29623 		    != NPI_SUCCESS)
30983859Sml29623 			goto fail;
30993859Sml29623 	} else {
31003859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
31013859Sml29623 					!= NPI_SUCCESS)
31023859Sml29623 			goto fail;
31033859Sml29623 	}
31043859Sml29623 
31053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
31063859Sml29623 			portn));
31073859Sml29623 
31083859Sml29623 	return (NXGE_OK);
31093859Sml29623 fail:
31103859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
31113859Sml29623 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
31123859Sml29623 			portn));
31133859Sml29623 
31143859Sml29623 	return (NXGE_ERROR | rs);
31153859Sml29623 }
31163859Sml29623 
31173859Sml29623 /* Reset RXMAC */
31183859Sml29623 
31193859Sml29623 nxge_status_t
31203859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
31213859Sml29623 {
31223859Sml29623 	npi_handle_t	handle;
31233859Sml29623 	uint8_t		portn;
31243859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
31253859Sml29623 
31263859Sml29623 	handle = nxgep->npi_handle;
31273859Sml29623 	portn = nxgep->mac.portnum;
31283859Sml29623 
31293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
31303859Sml29623 			portn));
31313859Sml29623 
31323859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
31333859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
31343859Sml29623 		    != NPI_SUCCESS)
31353859Sml29623 		goto fail;
31363859Sml29623 	} else {
31373859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
31383859Sml29623 					!= NPI_SUCCESS)
31393859Sml29623 		goto fail;
31403859Sml29623 	}
31413859Sml29623 
31423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
31433859Sml29623 			portn));
31443859Sml29623 
31453859Sml29623 	return (NXGE_OK);
31463859Sml29623 fail:
31473859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
31483859Sml29623 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
31493859Sml29623 			portn));
31503859Sml29623 	return (NXGE_ERROR | rs);
31513859Sml29623 }
31523859Sml29623 
31534732Sdavemq /* 10G fiber link interrupt start routine */
31544732Sdavemq 
31554732Sdavemq static nxge_status_t
31564732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
31574732Sdavemq {
31584732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
31594732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
31604732Sdavemq 
31614732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
31624732Sdavemq 
31634732Sdavemq 	if (rs != NPI_SUCCESS)
31644732Sdavemq 		return (NXGE_ERROR | rs);
31654732Sdavemq 	else
31664732Sdavemq 		return (NXGE_OK);
31674732Sdavemq }
31684732Sdavemq 
31694732Sdavemq /* 10G fiber link interrupt stop routine */
31704732Sdavemq 
31714732Sdavemq static nxge_status_t
31724732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
31734732Sdavemq {
31744732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
31754732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
31764732Sdavemq 
31774732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
31784732Sdavemq 
31794732Sdavemq 	if (rs != NPI_SUCCESS)
31804732Sdavemq 		return (NXGE_ERROR | rs);
31814732Sdavemq 	else
31824732Sdavemq 		return (NXGE_OK);
31834732Sdavemq }
31844732Sdavemq 
31854732Sdavemq /* 1G fiber link interrupt start routine */
31864732Sdavemq 
31874732Sdavemq static nxge_status_t
31884732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
31894732Sdavemq {
31904732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
31914732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
31924732Sdavemq 
31934732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
31944732Sdavemq 	if (rs != NPI_SUCCESS)
31954732Sdavemq 		return (NXGE_ERROR | rs);
31964732Sdavemq 	else
31974732Sdavemq 		return (NXGE_OK);
31984732Sdavemq }
31994732Sdavemq 
32004732Sdavemq /* 1G fiber link interrupt stop routine */
32014732Sdavemq 
32024732Sdavemq static nxge_status_t
32034732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
32044732Sdavemq {
32054732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
32064732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
32074732Sdavemq 
32084732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
32094732Sdavemq 
32104732Sdavemq 	if (rs != NPI_SUCCESS)
32114732Sdavemq 		return (NXGE_ERROR | rs);
32124732Sdavemq 	else
32134732Sdavemq 		return (NXGE_OK);
32144732Sdavemq }
32154732Sdavemq 
32164732Sdavemq /* 1G copper link interrupt start routine */
32174732Sdavemq 
32184732Sdavemq static nxge_status_t
32194732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
32204732Sdavemq {
32214732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
32224732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
32234732Sdavemq 
32244732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
32255203Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
32264732Sdavemq 
32274732Sdavemq 	if (rs != NPI_SUCCESS)
32284732Sdavemq 		return (NXGE_ERROR | rs);
32294732Sdavemq 	else
32304732Sdavemq 		return (NXGE_OK);
32314732Sdavemq }
32324732Sdavemq 
32334732Sdavemq /* 1G copper link interrupt stop routine */
32344732Sdavemq 
32354732Sdavemq static nxge_status_t
32364732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
32374732Sdavemq {
32384732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
32394732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
32404732Sdavemq 
32414732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
32424732Sdavemq 
32434732Sdavemq 	if (rs != NPI_SUCCESS)
32444732Sdavemq 		return (NXGE_ERROR | rs);
32454732Sdavemq 	else
32464732Sdavemq 		return (NXGE_OK);
32474732Sdavemq }
32484732Sdavemq 
32494732Sdavemq /* Enable/Disable Link Status change interrupt */
32503859Sml29623 
32513859Sml29623 nxge_status_t
32523859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
32533859Sml29623 {
32544732Sdavemq 	uint8_t		portn;
32554732Sdavemq 	nxge_status_t	status = NXGE_OK;
32563859Sml29623 
32573859Sml29623 	portn = nxgep->mac.portnum;
32583859Sml29623 
32593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
32604732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
32614732Sdavemq 		return (NXGE_OK);
32624732Sdavemq 
32634732Sdavemq 	if (enable == LINK_INTR_START)
32644732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
32654732Sdavemq 	else if (enable == LINK_INTR_STOP)
32664732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
32674732Sdavemq 	if (status != NXGE_OK)
32684732Sdavemq 		goto fail;
32693859Sml29623 
32703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
32713859Sml29623 
32723859Sml29623 	return (NXGE_OK);
32733859Sml29623 fail:
32743859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32753859Sml29623 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
32763859Sml29623 			portn));
32773859Sml29623 
32784732Sdavemq 	return (status);
32793859Sml29623 }
32803859Sml29623 
32813859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
32823859Sml29623 
32833859Sml29623 nxge_status_t
32843859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
32853859Sml29623 {
32863859Sml29623 	p_nxge_param_t	param_arr;
32873859Sml29623 	p_nxge_stats_t	statsp;
32883859Sml29623 	uint8_t		xcvr_portn;
32893859Sml29623 	p_mii_regs_t	mii_regs;
32903859Sml29623 	mii_bmcr_t	bmcr;
32913859Sml29623 	mii_bmsr_t	bmsr;
32923859Sml29623 	mii_anar_t	anar;
32933859Sml29623 	mii_gcr_t	gcr;
32943859Sml29623 	mii_esr_t	esr;
32953859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
32963859Sml29623 	int		status = NXGE_OK;
32973859Sml29623 
32983859Sml29623 	uint_t delay;
32993859Sml29623 
33003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
33013859Sml29623 
33023859Sml29623 	param_arr = nxgep->param_arr;
33033859Sml29623 	statsp = nxgep->statsp;
33043859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
33053859Sml29623 
33063859Sml29623 	mii_regs = NULL;
33073859Sml29623 
33083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
33093859Sml29623 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
33103859Sml29623 
33113859Sml29623 	/*
33125196Ssbehera 	 * The mif phy mode may be connected to either a copper link
33135196Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
33145196Ssbehera 	 * configuration if it is hard-wired to fiber link.
33155196Ssbehera 	 */
33165196Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
33175196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
33185196Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
33195196Ssbehera 	}
33205196Ssbehera 
33215196Ssbehera 	/*
33223859Sml29623 	 * Reset the transceiver.
33233859Sml29623 	 */
33243859Sml29623 	delay = 0;
33253859Sml29623 	bmcr.value = 0;
33263859Sml29623 	bmcr.bits.reset = 1;
33273859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
33285125Sjoycey #if defined(__i386)
33295125Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
33305125Sjoycey #else
33313859Sml29623 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
33325125Sjoycey #endif
33333859Sml29623 		goto fail;
33343859Sml29623 	do {
33353859Sml29623 		drv_usecwait(500);
33363859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
33375125Sjoycey #if defined(__i386)
33385125Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
33395125Sjoycey #else
33403859Sml29623 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
33415125Sjoycey #endif
33423859Sml29623 				!= NXGE_OK)
33433859Sml29623 			goto fail;
33443859Sml29623 		delay++;
33453859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
33463859Sml29623 	if (delay == 1000) {
33473859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
33483859Sml29623 		goto fail;
33493859Sml29623 	}
33503859Sml29623 
33513859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
33525125Sjoycey #if defined(__i386)
33535125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
33545125Sjoycey #else
33553859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
33565125Sjoycey #endif
33573859Sml29623 			&bmsr.value)) != NXGE_OK)
33583859Sml29623 		goto fail;
33593859Sml29623 
33603859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
33613859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
33623859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
33633859Sml29623 	param_arr[param_anar_100hdx].value = 0;
33643859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
33653859Sml29623 	param_arr[param_anar_10hdx].value = 0;
33663859Sml29623 
33673859Sml29623 	/*
33683859Sml29623 	 * Initialize the xcvr statistics.
33693859Sml29623 	 */
33703859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
33713859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
33723859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
33733859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
33743859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
33753859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
33763859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
33773859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
33783859Sml29623 
33793859Sml29623 	/*
33803859Sml29623 	 * Initialise the xcvr advertised capability statistics.
33813859Sml29623 	 */
33823859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
33833859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
33843859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
33853859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
33863859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
33873859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
33883859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
33893859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
33903859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
33913859Sml29623 					param_arr[param_anar_asmpause].value;
33923859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
33933859Sml29623 
33943859Sml29623 
33953859Sml29623 	/*
33963859Sml29623 	 * Check for extended status just in case we're
33973859Sml29623 	 * running a Gigibit phy.
33983859Sml29623 	 */
33993859Sml29623 	if (bmsr.bits.extend_status) {
34003859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
34015125Sjoycey #if defined(__i386)
34025125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
34035125Sjoycey #else
34043859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
34055125Sjoycey #endif
34063859Sml29623 				!= NXGE_OK)
34073859Sml29623 			goto fail;
34083859Sml29623 		param_arr[param_anar_1000fdx].value &=
34093859Sml29623 					esr.bits.link_1000fdx;
34103859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
34113859Sml29623 
34123859Sml29623 		statsp->mac_stats.cap_1000fdx =
34133859Sml29623 			(esr.bits.link_1000Xfdx ||
34143859Sml29623 				esr.bits.link_1000fdx);
34153859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
34163859Sml29623 	} else {
34173859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
34183859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
34193859Sml29623 	}
34203859Sml29623 
34213859Sml29623 	/*
34223859Sml29623 	 * Initialize 1G Statistics once the capability is established.
34233859Sml29623 	 */
34243859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
34253859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
34263859Sml29623 
34273859Sml29623 	/*
34283859Sml29623 	 * Initialise the link statistics.
34293859Sml29623 	 */
34303859Sml29623 	statsp->mac_stats.link_T4 = 0;
34313859Sml29623 	statsp->mac_stats.link_asmpause = 0;
34323859Sml29623 	statsp->mac_stats.link_pause = 0;
34333859Sml29623 	statsp->mac_stats.link_speed = 0;
34343859Sml29623 	statsp->mac_stats.link_duplex = 0;
34353859Sml29623 	statsp->mac_stats.link_up = 0;
34363859Sml29623 
34373859Sml29623 	/*
34383859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
34393859Sml29623 	 */
34403859Sml29623 	bmcr.value = 0;
34413859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
34425125Sjoycey #if defined(__i386)
34435125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
34445125Sjoycey #else
34453859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
34465125Sjoycey #endif
34473859Sml29623 		goto fail;
34483859Sml29623 
34493859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
34503859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
34513859Sml29623 		bmcr.bits.loopback = 1;
34523859Sml29623 		bmcr.bits.enable_autoneg = 0;
34533859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
34543859Sml29623 			bmcr.bits.speed_1000_sel = 1;
34553859Sml29623 		bmcr.bits.duplex_mode = 1;
34563859Sml29623 		param_arr[param_autoneg].value = 0;
34573859Sml29623 	} else {
34583859Sml29623 		bmcr.bits.loopback = 0;
34593859Sml29623 	}
34603859Sml29623 
34613859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
34623859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
34633859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
34643859Sml29623 		param_arr[param_autoneg].value = 0;
34653859Sml29623 		bcm5464r_aux.value = 0;
34663859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
34673859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
34683859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
34693859Sml29623 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
34703859Sml29623 				!= NXGE_OK)
34713859Sml29623 			goto fail;
34723859Sml29623 	}
34733859Sml29623 
34743859Sml29623 	if (param_arr[param_autoneg].value) {
34753859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
34763859Sml29623 				"Restarting Auto-negotiation."));
34773859Sml29623 		/*
34783859Sml29623 		 * Setup our Auto-negotiation advertisement register.
34793859Sml29623 		 */
34803859Sml29623 		anar.value = 0;
34813859Sml29623 		anar.bits.selector = 1;
34823859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
34833859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
34843859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
34853859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
34863859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
34873859Sml29623 		anar.bits.cap_asmpause = 0;
34883859Sml29623 		anar.bits.cap_pause = 0;
34893859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
34903859Sml29623 			param_arr[param_anar_100fdx].value ||
34913859Sml29623 			param_arr[param_anar_10fdx].value) {
34923859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
34933859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
34943859Sml29623 		}
34953859Sml29623 
34963859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
34975125Sjoycey #if defined(__i386)
34985125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
34995125Sjoycey #else
35003859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
35015125Sjoycey #endif
35023859Sml29623 				!= NXGE_OK)
35033859Sml29623 			goto fail;
35043859Sml29623 		if (bmsr.bits.extend_status) {
35053859Sml29623 			gcr.value = 0;
35063859Sml29623 			gcr.bits.ms_mode_en =
35073859Sml29623 				param_arr[param_master_cfg_enable].value;
35083859Sml29623 			gcr.bits.master =
35093859Sml29623 				param_arr[param_master_cfg_value].value;
35103859Sml29623 			gcr.bits.link_1000fdx =
35113859Sml29623 				param_arr[param_anar_1000fdx].value;
35123859Sml29623 			gcr.bits.link_1000hdx =
35133859Sml29623 				param_arr[param_anar_1000hdx].value;
35143859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
35155125Sjoycey #if defined(__i386)
35165125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
35175125Sjoycey #else
35183859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
35195125Sjoycey #endif
35203859Sml29623 				!= NXGE_OK)
35213859Sml29623 				goto fail;
35223859Sml29623 		}
35233859Sml29623 
35243859Sml29623 		bmcr.bits.enable_autoneg = 1;
35253859Sml29623 		bmcr.bits.restart_autoneg = 1;
35263859Sml29623 
35273859Sml29623 	} else {
35283859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
35293859Sml29623 		bmcr.bits.speed_1000_sel =
35303859Sml29623 			param_arr[param_anar_1000fdx].value |
35313859Sml29623 				param_arr[param_anar_1000hdx].value;
35323859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
35333859Sml29623 			(param_arr[param_anar_100fdx].value |
35343859Sml29623 				param_arr[param_anar_100hdx].value);
35353859Sml29623 		if (bmcr.bits.speed_1000_sel) {
35363859Sml29623 			statsp->mac_stats.link_speed = 1000;
35373859Sml29623 			gcr.value = 0;
35383859Sml29623 			gcr.bits.ms_mode_en =
35393859Sml29623 				param_arr[param_master_cfg_enable].value;
35403859Sml29623 			gcr.bits.master =
35413859Sml29623 				param_arr[param_master_cfg_value].value;
35423859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
35435125Sjoycey #if defined(__i386)
35445125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
35455125Sjoycey #else
35463859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr),
35475125Sjoycey #endif
35483859Sml29623 				gcr.value))
35493859Sml29623 				!= NXGE_OK)
35503859Sml29623 				goto fail;
35513859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
35523859Sml29623 				bmcr.bits.duplex_mode = 1;
35533859Sml29623 				statsp->mac_stats.link_duplex = 2;
35543859Sml29623 			} else
35553859Sml29623 				statsp->mac_stats.link_duplex = 1;
35563859Sml29623 		} else if (bmcr.bits.speed_sel) {
35573859Sml29623 			statsp->mac_stats.link_speed = 100;
35583859Sml29623 			if (param_arr[param_anar_100fdx].value) {
35593859Sml29623 				bmcr.bits.duplex_mode = 1;
35603859Sml29623 				statsp->mac_stats.link_duplex = 2;
35613859Sml29623 			} else
35623859Sml29623 				statsp->mac_stats.link_duplex = 1;
35633859Sml29623 		} else {
35643859Sml29623 			statsp->mac_stats.link_speed = 10;
35653859Sml29623 			if (param_arr[param_anar_10fdx].value) {
35663859Sml29623 				bmcr.bits.duplex_mode = 1;
35673859Sml29623 				statsp->mac_stats.link_duplex = 2;
35683859Sml29623 			} else
35693859Sml29623 				statsp->mac_stats.link_duplex = 1;
35703859Sml29623 		}
35713859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
35723859Sml29623 			statsp->mac_stats.link_asmpause =
35733859Sml29623 						statsp->mac_stats.cap_asmpause;
35743859Sml29623 			statsp->mac_stats.link_pause =
35753859Sml29623 						statsp->mac_stats.cap_pause;
35763859Sml29623 		}
35773859Sml29623 
35783859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
35793859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
35803859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
35813859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
35823859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
35833859Sml29623 				gcr.value = 0;
35843859Sml29623 				gcr.bits.ms_mode_en = 1;
35853859Sml29623 				gcr.bits.master = 1;
35863859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
35875125Sjoycey #if defined(__i386)
35885125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
35895125Sjoycey #else
35903859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gcr),
35915125Sjoycey #endif
35923859Sml29623 					gcr.value))
35933859Sml29623 					!= NXGE_OK)
35943859Sml29623 					goto fail;
35953859Sml29623 				bmcr.value = 0;
35963859Sml29623 				bmcr.bits.speed_1000_sel = 1;
35973859Sml29623 				statsp->mac_stats.link_speed = 1000;
35983859Sml29623 			} else if (statsp->port_stats.lb_mode
35993859Sml29623 			    == nxge_lb_ext100) {
36003859Sml29623 				/* BCM5464R 100mbps external loopback mode */
36013859Sml29623 				bmcr.value = 0;
36023859Sml29623 				bmcr.bits.speed_sel = 1;
36033859Sml29623 				bmcr.bits.duplex_mode = 1;
36043859Sml29623 				statsp->mac_stats.link_speed = 100;
36053859Sml29623 			} else if (statsp->port_stats.lb_mode
36063859Sml29623 			    == nxge_lb_ext10) {
36073859Sml29623 				/* BCM5464R 10mbps external loopback mode */
36083859Sml29623 				bmcr.value = 0;
36093859Sml29623 				bmcr.bits.duplex_mode = 1;
36103859Sml29623 				statsp->mac_stats.link_speed = 10;
36113859Sml29623 			}
36123859Sml29623 		}
36133859Sml29623 	}
36143859Sml29623 
36153859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
36165125Sjoycey #if defined(__i386)
36175125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
36185125Sjoycey #else
36193859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
36205125Sjoycey #endif
36213859Sml29623 			bmcr.value)) != NXGE_OK)
36223859Sml29623 		goto fail;
36233859Sml29623 
36243859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
36255125Sjoycey #if defined(__i386)
36265125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
36275125Sjoycey #else
36283859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
36295125Sjoycey #endif
36303859Sml29623 		goto fail;
36313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
36323859Sml29623 
36333859Sml29623 	/*
36343859Sml29623 	 * Initialize the xcvr status kept in the context structure.
36353859Sml29623 	 */
36363859Sml29623 	nxgep->soft_bmsr.value = 0;
36373859Sml29623 
36383859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
36395125Sjoycey #if defined(__i386)
36405125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
36415125Sjoycey #else
36423859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
36435125Sjoycey #endif
36443859Sml29623 			&nxgep->bmsr.value)) != NXGE_OK)
36453859Sml29623 		goto fail;
36463859Sml29623 
36473859Sml29623 	statsp->mac_stats.xcvr_inits++;
36483859Sml29623 	nxgep->bmsr.value = 0;
36493859Sml29623 
36503859Sml29623 fail:
36513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36523859Sml29623 			"<== nxge_mii_xcvr_init status 0x%x", status));
36533859Sml29623 	return (status);
36543859Sml29623 }
36553859Sml29623 
36565196Ssbehera nxge_status_t
36575196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
36585196Ssbehera {
36595196Ssbehera 	p_nxge_param_t	param_arr;
36605196Ssbehera 	p_nxge_stats_t	statsp;
36615196Ssbehera 	uint8_t		xcvr_portn;
36625196Ssbehera 	p_mii_regs_t	mii_regs;
36635196Ssbehera 	mii_bmcr_t	bmcr;
36645196Ssbehera 	mii_bmsr_t	bmsr;
36655196Ssbehera 	mii_gcr_t	gcr;
36665196Ssbehera 	mii_esr_t	esr;
36675196Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
36685196Ssbehera 	int		status = NXGE_OK;
36695196Ssbehera 
36705196Ssbehera 	uint_t delay;
36715196Ssbehera 
36725196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
36735196Ssbehera 
36745196Ssbehera 	param_arr = nxgep->param_arr;
36755196Ssbehera 	statsp = nxgep->statsp;
36765196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
36775196Ssbehera 
36785196Ssbehera 	mii_regs = NULL;
36795196Ssbehera 
36805196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36815196Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
36825196Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
36835196Ssbehera 
36845196Ssbehera 	/*
36855196Ssbehera 	 * Reset the transceiver.
36865196Ssbehera 	 */
36875196Ssbehera 	delay = 0;
36885196Ssbehera 	bmcr.value = 0;
36895196Ssbehera 	bmcr.bits.reset = 1;
36905196Ssbehera 
36915196Ssbehera #if defined(__i386)
36925196Ssbehera 
36935196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
36945196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
36955196Ssbehera 		goto fail;
36965196Ssbehera #else
36975196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
36985196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
36995196Ssbehera 		goto fail;
37005196Ssbehera #endif
37015196Ssbehera 	do {
37025196Ssbehera 		drv_usecwait(500);
37035196Ssbehera #if defined(__i386)
37045196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
37055196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
37065196Ssbehera 		    != NXGE_OK)
37075196Ssbehera 			goto fail;
37085196Ssbehera #else
37095196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
37105196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
37115196Ssbehera 		    != NXGE_OK)
37125196Ssbehera 			goto fail;
37135196Ssbehera #endif
37145196Ssbehera 		delay++;
37155196Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
37165196Ssbehera 	if (delay == 1000) {
37175196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
37185196Ssbehera 		goto fail;
37195196Ssbehera 	}
37205196Ssbehera 
37215196Ssbehera #if defined(__i386)
37225196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
37235196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
37245196Ssbehera 		goto fail;
37255196Ssbehera #else
37265196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
37275196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
37285196Ssbehera 		goto fail;
37295196Ssbehera #endif
37305196Ssbehera 
37315196Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
37325196Ssbehera 	param_arr[param_anar_100T4].value = 0;
37335196Ssbehera 	param_arr[param_anar_100fdx].value = 0;
37345196Ssbehera 	param_arr[param_anar_100hdx].value = 0;
37355196Ssbehera 	param_arr[param_anar_10fdx].value = 0;
37365196Ssbehera 	param_arr[param_anar_10hdx].value = 0;
37375196Ssbehera 
37385196Ssbehera 	/*
37395196Ssbehera 	 * Initialize the xcvr statistics.
37405196Ssbehera 	 */
37415196Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
37425196Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
37435196Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
37445196Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
37455196Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
37465196Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
37475196Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
37485196Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
37495196Ssbehera 
37505196Ssbehera 	/*
37515196Ssbehera 	 * Initialize the xcvr advertised capability statistics.
37525196Ssbehera 	 */
37535196Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
37545196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
37555196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
37565196Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
37575196Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
37585196Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
37595196Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
37605196Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
37615196Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
37625196Ssbehera 	    param_arr[param_anar_asmpause].value;
37635196Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
37645196Ssbehera 
37655196Ssbehera 	/*
37665196Ssbehera 	 * Check for extended status just in case we're
37675196Ssbehera 	 * running a Gigibit phy.
37685196Ssbehera 	 */
37695196Ssbehera 	if (bmsr.bits.extend_status) {
37705196Ssbehera #if defined(__i386)
37715196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
37725196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
37735196Ssbehera 		    NXGE_OK)
37745196Ssbehera 			goto fail;
37755196Ssbehera #else
37765196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
37775196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
37785196Ssbehera 		    NXGE_OK)
37795196Ssbehera 			goto fail;
37805196Ssbehera #endif
37815196Ssbehera 		param_arr[param_anar_1000fdx].value &=
37825196Ssbehera 		    esr.bits.link_1000fdx;
37835196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
37845196Ssbehera 
37855196Ssbehera 		statsp->mac_stats.cap_1000fdx =
37865196Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
37875196Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
37885196Ssbehera 	} else {
37895196Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
37905196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
37915196Ssbehera 	}
37925196Ssbehera 
37935196Ssbehera 	/*
37945196Ssbehera 	 * Initialize 1G Statistics once the capability is established.
37955196Ssbehera 	 */
37965196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
37975196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
37985196Ssbehera 
37995196Ssbehera 	/*
38005196Ssbehera 	 * Initialize the link statistics.
38015196Ssbehera 	 */
38025196Ssbehera 	statsp->mac_stats.link_T4 = 0;
38035196Ssbehera 	statsp->mac_stats.link_asmpause = 0;
38045196Ssbehera 	statsp->mac_stats.link_pause = 0;
38055196Ssbehera 	statsp->mac_stats.link_speed = 0;
38065196Ssbehera 	statsp->mac_stats.link_duplex = 0;
38075196Ssbehera 	statsp->mac_stats.link_up = 0;
38085196Ssbehera 
38095196Ssbehera 	/*
38105196Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
38115196Ssbehera 	 */
38125196Ssbehera 	bmcr.value = 0;
38135196Ssbehera #if defined(__i386)
38145196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38155196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
38165196Ssbehera 		goto fail;
38175196Ssbehera #else
38185196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38195196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
38205196Ssbehera 		goto fail;
38215196Ssbehera #endif
38225196Ssbehera 
38235196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
38245196Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
38255196Ssbehera 		bmcr.bits.loopback = 1;
38265196Ssbehera 		bmcr.bits.enable_autoneg = 0;
38275196Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
38285196Ssbehera 			bmcr.bits.speed_1000_sel = 1;
38295196Ssbehera 		bmcr.bits.duplex_mode = 1;
38305196Ssbehera 		param_arr[param_autoneg].value = 0;
38315196Ssbehera 	} else {
38325196Ssbehera 		bmcr.bits.loopback = 0;
38335196Ssbehera 	}
38345196Ssbehera 
38355196Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
38365196Ssbehera 		param_arr[param_autoneg].value = 0;
38375196Ssbehera 		bcm5464r_aux.value = 0;
38385196Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
38395196Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
38405196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
38415196Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
38425196Ssbehera 			goto fail;
38435196Ssbehera 	}
38445196Ssbehera 
38455196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
38465196Ssbehera 	bmcr.bits.speed_1000_sel = 1;
38475196Ssbehera 	bmcr.bits.speed_sel = 0;
38485196Ssbehera 	bmcr.bits.duplex_mode = 1;
38495196Ssbehera 	statsp->mac_stats.link_speed = 1000;
38505196Ssbehera 	statsp->mac_stats.link_duplex = 2;
38515196Ssbehera 
38525196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
38535196Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
38545196Ssbehera 		gcr.value = 0;
38555196Ssbehera 		gcr.bits.ms_mode_en = 1;
38565196Ssbehera 		gcr.bits.master = 1;
38575196Ssbehera #if defined(__i386)
38585196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
38595196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
38605196Ssbehera 		    gcr.value)) != NXGE_OK)
38615196Ssbehera 			goto fail;
38625196Ssbehera #else
38635196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
38645196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
38655196Ssbehera 		    gcr.value)) != NXGE_OK)
38665196Ssbehera 			goto fail;
38675196Ssbehera #endif
38685196Ssbehera 		bmcr.value = 0;
38695196Ssbehera 		bmcr.bits.speed_1000_sel = 1;
38705196Ssbehera 		statsp->mac_stats.link_speed = 1000;
38715196Ssbehera 	}
38725196Ssbehera 
38735196Ssbehera #if defined(__i386)
38745196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38755196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
38765196Ssbehera 	    bmcr.value)) != NXGE_OK)
38775196Ssbehera 		goto fail;
38785196Ssbehera #else
38795196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38805196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
38815196Ssbehera 	    bmcr.value)) != NXGE_OK)
38825196Ssbehera 		goto fail;
38835196Ssbehera #endif
38845196Ssbehera 
38855196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38865196Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
38875196Ssbehera 	    bmcr.value));
38885196Ssbehera 
38895196Ssbehera #if defined(__i386)
38905196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
38915196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
38925196Ssbehera 		goto fail;
38935196Ssbehera #else
38945196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
38955196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
38965196Ssbehera 		goto fail;
38975196Ssbehera #endif
38985196Ssbehera 
38995196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39005196Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
39015196Ssbehera 
39025196Ssbehera 	/*
39035196Ssbehera 	 * Initialize the xcvr status kept in the context structure.
39045196Ssbehera 	 */
39055196Ssbehera 	nxgep->soft_bmsr.value = 0;
39065196Ssbehera #if defined(__i386)
39075196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39085196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
39095196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
39105196Ssbehera 		goto fail;
39115196Ssbehera #else
39125196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39135196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
39145196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
39155196Ssbehera 		goto fail;
39165196Ssbehera #endif
39175196Ssbehera 
39185196Ssbehera 	statsp->mac_stats.xcvr_inits++;
39195196Ssbehera 	nxgep->bmsr.value = 0;
39205196Ssbehera 
39215196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39225196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
39235196Ssbehera 	return (status);
39245196Ssbehera 
39255196Ssbehera fail:
39265196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
39275196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
39285196Ssbehera 	return (status);
39295196Ssbehera }
39305196Ssbehera 
39313859Sml29623 /* Read from a MII compliant register */
39323859Sml29623 
39333859Sml29623 nxge_status_t
39343859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
39353859Sml29623 		uint16_t *value)
39363859Sml29623 {
39373859Sml29623 	npi_status_t rs = NPI_SUCCESS;
39383859Sml29623 
39393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
39403859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
39413859Sml29623 
39426075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
39433859Sml29623 
39445196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
39455196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
39463859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
39473859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
39483859Sml29623 			goto fail;
39494977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
39504977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
39513859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
39523859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
39533859Sml29623 			goto fail;
39543859Sml29623 	} else
39553859Sml29623 		goto fail;
39563859Sml29623 
39576075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
39583859Sml29623 
39593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
39603859Sml29623 			"xcvr_reg<%d> value=0x%x",
39613859Sml29623 			xcvr_portn, xcvr_reg, *value));
39623859Sml29623 	return (NXGE_OK);
39633859Sml29623 fail:
39646075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
39653859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
39663859Sml29623 			"nxge_mii_read: Failed to read mii on xcvr %d",
39673859Sml29623 			xcvr_portn));
39683859Sml29623 
39693859Sml29623 	return (NXGE_ERROR | rs);
39703859Sml29623 }
39713859Sml29623 
39723859Sml29623 /* Write to a MII compliant Register */
39733859Sml29623 
39743859Sml29623 nxge_status_t
39753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
39763859Sml29623 		uint16_t value)
39773859Sml29623 {
39783859Sml29623 	npi_status_t rs = NPI_SUCCESS;
39793859Sml29623 
39803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
39813859Sml29623 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
39823859Sml29623 			value));
39833859Sml29623 
39846075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
39853859Sml29623 
39865196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
39875196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
39883859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
39893859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
39903859Sml29623 			goto fail;
39914977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
39924977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
39933859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
39943859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
39953859Sml29623 			goto fail;
39963859Sml29623 	} else
39973859Sml29623 		goto fail;
39983859Sml29623 
39996075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40003859Sml29623 
40013859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
40023859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
40033859Sml29623 	return (NXGE_OK);
40043859Sml29623 fail:
40056075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40063859Sml29623 
40073859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40083859Sml29623 			"nxge_mii_write: Failed to write mii on xcvr %d",
40093859Sml29623 			xcvr_portn));
40103859Sml29623 
40113859Sml29623 	return (NXGE_ERROR | rs);
40123859Sml29623 }
40133859Sml29623 
40143859Sml29623 /* Perform read from Clause45 serdes / transceiver device */
40153859Sml29623 
40163859Sml29623 nxge_status_t
40173859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
40183859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
40193859Sml29623 {
40203859Sml29623 	npi_status_t rs = NPI_SUCCESS;
40213859Sml29623 
40223859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
40233859Sml29623 			xcvr_portn));
40243859Sml29623 
40255780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
40263859Sml29623 
40273859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
40283859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
40293859Sml29623 		goto fail;
40303859Sml29623 
40315780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40323859Sml29623 
40333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
40343859Sml29623 			xcvr_portn));
40353859Sml29623 	return (NXGE_OK);
40363859Sml29623 fail:
40375780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40383859Sml29623 
40393859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40403859Sml29623 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
40413859Sml29623 			xcvr_portn));
40423859Sml29623 
40433859Sml29623 	return (NXGE_ERROR | rs);
40443859Sml29623 }
40453859Sml29623 
40463859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
40473859Sml29623 
40483859Sml29623 nxge_status_t
40493859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
40503859Sml29623 		uint16_t xcvr_reg, uint16_t value)
40513859Sml29623 {
40523859Sml29623 	npi_status_t rs = NPI_SUCCESS;
40533859Sml29623 
40543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
40553859Sml29623 			xcvr_portn));
40563859Sml29623 
40575780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
40583859Sml29623 
40593859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
40603859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
40613859Sml29623 		goto fail;
40623859Sml29623 
40635780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40643859Sml29623 
40653859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
40663859Sml29623 			xcvr_portn));
40673859Sml29623 	return (NXGE_OK);
40683859Sml29623 fail:
40695780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
40703859Sml29623 
40713859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40723859Sml29623 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
40733859Sml29623 			xcvr_portn));
40743859Sml29623 
40753859Sml29623 	return (NXGE_ERROR | rs);
40763859Sml29623 }
40773859Sml29623 
40783859Sml29623 
40793859Sml29623 /* Check MII to see if there is any link status change */
40803859Sml29623 
40813859Sml29623 nxge_status_t
40823859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
40833859Sml29623 		nxge_link_state_t *link_up)
40843859Sml29623 {
40853859Sml29623 	p_nxge_param_t	param_arr;
40863859Sml29623 	p_nxge_stats_t	statsp;
40873859Sml29623 	p_mii_regs_t	mii_regs;
40883859Sml29623 	p_mii_bmsr_t	soft_bmsr;
40893859Sml29623 	mii_anar_t	anar;
40903859Sml29623 	mii_anlpar_t	anlpar;
40913859Sml29623 	mii_anar_t	an_common;
40923859Sml29623 	mii_aner_t	aner;
40933859Sml29623 	mii_gsr_t	gsr;
40943859Sml29623 	nxge_status_t	status = NXGE_OK;
40953859Sml29623 
40963859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
40973859Sml29623 
40983859Sml29623 	mii_regs = NULL;
40993859Sml29623 	param_arr = nxgep->param_arr;
41003859Sml29623 	statsp = nxgep->statsp;
41013859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
41023859Sml29623 	*link_up = LINK_NO_CHANGE;
41033859Sml29623 
41045196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41055196Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
41065196Ssbehera 	    bmsr.value, bmsr_ints.value));
41075196Ssbehera 
41083859Sml29623 	if (bmsr_ints.bits.link_status) {
41095196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41105196Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
41115196Ssbehera 		    bmsr.value, bmsr_ints.value));
41123859Sml29623 		if (bmsr.bits.link_status) {
41133859Sml29623 			soft_bmsr->bits.link_status = 1;
41145196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41155196Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
41165196Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
41173859Sml29623 		} else {
41183859Sml29623 			statsp->mac_stats.link_up = 0;
41193859Sml29623 			soft_bmsr->bits.link_status = 0;
41203859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41213859Sml29623 					"Link down cable problem"));
41223859Sml29623 			*link_up = LINK_IS_DOWN;
41233859Sml29623 		}
41243859Sml29623 	}
41253859Sml29623 
41265196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
41275196Ssbehera 	    param_arr[param_autoneg].value) {
41283859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
41293859Sml29623 			if (bmsr.bits.auto_neg_complete)
41303859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
41313859Sml29623 			else
41323859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
41333859Sml29623 		}
41343859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
41353859Sml29623 			statsp->mac_stats.link_T4 = 0;
41363859Sml29623 			statsp->mac_stats.link_speed = 0;
41373859Sml29623 			statsp->mac_stats.link_duplex = 0;
41383859Sml29623 			statsp->mac_stats.link_asmpause = 0;
41393859Sml29623 			statsp->mac_stats.link_pause = 0;
41403859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
41413859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
41423859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
41433859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
41443859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
41453859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
41463859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
41473859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
41483859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
41493859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
41503859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
41513859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
41523859Sml29623 		}
41533859Sml29623 	} else
41543859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
41553859Sml29623 
41563859Sml29623 	if ((bmsr_ints.bits.link_status ||
41573859Sml29623 		bmsr_ints.bits.auto_neg_complete) &&
41583859Sml29623 		soft_bmsr->bits.link_status &&
41593859Sml29623 		soft_bmsr->bits.auto_neg_complete) {
41603859Sml29623 		statsp->mac_stats.link_up = 1;
41615196Ssbehera 
41625196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41635196Ssbehera 		    "==> nxge_mii_check "
41645196Ssbehera 		    "(auto negotiation complete or link up) "
41655196Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
41665196Ssbehera 		    bmsr.value, bmsr_ints.value));
41675196Ssbehera 
41685196Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
41695196Ssbehera 		    param_arr[param_autoneg].value) {
41703859Sml29623 			if ((status = nxge_mii_read(nxgep,
41713859Sml29623 				statsp->mac_stats.xcvr_portn,
41725125Sjoycey #if defined(__i386)
41735125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
41745125Sjoycey #else
41753859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anar),
41765125Sjoycey #endif
41773859Sml29623 					&anar.value)) != NXGE_OK)
41783859Sml29623 				goto fail;
41793859Sml29623 			if ((status = nxge_mii_read(nxgep,
41803859Sml29623 				statsp->mac_stats.xcvr_portn,
41815125Sjoycey #if defined(__i386)
41825125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
41835125Sjoycey #else
41843859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
41855125Sjoycey #endif
41863859Sml29623 					&anlpar.value)) != NXGE_OK)
41873859Sml29623 				goto fail;
41883859Sml29623 			if ((status = nxge_mii_read(nxgep,
41893859Sml29623 				statsp->mac_stats.xcvr_portn,
41905125Sjoycey #if defined(__i386)
41915125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
41925125Sjoycey #else
41933859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->aner),
41945125Sjoycey #endif
41953859Sml29623 					&aner.value)) != NXGE_OK)
41963859Sml29623 				goto fail;
41973859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
41983859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
41993859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
42003859Sml29623 							anlpar.bits.cap_100fdx;
42013859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
42023859Sml29623 							anlpar.bits.cap_100hdx;
42033859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
42043859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
42053859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
42063859Sml29623 						anlpar.bits.cap_asmpause;
42073859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
42083859Sml29623 			an_common.value = anar.value & anlpar.value;
42093859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
42103859Sml29623 				param_arr[param_anar_1000hdx].value) {
42113859Sml29623 				if ((status = nxge_mii_read(nxgep,
42123859Sml29623 					statsp->mac_stats.xcvr_portn,
42135125Sjoycey #if defined(__i386)
42145125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
42155125Sjoycey #else
42163859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gsr),
42175125Sjoycey #endif
42183859Sml29623 						&gsr.value))
42193859Sml29623 						!= NXGE_OK)
42203859Sml29623 					goto fail;
42213859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
42223859Sml29623 					gsr.bits.link_1000fdx;
42233859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
42243859Sml29623 					gsr.bits.link_1000hdx;
42253859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
42263859Sml29623 					gsr.bits.link_1000fdx) {
42273859Sml29623 					statsp->mac_stats.link_speed = 1000;
42283859Sml29623 					statsp->mac_stats.link_duplex = 2;
42293859Sml29623 				} else if (
42303859Sml29623 					param_arr[param_anar_1000hdx].value &&
42313859Sml29623 						gsr.bits.link_1000hdx) {
42323859Sml29623 					statsp->mac_stats.link_speed = 1000;
42333859Sml29623 					statsp->mac_stats.link_duplex = 1;
42343859Sml29623 				}
42353859Sml29623 			}
42363859Sml29623 			if ((an_common.value != 0) &&
42373859Sml29623 					!(statsp->mac_stats.link_speed)) {
42383859Sml29623 				if (an_common.bits.cap_100T4) {
42393859Sml29623 					statsp->mac_stats.link_T4 = 1;
42403859Sml29623 					statsp->mac_stats.link_speed = 100;
42413859Sml29623 					statsp->mac_stats.link_duplex = 1;
42423859Sml29623 				} else if (an_common.bits.cap_100fdx) {
42433859Sml29623 					statsp->mac_stats.link_speed = 100;
42443859Sml29623 					statsp->mac_stats.link_duplex = 2;
42453859Sml29623 				} else if (an_common.bits.cap_100hdx) {
42463859Sml29623 					statsp->mac_stats.link_speed = 100;
42473859Sml29623 					statsp->mac_stats.link_duplex = 1;
42483859Sml29623 				} else if (an_common.bits.cap_10fdx) {
42493859Sml29623 					statsp->mac_stats.link_speed = 10;
42503859Sml29623 					statsp->mac_stats.link_duplex = 2;
42513859Sml29623 				} else if (an_common.bits.cap_10hdx) {
42523859Sml29623 					statsp->mac_stats.link_speed = 10;
42533859Sml29623 					statsp->mac_stats.link_duplex = 1;
42543859Sml29623 				} else {
42553859Sml29623 					goto fail;
42563859Sml29623 				}
42573859Sml29623 			}
42583859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
42593859Sml29623 				statsp->mac_stats.link_asmpause =
42603859Sml29623 					an_common.bits.cap_asmpause;
42613859Sml29623 				if (statsp->mac_stats.link_asmpause)
42623859Sml29623 				if ((statsp->mac_stats.cap_pause == 0) &&
42633859Sml29623 						(statsp->mac_stats.lp_cap_pause
42643859Sml29623 						== 1))
42653859Sml29623 						statsp->mac_stats.link_pause
42663859Sml29623 						= 0;
42673859Sml29623 					else
42683859Sml29623 						statsp->mac_stats.link_pause
42693859Sml29623 						= 1;
42703859Sml29623 				else
42713859Sml29623 					statsp->mac_stats.link_pause =
42723859Sml29623 						an_common.bits.cap_pause;
42733859Sml29623 			}
42745196Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
42755196Ssbehera 			statsp->mac_stats.link_speed = 1000;
42765196Ssbehera 			statsp->mac_stats.link_duplex = 2;
42773859Sml29623 		}
42783859Sml29623 		*link_up = LINK_IS_UP;
42793859Sml29623 	}
42803859Sml29623 
42813859Sml29623 	if (nxgep->link_notify) {
42823859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
42833859Sml29623 				LINK_IS_DOWN);
42843859Sml29623 		nxgep->link_notify = B_FALSE;
42853859Sml29623 	}
42863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
42873859Sml29623 	return (NXGE_OK);
42883859Sml29623 fail:
42893859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42903859Sml29623 			"nxge_mii_check: Unable to check MII"));
42913859Sml29623 	return (status);
42923859Sml29623 }
42933859Sml29623 
42944977Sraghus /* Check PCS to see if there is any link status change */
42954977Sraghus nxge_status_t
42964977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
42974977Sraghus {
42984977Sraghus 	p_nxge_stats_t	statsp;
42994977Sraghus 	nxge_status_t	status = NXGE_OK;
43004977Sraghus 	boolean_t	linkup;
43014977Sraghus 
43024977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
43034977Sraghus 
43044977Sraghus 	statsp = nxgep->statsp;
43054977Sraghus 	*link_up = LINK_NO_CHANGE;
43064977Sraghus 
43074977Sraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
43084977Sraghus 	if (linkup) {
43094977Sraghus 		if (nxgep->link_notify ||
43104977Sraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
43114977Sraghus 			statsp->mac_stats.link_up = 1;
43124977Sraghus 			statsp->mac_stats.link_speed = 1000;
43134977Sraghus 			statsp->mac_stats.link_duplex = 2;
43144977Sraghus 			*link_up = LINK_IS_UP;
43154977Sraghus 			nxgep->link_notify = B_FALSE;
43164977Sraghus 		}
43174977Sraghus 	} else {
43184977Sraghus 		if (nxgep->link_notify ||
43194977Sraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
43204977Sraghus 			statsp->mac_stats.link_up = 0;
43214977Sraghus 			statsp->mac_stats.link_speed = 0;
43224977Sraghus 			statsp->mac_stats.link_duplex = 0;
43234977Sraghus 			*link_up = LINK_IS_DOWN;
43244977Sraghus 			nxgep->link_notify = B_FALSE;
43254977Sraghus 		}
43264977Sraghus 	}
43274977Sraghus 
43284977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
43294977Sraghus 	return (NXGE_OK);
43304977Sraghus fail:
43314977Sraghus 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43324977Sraghus 	    "nxge_pcs_check: Unable to check PCS"));
43334977Sraghus 	return (status);
43344977Sraghus }
43354977Sraghus 
43363859Sml29623 /* Add a multicast address entry into the HW hash table */
43373859Sml29623 
43383859Sml29623 nxge_status_t
43393859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
43403859Sml29623 {
43413859Sml29623 	uint32_t mchash;
43423859Sml29623 	p_hash_filter_t hash_filter;
43433859Sml29623 	uint16_t hash_bit;
43443859Sml29623 	boolean_t rx_init = B_FALSE;
43453859Sml29623 	uint_t j;
43463859Sml29623 	nxge_status_t status = NXGE_OK;
43473859Sml29623 
43483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
43493859Sml29623 
43503859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
43513859Sml29623 	mchash = crc32_mchash(addrp);
43523859Sml29623 	if (nxgep->hash_filter == NULL) {
43533859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
43543859Sml29623 			"Allocating hash filter storage."));
43553859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
43563859Sml29623 					KM_SLEEP);
43573859Sml29623 	}
43583859Sml29623 	hash_filter = nxgep->hash_filter;
43593859Sml29623 	j = mchash / HASH_REG_WIDTH;
43603859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
43613859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
43623859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
43633859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
43643859Sml29623 		hash_filter->hash_ref_cnt++;
43653859Sml29623 		rx_init = B_TRUE;
43663859Sml29623 	}
43673859Sml29623 	if (rx_init) {
43683859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
43693859Sml29623 			goto fail;
43703859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
43713859Sml29623 			goto fail;
43723859Sml29623 	}
43733859Sml29623 
43743859Sml29623 	RW_EXIT(&nxgep->filter_lock);
43753859Sml29623 
43763859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
43773859Sml29623 
43783859Sml29623 	return (NXGE_OK);
43793859Sml29623 fail:
43803859Sml29623 	RW_EXIT(&nxgep->filter_lock);
43813859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
43823859Sml29623 					"Unable to add multicast address"));
43833859Sml29623 	return (status);
43843859Sml29623 }
43853859Sml29623 
43863859Sml29623 /* Remove a multicast address entry from the HW hash table */
43873859Sml29623 
43883859Sml29623 nxge_status_t
43893859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
43903859Sml29623 {
43913859Sml29623 	uint32_t mchash;
43923859Sml29623 	p_hash_filter_t hash_filter;
43933859Sml29623 	uint16_t hash_bit;
43943859Sml29623 	boolean_t rx_init = B_FALSE;
43953859Sml29623 	uint_t j;
43963859Sml29623 	nxge_status_t status = NXGE_OK;
43973859Sml29623 
43983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
43993859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
44003859Sml29623 	mchash = crc32_mchash(addrp);
44013859Sml29623 	if (nxgep->hash_filter == NULL) {
44023859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
44033859Sml29623 			"Hash filter already de_allocated."));
44043859Sml29623 		RW_EXIT(&nxgep->filter_lock);
44053859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
44063859Sml29623 		return (NXGE_OK);
44073859Sml29623 	}
44083859Sml29623 	hash_filter = nxgep->hash_filter;
44093859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
44103859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
44113859Sml29623 		j = mchash / HASH_REG_WIDTH;
44123859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
44133859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
44143859Sml29623 		hash_filter->hash_ref_cnt--;
44153859Sml29623 		rx_init = B_TRUE;
44163859Sml29623 	}
44173859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
44183859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
44193859Sml29623 			"De-allocating hash filter storage."));
44203859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
44213859Sml29623 		nxgep->hash_filter = NULL;
44223859Sml29623 	}
44233859Sml29623 
44243859Sml29623 	if (rx_init) {
44253859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
44263859Sml29623 			goto fail;
44273859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
44283859Sml29623 			goto fail;
44293859Sml29623 	}
44303859Sml29623 	RW_EXIT(&nxgep->filter_lock);
44313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
44323859Sml29623 
44333859Sml29623 	return (NXGE_OK);
44343859Sml29623 fail:
44353859Sml29623 	RW_EXIT(&nxgep->filter_lock);
44363859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
44373859Sml29623 			"Unable to remove multicast address"));
44383859Sml29623 
44393859Sml29623 	return (status);
44403859Sml29623 }
44413859Sml29623 
44423859Sml29623 /* Set MAC address into MAC address HW registers */
44433859Sml29623 
44443859Sml29623 nxge_status_t
44453859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
44463859Sml29623 {
44473859Sml29623 	nxge_status_t status = NXGE_OK;
44483859Sml29623 
44493859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
44503859Sml29623 
44513859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
44523859Sml29623 	/*
44533859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
44543859Sml29623 	 */
44553859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
44563859Sml29623 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
44573859Sml29623 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
44583859Sml29623 		goto nxge_set_mac_addr_exit;
44593859Sml29623 	}
44603859Sml29623 	nxgep->ouraddr = *addrp;
44613859Sml29623 	/*
44623859Sml29623 	 * Set new interface local address and re-init device.
44633859Sml29623 	 * This is destructive to any other streams attached
44643859Sml29623 	 * to this device.
44653859Sml29623 	 */
44663859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
44673859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
44683859Sml29623 		goto fail;
44693859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
44703859Sml29623 		goto fail;
44713859Sml29623 
44723859Sml29623 	RW_EXIT(&nxgep->filter_lock);
44733859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
44743859Sml29623 	goto nxge_set_mac_addr_end;
44753859Sml29623 nxge_set_mac_addr_exit:
44763859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
44773859Sml29623 nxge_set_mac_addr_end:
44783859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
44793859Sml29623 
44803859Sml29623 	return (NXGE_OK);
44813859Sml29623 fail:
44823859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
44833859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
44843859Sml29623 			"Unable to set mac address"));
44853859Sml29623 	return (status);
44863859Sml29623 }
44873859Sml29623 
44884693Stm144005 static
44894693Stm144005 check_link_state_t
44904693Stm144005 nxge_check_link_stop(
44914693Stm144005 	nxge_t *nxge)
44924693Stm144005 {
44934693Stm144005 	/* If the poll has been cancelled, return STOP. */
44944693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
44954693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
44964693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
44974693Stm144005 		nxge->nxge_link_poll_timerid = 0;
44984693Stm144005 		cv_broadcast(&nxge->poll_cv);
44994693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
45004693Stm144005 
45014693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
45024693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
45034693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
45044693Stm144005 		    nxge->mac.portnum));
45054693Stm144005 		return (CHECK_LINK_STOP);
45064693Stm144005 	}
45074693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
45084693Stm144005 
45094693Stm144005 	return (CHECK_LINK_RESCHEDULE);
45104693Stm144005 }
45114693Stm144005 
45123859Sml29623 /* Check status of MII (MIF or PCS) link */
45133859Sml29623 
45144732Sdavemq static nxge_status_t
45153859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
45163859Sml29623 {
45173859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
45183859Sml29623 	mii_anlpar_t anlpar;
45193859Sml29623 	mii_gsr_t gsr;
45203859Sml29623 	p_mii_regs_t mii_regs;
45213859Sml29623 	nxge_status_t status = NXGE_OK;
45223859Sml29623 	uint8_t portn;
45233859Sml29623 	nxge_link_state_t link_up;
45243859Sml29623 
45254693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
45264693Stm144005 		return (NXGE_ERROR);
45274693Stm144005 
45284693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
45294693Stm144005 		return (NXGE_OK);
45304693Stm144005 
45313859Sml29623 	portn = nxgep->mac.portnum;
45323859Sml29623 
45333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
45344693Stm144005 	    portn));
45353859Sml29623 
45363859Sml29623 	mii_regs = NULL;
45373859Sml29623 
45383859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
45393859Sml29623 
45403859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
45413859Sml29623 		goto nxge_check_mii_link_exit;
45423859Sml29623 
45434977Sraghus 	switch (nxgep->mac.portmode) {
45444977Sraghus 	default:
45455196Ssbehera 		bmsr_data.value = 0;
45463859Sml29623 		if ((status = nxge_mii_read(nxgep,
45474977Sraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
45485125Sjoycey #if defined(__i386)
45495125Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
45505125Sjoycey #else
45514977Sraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
45525125Sjoycey #endif
45534977Sraghus 		    &bmsr_data.value)) != NXGE_OK) {
45543859Sml29623 			goto fail;
45553859Sml29623 		}
45564977Sraghus 
45575196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45585196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
45595196Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
45605572Ssbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
45615196Ssbehera 
45624977Sraghus 		if (nxgep->param_arr[param_autoneg].value) {
45634977Sraghus 			if ((status = nxge_mii_read(nxgep,
45644977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
45655125Sjoycey #if defined(__i386)
45665125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
45675125Sjoycey #else
45684977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
45695125Sjoycey #endif
45704977Sraghus 				&gsr.value)) != NXGE_OK)
45714977Sraghus 				goto fail;
45724977Sraghus 			if ((status = nxge_mii_read(nxgep,
45734977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
45745125Sjoycey #if defined(__i386)
45755125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
45765125Sjoycey #else
45774977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
45785125Sjoycey #endif
45794977Sraghus 				&anlpar.value)) != NXGE_OK)
45804977Sraghus 				goto fail;
45815196Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
45825196Ssbehera 
45835196Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
45845196Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
45855196Ssbehera 				    gsr.bits.link_1000fdx) ||
45865196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
45875196Ssbehera 				    gsr.bits.link_1000hdx) ||
45885196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
45895196Ssbehera 				    anlpar.bits.cap_100T4) ||
45905196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
45915196Ssbehera 				    anlpar.bits.cap_100fdx) ||
45925196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
45935196Ssbehera 				    anlpar.bits.cap_100hdx) ||
45945196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
45955196Ssbehera 				    anlpar.bits.cap_10fdx) ||
45965196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
45975196Ssbehera 				    anlpar.bits.cap_10hdx))) {
45985196Ssbehera 					bmsr_data.bits.link_status = 0;
45995196Ssbehera 				}
46004977Sraghus 			}
46014977Sraghus 		}
46024977Sraghus 
46034977Sraghus 		/* Workaround for link down issue */
46044977Sraghus 		if (bmsr_data.value == 0) {
46054977Sraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
46064977Sraghus 			goto nxge_check_mii_link_exit;
46074977Sraghus 		}
46084977Sraghus 
46095196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46105196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
46115196Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
46125572Ssbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
46135196Ssbehera 
46144977Sraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
46154977Sraghus 		nxgep->bmsr.value = bmsr_data.value;
46165196Ssbehera 
46175196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46185196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
46195196Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
46205572Ssbehera 		    portn, bmsr_data.value, bmsr_ints.value));
46215196Ssbehera 
46224977Sraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
46234977Sraghus 		    &link_up)) != NXGE_OK) {
46244977Sraghus 			goto fail;
46254977Sraghus 		}
46264977Sraghus 		break;
46274977Sraghus 
46284977Sraghus 	case PORT_1G_SERDES:
46294977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46304977Sraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
46314977Sraghus 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
46324977Sraghus 		    != NXGE_OK) {
46334977Sraghus 			goto fail;
46344977Sraghus 		}
46354977Sraghus 		break;
46363859Sml29623 	}
46373859Sml29623 
46383859Sml29623 nxge_check_mii_link_exit:
46393859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46403859Sml29623 	if (link_up == LINK_IS_UP) {
46413859Sml29623 		nxge_link_is_up(nxgep);
46423859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
46433859Sml29623 		nxge_link_is_down(nxgep);
46443859Sml29623 	}
46453859Sml29623 
46463859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
46473859Sml29623 
46483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
46494977Sraghus 				portn));
46503859Sml29623 	return (NXGE_OK);
46513859Sml29623 
46523859Sml29623 fail:
46533859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46543859Sml29623 
46553859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
46563859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
46574977Sraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
46584977Sraghus 			portn));
46593859Sml29623 	return (status);
46603859Sml29623 }
46613859Sml29623 
46623859Sml29623 
46633859Sml29623 /*ARGSUSED*/
46644732Sdavemq static nxge_status_t
46653859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
46663859Sml29623 {
46673859Sml29623 	uint8_t		portn;
46683859Sml29623 	nxge_status_t	status = NXGE_OK;
46695422Ssbehera 	boolean_t	link_up;
46704977Sraghus 	uint32_t	val;
46714977Sraghus 	npi_status_t	rs;
46723859Sml29623 
46734693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
46744693Stm144005 		return (NXGE_ERROR);
46754693Stm144005 
46764693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
46774693Stm144005 		return (NXGE_OK);
46784693Stm144005 
46793859Sml29623 	portn = nxgep->mac.portnum;
46805196Ssbehera 	val = 0;
46815196Ssbehera 	rs = NPI_SUCCESS;
46823859Sml29623 
46833859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
46844693Stm144005 	    portn));
46853859Sml29623 
46864977Sraghus 	switch (nxgep->mac.portmode) {
46874977Sraghus 	default:
46885572Ssbehera 		/*
46895572Ssbehera 		 * Check if the phy is present in case of hot swappable phy
46905572Ssbehera 		 */
46915572Ssbehera 		if (nxgep->hot_swappable_phy) {
46925572Ssbehera 			boolean_t phy_present_now = B_FALSE;
46935572Ssbehera 
46945572Ssbehera 			/*
46955572Ssbehera 			 * If this is the 2nd Goa port, then check 2 addresses
46965572Ssbehera 			 * to take care of the Goa NEM card requirements.
46975572Ssbehera 			 */
46985572Ssbehera 			if (portn == 1) {
46995572Ssbehera 				if (nxge_is_phy_present(nxgep,
47005572Ssbehera 				    BCM8706_ALT_GOA_PORT1_ADDR,
47015572Ssbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
47025572Ssbehera 					phy_present_now = B_TRUE;
47035572Ssbehera 					nxgep->xcvr_addr =
47045572Ssbehera 					    BCM8706_ALT_GOA_PORT1_ADDR;
47055572Ssbehera 					goto phy_check_done;
47065572Ssbehera 				}
47075572Ssbehera 			}
47085572Ssbehera 			if (nxge_is_phy_present(nxgep,
47095572Ssbehera 			    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
47105572Ssbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
47115572Ssbehera 				nxgep->xcvr_addr =
47125572Ssbehera 				    (BCM8706_GOA_PORT_ADDR_BASE) + portn;
47135572Ssbehera 				phy_present_now = B_TRUE;
47145572Ssbehera 			}
47155572Ssbehera 
47165572Ssbehera phy_check_done:
47175572Ssbehera 			if (nxgep->phy_absent) {
47185572Ssbehera 				if (phy_present_now) {
47195572Ssbehera 				/*
47205572Ssbehera 				 * Detect, Initialize phy and do link up
47215572Ssbehera 				 * set xcvr vals, link_init, nxge_init
47225572Ssbehera 				 */
47235572Ssbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
47245572Ssbehera 					    "Hot swappable phy DETECTED!!"));
47255572Ssbehera 					nxgep->phy_absent = B_FALSE;
47265572Ssbehera 					(void) nxge_xcvr_find(nxgep);
47275572Ssbehera 					(void) nxge_link_init(nxgep);
47285572Ssbehera 					if (!(nxgep->drv_state &
47295572Ssbehera 					    STATE_HW_INITIALIZED)) {
47305572Ssbehera 						status = nxge_init(nxgep);
47315572Ssbehera 						if (status != NXGE_OK) {
47325572Ssbehera 							NXGE_ERROR_MSG((nxgep,
47335572Ssbehera 							    NXGE_ERR_CTL,
47345572Ssbehera 							    "Hot swappable "
47355572Ssbehera 							    "phy present, but"
47365572Ssbehera 							    " driver init"
47375572Ssbehera 							    "  failed..."));
47385572Ssbehera 							goto fail;
47395572Ssbehera 						}
47405572Ssbehera 					}
47415572Ssbehera 				}
47425572Ssbehera 
47435572Ssbehera 				goto start_link_check;
47445572Ssbehera 
47455572Ssbehera 			} else if (!phy_present_now) {
47465572Ssbehera 				/*
47475572Ssbehera 				 * Phy gone, bring link down reset xcvr vals
47485572Ssbehera 				 */
47495572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
47505572Ssbehera 				    "Hot swappable phy REMOVED!!"));
47515572Ssbehera 				nxgep->phy_absent = B_TRUE;
47525572Ssbehera 				nxgep->statsp->mac_stats.link_up = 0;
47535572Ssbehera 				nxgep->statsp->mac_stats.link_speed = 0;
47545572Ssbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
47555572Ssbehera 				nxge_link_is_down(nxgep);
47565572Ssbehera 				nxgep->link_notify = B_FALSE;
47575572Ssbehera 
47585572Ssbehera 				(void) nxge_xcvr_find(nxgep);
47595572Ssbehera 
47605572Ssbehera 				goto start_link_check;
47615572Ssbehera 
47625572Ssbehera 			}
47635572Ssbehera 		}
47646604Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
47656604Ssbehera 			status = nxge_mrvl88x2011_link(nxgep, &link_up);
47666604Ssbehera 		} else {
47676604Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
47686604Ssbehera 		}
47694977Sraghus 		if (status != NXGE_OK)
47704977Sraghus 			goto fail;
47714977Sraghus 		break;
47724977Sraghus 	case PORT_10G_SERDES:
47734977Sraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
47745422Ssbehera 		    XPCS_REG_STATUS, &val);
47754977Sraghus 		if (rs != 0)
47764977Sraghus 			goto fail;
47774977Sraghus 
47784977Sraghus 		link_up = B_FALSE;
47795422Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
47805422Ssbehera 			link_up = B_TRUE;
47814977Sraghus 		}
47824977Sraghus 
47834977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
47844977Sraghus 		    "==> nxge_check_10g_link port<%d> "
47855422Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
47865422Ssbehera 		    portn, val, link_up));
47875422Ssbehera 
47884977Sraghus 		break;
47894977Sraghus 	}
47903859Sml29623 
47913859Sml29623 	if (link_up) {
47923859Sml29623 		if (nxgep->link_notify ||
47933859Sml29623 			nxgep->statsp->mac_stats.link_up == 0) {
47943859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
47953859Sml29623 				goto fail;
47963859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
47973859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
47983859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
47993859Sml29623 
48003859Sml29623 			nxge_link_is_up(nxgep);
48013859Sml29623 			nxgep->link_notify = B_FALSE;
48023859Sml29623 		}
48033859Sml29623 	} else {
48043859Sml29623 		if (nxgep->link_notify ||
48053859Sml29623 			nxgep->statsp->mac_stats.link_up == 1) {
48063859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
48073859Sml29623 				goto fail;
48083859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48094977Sraghus 					"Link down cable problem"));
48103859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
48113859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
48123859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
48133859Sml29623 
48143859Sml29623 			nxge_link_is_down(nxgep);
48153859Sml29623 			nxgep->link_notify = B_FALSE;
48163859Sml29623 		}
48173859Sml29623 	}
48183859Sml29623 
48195572Ssbehera start_link_check:
48203859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
48213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
48224693Stm144005 	    portn));
48233859Sml29623 	return (NXGE_OK);
48243859Sml29623 
48253859Sml29623 fail:
48264693Stm144005 	(void) nxge_check_link_stop(nxgep);
48274693Stm144005 
48283859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
48294693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
48304693Stm144005 	    portn));
48313859Sml29623 	return (status);
48323859Sml29623 }
48333859Sml29623 
48343859Sml29623 
48353859Sml29623 /* Declare link down */
48363859Sml29623 
48373859Sml29623 void
48383859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
48393859Sml29623 {
48404732Sdavemq 	p_nxge_stats_t statsp;
48414732Sdavemq 	char link_stat_msg[64];
48424732Sdavemq 
48433859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
48443859Sml29623 
48454732Sdavemq 	statsp = nxgep->statsp;
48464732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
48474732Sdavemq 	    statsp->mac_stats.xcvr_portn);
48484732Sdavemq 
48494732Sdavemq 	if (nxge_no_msg == B_FALSE) {
48504732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
48514732Sdavemq 	}
48524732Sdavemq 
48533859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
48543859Sml29623 
48553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
48563859Sml29623 }
48573859Sml29623 
48583859Sml29623 /* Declare link up */
48593859Sml29623 
48603859Sml29623 void
48613859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
48623859Sml29623 {
48634732Sdavemq 	p_nxge_stats_t statsp;
48644732Sdavemq 	char link_stat_msg[64];
48653859Sml29623 	uint32_t val;
48663859Sml29623 
48673859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
48683859Sml29623 
48694732Sdavemq 	statsp = nxgep->statsp;
48704732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
48714732Sdavemq 	    statsp->mac_stats.xcvr_portn,
48724732Sdavemq 	    statsp->mac_stats.link_speed);
48734732Sdavemq 
48744732Sdavemq 	if (statsp->mac_stats.link_T4)
48754732Sdavemq 		(void) strcat(link_stat_msg, "T4");
48764732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
48774732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
48784732Sdavemq 	else
48794732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
48804732Sdavemq 
48813859Sml29623 	(void) nxge_xif_init(nxgep);
48823859Sml29623 
48833859Sml29623 	/* Clean up symbol errors incurred during link transition */
48844977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
48854977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
48863859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
48873859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
48883859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
48893859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
48903859Sml29623 	}
48913859Sml29623 
48924732Sdavemq 	if (nxge_no_msg == B_FALSE) {
48934732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
48944732Sdavemq 	}
48954732Sdavemq 
48963859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
48973859Sml29623 
48983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
48993859Sml29623 }
49003859Sml29623 
49013859Sml29623 /*
49023859Sml29623  * Calculate the bit in the multicast address filter
49033859Sml29623  * that selects the given * address.
49043859Sml29623  * Note: For GEM, the last 8-bits are used.
49053859Sml29623  */
49063859Sml29623 uint32_t
49073859Sml29623 crc32_mchash(p_ether_addr_t addr)
49083859Sml29623 {
49093859Sml29623 	uint8_t *cp;
49103859Sml29623 	uint32_t crc;
49113859Sml29623 	uint32_t c;
49123859Sml29623 	int byte;
49133859Sml29623 	int bit;
49143859Sml29623 
49153859Sml29623 	cp = (uint8_t *)addr;
49163859Sml29623 	crc = (uint32_t)0xffffffff;
49173859Sml29623 	for (byte = 0; byte < 6; byte++) {
49183859Sml29623 		c = (uint32_t)cp[byte];
49193859Sml29623 		for (bit = 0; bit < 8; bit++) {
49203859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
49213859Sml29623 				crc = (crc >> 1)^0xedb88320;
49223859Sml29623 			else
49233859Sml29623 				crc = (crc >> 1);
49243859Sml29623 			c >>= 1;
49253859Sml29623 		}
49263859Sml29623 	}
49273859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
49283859Sml29623 }
49293859Sml29623 
49303859Sml29623 /* Reset serdes */
49313859Sml29623 
49323859Sml29623 nxge_status_t
49333859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
49343859Sml29623 {
49353859Sml29623 	npi_handle_t		handle;
49363859Sml29623 
49373859Sml29623 	handle = nxgep->npi_handle;
49383859Sml29623 
49393859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
49403859Sml29623 	drv_usecwait(500);
49413859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
49423859Sml29623 
49433859Sml29623 	return (NXGE_OK);
49443859Sml29623 }
49453859Sml29623 
49463859Sml29623 /* Monitor link status using interrupt or polling */
49473859Sml29623 nxge_status_t
49483859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
49493859Sml29623 {
49503859Sml29623 	nxge_status_t status = NXGE_OK;
49513859Sml29623 
49526495Sspeer 	/* If we are a guest domain driver, don't bother. */
49536495Sspeer 	if (isLDOMguest(nxgep))
49546495Sspeer 		return (status);
49556495Sspeer 
49563859Sml29623 	/*
49574693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
49584693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
49593859Sml29623 	 */
49604977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
49614977Sraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
49624977Sraghus 	    (nxgep->mac.portnum > 1))
49633859Sml29623 		return (NXGE_OK);
49643859Sml29623 
49653859Sml29623 	if (nxgep->statsp == NULL) {
49663859Sml29623 		/* stats has not been allocated. */
49673859Sml29623 		return (NXGE_OK);
49683859Sml29623 	}
49696075Ssbehera 	/* Don't check link if we're in internal loopback mode */
49706075Ssbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
49713859Sml29623 		return (NXGE_OK);
49723859Sml29623 
49733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49744693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
49754693Stm144005 	    nxgep->mac.portnum, enable));
49763859Sml29623 	if (enable == LINK_MONITOR_START) {
49773859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
49783859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
49794693Stm144005 			    != NXGE_OK)
49803859Sml29623 				goto fail;
49813859Sml29623 		} else {
49824693Stm144005 			timeout_id_t timerid;
49834693Stm144005 
49844693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
49854693Stm144005 				return (NXGE_OK);
49864693Stm144005 
49874732Sdavemq 			if (nxgep->xcvr.check_link) {
49884732Sdavemq 				timerid = timeout(
49894732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
49904693Stm144005 				    nxgep,
49914693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
49924732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
49934732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
49944732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
49954732Sdavemq 			} else {
49964693Stm144005 				return (NXGE_ERROR);
49973859Sml29623 			}
49983859Sml29623 		}
49993859Sml29623 	} else {
50003859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
50013859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
50024693Stm144005 			    != NXGE_OK)
50033859Sml29623 				goto fail;
50043859Sml29623 		} else {
50054693Stm144005 			clock_t rv;
50064693Stm144005 
50074693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
50084693Stm144005 
50094693Stm144005 			/* If <timerid> == 0, the link monitor has */
50104693Stm144005 			/* never been started, or just now stopped. */
50114693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
50124693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
50134693Stm144005 				return (NXGE_OK);
50144693Stm144005 			}
50154693Stm144005 
50164693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
50174693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
50184693Stm144005 			    &nxgep->poll_lock,
50194693Stm144005 			    ddi_get_lbolt() +
50204693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
50214693Stm144005 			    LINK_MONITOR_PERIOD));
50224693Stm144005 			if (rv == -1) {
50234693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50244693Stm144005 				    "==> stopping port %d: "
50254693Stm144005 				    "cv_timedwait(%d) timed out",
50264693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
50274693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
50283859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
50293859Sml29623 			}
50304693Stm144005 
50314693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
50323859Sml29623 		}
50333859Sml29623 	}
50343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50354693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
50364693Stm144005 	    nxgep->mac.portnum, enable));
50376495Sspeer 
50383859Sml29623 	return (NXGE_OK);
50393859Sml29623 fail:
50403859Sml29623 	return (status);
50413859Sml29623 }
50423859Sml29623 
50433859Sml29623 /* Set promiscous mode */
50443859Sml29623 
50453859Sml29623 nxge_status_t
50463859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
50473859Sml29623 {
50483859Sml29623 	nxge_status_t status = NXGE_OK;
50493859Sml29623 
50504732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
50513859Sml29623 
50523859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
50533859Sml29623 
50543859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
50553859Sml29623 
50563859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
50573859Sml29623 		goto fail;
50583859Sml29623 	}
50593859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
50603859Sml29623 		goto fail;
50613859Sml29623 	}
50623859Sml29623 
50633859Sml29623 	RW_EXIT(&nxgep->filter_lock);
50643859Sml29623 
50653859Sml29623 	if (on)
50663859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
50673859Sml29623 	else
50683859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
50693859Sml29623 
50703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
50713859Sml29623 
50723859Sml29623 	return (NXGE_OK);
50733859Sml29623 fail:
50743859Sml29623 	RW_EXIT(&nxgep->filter_lock);
50753859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
50764732Sdavemq 	    "Unable to set promisc (%d)", on));
50773859Sml29623 
50783859Sml29623 	return (status);
50793859Sml29623 }
50803859Sml29623 
50813859Sml29623 /*ARGSUSED*/
50823859Sml29623 uint_t
50833859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
50843859Sml29623 {
50853859Sml29623 #ifdef	NXGE_DEBUG
50863859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
50873859Sml29623 #endif
50883859Sml29623 #if NXGE_MIF
50893859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
50903859Sml29623 	uint32_t		status;
50913859Sml29623 	npi_handle_t		handle;
50923859Sml29623 	uint8_t			portn;
50933859Sml29623 	p_nxge_stats_t		statsp;
50943859Sml29623 #endif
50953859Sml29623 
50963859Sml29623 #ifdef	NXGE_MIF
50973859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
50983859Sml29623 		nxgep = ldvp->nxgep;
50993859Sml29623 	}
51003859Sml29623 	nxgep = ldvp->nxgep;
51013859Sml29623 #endif
51023859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
51033859Sml29623 
51043859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
51053859Sml29623 	return (DDI_INTR_CLAIMED);
51063859Sml29623 
51073859Sml29623 mif_intr_fail:
51083859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
51093859Sml29623 	return (DDI_INTR_UNCLAIMED);
51103859Sml29623 }
51113859Sml29623 
51123859Sml29623 /*ARGSUSED*/
51133859Sml29623 uint_t
51143859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
51153859Sml29623 {
51163859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
51173859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
51183859Sml29623 	p_nxge_ldg_t		ldgp;
51193859Sml29623 	uint32_t		status;
51203859Sml29623 	npi_handle_t		handle;
51213859Sml29623 	uint8_t			portn;
51223859Sml29623 	p_nxge_stats_t		statsp;
51233859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
51243859Sml29623 
51253859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
51263859Sml29623 		nxgep = ldvp->nxgep;
51273859Sml29623 	}
51283859Sml29623 
51293859Sml29623 	ldgp = ldvp->ldgp;
51303859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
51314732Sdavemq 	    "group %d", ldgp->ldg));
51323859Sml29623 
51333859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
51343859Sml29623 	/*
51353859Sml29623 	 * This interrupt handler is for a specific
51363859Sml29623 	 * mac port.
51373859Sml29623 	 */
51383859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
51393859Sml29623 	portn = nxgep->mac.portnum;
51403859Sml29623 
51413859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
51424732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
51433859Sml29623 
51443859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
51453859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
51463859Sml29623 					(xmac_tx_iconfig_t *)&status);
51473859Sml29623 		if (rs != NPI_SUCCESS)
51483859Sml29623 			goto npi_fail;
51493859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
51503859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
51513859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
51523859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
51533859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
51543859Sml29623 			}
51553859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
51563859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
51575523Syc148097 				/*
51585523Syc148097 				 * Do not send FMA ereport because this
51595523Syc148097 				 * error does not indicate HW failure.
51605523Syc148097 				 */
51613859Sml29623 			}
51623859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
51633859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
51643859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
51653859Sml29623 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
51663859Sml29623 			}
51673859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
51683859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
51693859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
51703859Sml29623 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
51713859Sml29623 			}
51723859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
51733859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
51743859Sml29623 							XTXMAC_BYTE_CNT_MASK;
51753859Sml29623 			}
51763859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
51773859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
51783859Sml29623 							XTXMAC_FRM_CNT_MASK;
51793859Sml29623 			}
51803859Sml29623 		}
51813859Sml29623 
51823859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
51833859Sml29623 					(xmac_rx_iconfig_t *)&status);
51843859Sml29623 		if (rs != NPI_SUCCESS)
51853859Sml29623 			goto npi_fail;
51863859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
51873859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
51883859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
51893859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
51903859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
51913859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
51923859Sml29623 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
51933859Sml29623 			}
51945523Syc148097 			/*
51955523Syc148097 			 * Do not send FMA ereport for the following 3 errors
51965523Syc148097 			 * because they do not indicate HW failures.
51975523Syc148097 			 */
51983859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
51993859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
52003859Sml29623 							XRXMAC_CRC_ER_CNT_MASK;
52013859Sml29623 			}
52023859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
52033859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
52043859Sml29623 							MAC_LEN_ER_CNT_MASK;
52053859Sml29623 			}
52063859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
52073859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
52083859Sml29623 							XRXMAC_CD_VIO_CNT_MASK;
52093859Sml29623 			}
52103859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
52113859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
52123859Sml29623 							XRXMAC_BT_CNT_MASK;
52133859Sml29623 			}
52143859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
52153859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
52163859Sml29623 							XRXMAC_HIST_CNT1_MASK;
52173859Sml29623 			}
52183859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
52193859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
52203859Sml29623 							XRXMAC_HIST_CNT2_MASK;
52213859Sml29623 			}
52223859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
52233859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
52243859Sml29623 							XRXMAC_HIST_CNT3_MASK;
52253859Sml29623 			}
52263859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
52273859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
52283859Sml29623 							XRXMAC_HIST_CNT4_MASK;
52293859Sml29623 			}
52303859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
52313859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
52323859Sml29623 							XRXMAC_HIST_CNT5_MASK;
52333859Sml29623 			}
52343859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
52353859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
52363859Sml29623 							XRXMAC_HIST_CNT6_MASK;
52373859Sml29623 			}
52383859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
52393859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
52403859Sml29623 							XRXMAC_BC_FRM_CNT_MASK;
52413859Sml29623 			}
52423859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
52433859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
52443859Sml29623 							XRXMAC_MC_FRM_CNT_MASK;
52453859Sml29623 			}
52465523Syc148097 			/*
52475523Syc148097 			 * Do not send FMA ereport for the following 3 errors
52485523Syc148097 			 * because they do not indicate HW failures.
52495523Syc148097 			 */
52503859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
52513859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
52523859Sml29623 							XRXMAC_FRAG_CNT_MASK;
52533859Sml29623 			}
52543859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
52553859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
52563859Sml29623 							XRXMAC_AL_ER_CNT_MASK;
52573859Sml29623 			}
52583859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
52593859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
52603859Sml29623 							XMAC_LINK_FLT_CNT_MASK;
52613859Sml29623 			}
52623859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
52633859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
52643859Sml29623 			}
52653859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
52663859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
52673859Sml29623 			}
52683859Sml29623 		}
52693859Sml29623 
52703859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
52713859Sml29623 						(xmac_ctl_iconfig_t *)&status);
52723859Sml29623 		if (rs != NPI_SUCCESS)
52733859Sml29623 			goto npi_fail;
52743859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
52753859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
52763859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
52773859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
52783859Sml29623 				statsp->xmac_stats.tx_pause_state++;
52793859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
52803859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
52813859Sml29623 		}
52823859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
52833859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
52843859Sml29623 						(bmac_tx_iconfig_t *)&status);
52853859Sml29623 		if (rs != NPI_SUCCESS)
52863859Sml29623 			goto npi_fail;
52873859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
52883859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
52893859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
52903859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
52913859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
52923859Sml29623 			}
52933859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
52943859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
52953859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
52963859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
52973859Sml29623 			}
52983859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
52993859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
53003859Sml29623 							BTXMAC_BYTE_CNT_MASK;
53013859Sml29623 			}
53023859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
53033859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
53043859Sml29623 							BTXMAC_FRM_CNT_MASK;
53053859Sml29623 			}
53063859Sml29623 		}
53073859Sml29623 
53083859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
53093859Sml29623 						(bmac_rx_iconfig_t *)&status);
53103859Sml29623 		if (rs != NPI_SUCCESS)
53113859Sml29623 			goto npi_fail;
53123859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
53133859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
53143859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
53153859Sml29623 			}
53163859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
53173859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
53183859Sml29623 							RXMAC_FRM_CNT_MASK;
53193859Sml29623 			}
53203859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
53213859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
53223859Sml29623 							BMAC_CRC_ER_CNT_MASK;
53233859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
53243859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
53253859Sml29623 			}
53263859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
53273859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
53283859Sml29623 							MAC_LEN_ER_CNT_MASK;
53293859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
53303859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
53313859Sml29623 			}
53323859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
53333859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
53343859Sml29623 							BMAC_CD_VIO_CNT_MASK;
53353859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
53363859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
53373859Sml29623 			}
53383859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
53393859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
53403859Sml29623 							BRXMAC_BYTE_CNT_MASK;
53413859Sml29623 			}
53423859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
53433859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
53443859Sml29623 							BMAC_AL_ER_CNT_MASK;
53453859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
53463859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
53473859Sml29623 			}
53483859Sml29623 
53493859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
53503859Sml29623 						(bmac_ctl_iconfig_t *)&status);
53513859Sml29623 			if (rs != NPI_SUCCESS)
53523859Sml29623 				goto npi_fail;
53533859Sml29623 
53543859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
53553859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
53563859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
53573859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
53583859Sml29623 					statsp->bmac_stats.tx_pause_state++;
53593859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
53603859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
53613859Sml29623 			}
53623859Sml29623 		}
53633859Sml29623 
53643859Sml29623 	if (ldgp->nldvs == 1) {
53653859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
53663859Sml29623 			B_TRUE, ldgp->ldg_timer);
53673859Sml29623 	}
53683859Sml29623 
53693859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
53703859Sml29623 	return (DDI_INTR_CLAIMED);
53713859Sml29623 
53723859Sml29623 npi_fail:
53733859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
53743859Sml29623 	return (DDI_INTR_UNCLAIMED);
53753859Sml29623 }
53763859Sml29623 
53773859Sml29623 nxge_status_t
53783859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
53793859Sml29623 {
53803859Sml29623 	uint8_t		phy_port_addr;
53813859Sml29623 	nxge_status_t	status = NXGE_OK;
53823859Sml29623 	boolean_t	rx_sig_ok;
53833859Sml29623 	boolean_t	pcs_blk_lock;
53843859Sml29623 	boolean_t	link_align;
53853859Sml29623 	uint16_t	val1, val2, val3;
53863859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
53873859Sml29623 	uint16_t	val_debug;
53883859Sml29623 	uint16_t	val;
53893859Sml29623 #endif
53903859Sml29623 
53913859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
53923859Sml29623 
53933859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
53943859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
53953859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
53963859Sml29623 	if ((val_debug & ~0x200) != 0) {
53973859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
53983859Sml29623 				nxgep->mac.portnum, val_debug);
53993859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
54003859Sml29623 				&val_debug);
54013859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
54023859Sml29623 				nxgep->mac.portnum, val_debug);
54033859Sml29623 	}
54043859Sml29623 
54053859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
54063859Sml29623 					XPCS_REG_DESCWERR_COUNTER, &val);
54073859Sml29623 	if (val != 0)
54083859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
54093859Sml29623 
54103859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
54113859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
54123859Sml29623 	if (val != 0)
54133859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
54143859Sml29623 
54153859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
54163859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
54173859Sml29623 	if (val != 0)
54183859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
54193859Sml29623 #endif
54203859Sml29623 
54213859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
54223859Sml29623 
54233859Sml29623 	/* Check Device 1 Register 0xA bit0 */
54243859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
54253859Sml29623 			BCM8704_PMA_PMD_DEV_ADDR,
54263859Sml29623 			BCM8704_PMD_RECEIVE_SIG_DETECT,
54273859Sml29623 			&val1);
54283859Sml29623 	if (status != NXGE_OK)
54293859Sml29623 		goto fail;
54303859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
54313859Sml29623 
54323859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
54333859Sml29623 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
54343859Sml29623 			BCM8704_PCS_DEV_ADDR,
54353859Sml29623 			BCM8704_10GBASE_R_PCS_STATUS_REG,
54363859Sml29623 			&val2)) != NPI_SUCCESS)
54373859Sml29623 		goto fail;
54383859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
54393859Sml29623 
54403859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
54413859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
54423859Sml29623 			BCM8704_PHYXS_ADDR,
54433859Sml29623 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
54443859Sml29623 			&val3);
54453859Sml29623 	if (status != NXGE_OK)
54463859Sml29623 		goto fail;
54475572Ssbehera 
54485572Ssbehera 	switch (nxgep->chip_id) {
54495572Ssbehera 	case BCM8704_CHIP_ID:
54505572Ssbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
54515572Ssbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
54525572Ssbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
54535572Ssbehera 		break;
54545572Ssbehera 	case BCM8706_CHIP_ID:
54555572Ssbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
54565572Ssbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
54575572Ssbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
54585572Ssbehera 		    B_TRUE : B_FALSE;
54595572Ssbehera 		break;
54605572Ssbehera 	default:
54615572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
54625572Ssbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
54635572Ssbehera 		goto fail;
54645572Ssbehera 	}
54655572Ssbehera 
54663859Sml29623 
54673859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
54683859Sml29623 	/* Temp workaround for link down issue */
54693859Sml29623 	if (pcs_blk_lock == B_FALSE) {
54703859Sml29623 		if (val2 != 0x4) {
54713859Sml29623 			pcs_blk_lock = B_TRUE;
54723859Sml29623 			cmn_err(CE_NOTE,
54733859Sml29623 				"!LINK DEBUG: port%d PHY Dev3 "
54743859Sml29623 				"Reg 0x20 = 0x%x\n",
54753859Sml29623 				nxgep->mac.portnum, val2);
54763859Sml29623 		}
54773859Sml29623 	}
54783859Sml29623 
54793859Sml29623 	if (link_align == B_FALSE) {
54803859Sml29623 		if (val3 != 0x140f) {
54813859Sml29623 			link_align = B_TRUE;
54823859Sml29623 			cmn_err(CE_NOTE,
54833859Sml29623 				"!LINK DEBUG: port%d PHY Dev4 "
54843859Sml29623 				"Reg 0x18 = 0x%x\n",
54853859Sml29623 				nxgep->mac.portnum, val3);
54863859Sml29623 		}
54873859Sml29623 	}
54883859Sml29623 
54893859Sml29623 	if (rx_sig_ok == B_FALSE) {
54903859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
54913859Sml29623 			rx_sig_ok = B_TRUE;
54923859Sml29623 			cmn_err(CE_NOTE,
54933859Sml29623 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
54943859Sml29623 				nxgep->mac.portnum);
54953859Sml29623 		}
54963859Sml29623 	}
54973859Sml29623 #endif
54983859Sml29623 
54993859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
55003859Sml29623 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
55013859Sml29623 
55023859Sml29623 	return (NXGE_OK);
55033859Sml29623 fail:
55043859Sml29623 	return (status);
55053859Sml29623 }
55063859Sml29623 
55076604Ssbehera static nxge_status_t
55086604Ssbehera nxge_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
55096604Ssbehera {
55106604Ssbehera 	uint8_t		phy;
55116604Ssbehera 	nxge_status_t   status = NXGE_OK;
55126604Ssbehera 	boolean_t	pma_status;
55136604Ssbehera 	boolean_t	pcs_status;
55146604Ssbehera 	boolean_t	xgxs_status;
55156604Ssbehera 	uint16_t	val;
55166604Ssbehera 
55176604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
55186604Ssbehera 
55196604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
55206604Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
55216604Ssbehera 
55226604Ssbehera 	*link_up = B_FALSE;
55236604Ssbehera 
55246604Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
55256604Ssbehera 
55266604Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
55276604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
55286604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
55296604Ssbehera 
55306604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55316604Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
55326604Ssbehera 
55336604Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
55346604Ssbehera 
55356604Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
55366604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
55376604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
55386604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
55396604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
55406604Ssbehera 
55416604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55426604Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
55436604Ssbehera 
55446604Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
55456604Ssbehera 
55466604Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
55476604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
55486604Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
55496604Ssbehera 
55506604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55516604Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
55526604Ssbehera 
55536604Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
55546604Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
55556604Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
55566604Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
55576604Ssbehera 
55586604Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
55596604Ssbehera 	    B_TRUE : B_FALSE;
55606604Ssbehera 
55616604Ssbehera fail:
55626604Ssbehera 
55636604Ssbehera 	if (*link_up == B_FALSE) {
55646604Ssbehera 		/* PCS OFF */
55656604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
55666604Ssbehera 	} else {
55676604Ssbehera 		/* PCS Activity */
55686604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
55696604Ssbehera 	}
55706604Ssbehera 
55716604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55726604Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
55736604Ssbehera 
55746604Ssbehera 	return (status);
55756604Ssbehera }
55766604Ssbehera 
55773859Sml29623 nxge_status_t
55783859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
55793859Sml29623 {
55803859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
55814732Sdavemq 	    != NPI_SUCCESS)
55823859Sml29623 		return (NXGE_ERROR);
55833859Sml29623 	else
55843859Sml29623 		return (NXGE_OK);
55853859Sml29623 }
55863859Sml29623 
55873859Sml29623 nxge_status_t
55883859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
55893859Sml29623 {
55903859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
55914732Sdavemq 	    != NPI_SUCCESS)
55923859Sml29623 		return (NXGE_ERROR);
55933859Sml29623 	else
55943859Sml29623 		return (NXGE_OK);
55953859Sml29623 }
55964185Sspeer 
55975572Ssbehera static boolean_t
55985572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
55995572Ssbehera {
56005572Ssbehera 	uint32_t pma_pmd_id = 0;
56015572Ssbehera 	uint32_t pcs_id = 0;
56025572Ssbehera 	uint32_t phy_id = 0;
56035572Ssbehera 
56045572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
56055572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56065572Ssbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
56075572Ssbehera 	if ((pma_pmd_id & mask) == (id & mask))
56085572Ssbehera 		goto found_phy;
56095572Ssbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
56105572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56115572Ssbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
56125572Ssbehera 	if ((pcs_id & mask) == (id & mask))
56135572Ssbehera 		goto found_phy;
56145572Ssbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
56155572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56165572Ssbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
56175572Ssbehera 	if ((phy_id & mask) == (id & mask))
56185572Ssbehera 		goto found_phy;
56195572Ssbehera 
56205572Ssbehera 	return (B_FALSE);
56215572Ssbehera 
56225572Ssbehera found_phy:
56235572Ssbehera 	return (B_TRUE);
56245572Ssbehera }
56255572Ssbehera 
56264732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
56274732Sdavemq 
56284732Sdavemq static boolean_t
56294732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
56304732Sdavemq {
56314732Sdavemq 	int		i;
56324732Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
56334732Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
56344732Sdavemq 	boolean_t	found = B_FALSE;
56354732Sdavemq 
56364732Sdavemq 	switch (type) {
56374732Sdavemq 	case CLAUSE_45_TYPE:
56384732Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
56394782Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
56404782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
56414732Sdavemq 				found = B_TRUE;
56424732Sdavemq 				break;
56434732Sdavemq 			}
56444732Sdavemq 		}
56454732Sdavemq 		break;
56464732Sdavemq 	case CLAUSE_22_TYPE:
56474732Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
56484782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
56494782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
56504732Sdavemq 				found = B_TRUE;
56514732Sdavemq 				break;
56524732Sdavemq 			}
56534732Sdavemq 		}
56544732Sdavemq 		break;
56554732Sdavemq 	default:
56564732Sdavemq 		break;
56574732Sdavemq 	}
56584732Sdavemq 
56594732Sdavemq 	return (found);
56604732Sdavemq }
56614732Sdavemq 
56624977Sraghus static uint32_t
56634977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
56644977Sraghus {
56654977Sraghus 	uint16_t	val1 = 0;
56664977Sraghus 	uint16_t	val2 = 0;
56674977Sraghus 	uint32_t	pma_pmd_dev_id = 0;
56684977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
56694977Sraghus 
56705780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
56714977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
56724977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
56734977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
56744977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
56755780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
56764977Sraghus 
56774977Sraghus 	pma_pmd_dev_id = val1;
56784977Sraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
56794977Sraghus 	pma_pmd_dev_id |= val2;
56804977Sraghus 
56814977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
56824977Sraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
56834977Sraghus 
56844977Sraghus 	return (pma_pmd_dev_id);
56854977Sraghus }
56864977Sraghus 
56874977Sraghus static uint32_t
56884977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
56894977Sraghus {
56904977Sraghus 	uint16_t	val1 = 0;
56914977Sraghus 	uint16_t	val2 = 0;
56924977Sraghus 	uint32_t	pcs_dev_id = 0;
56934977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
56944977Sraghus 
56955780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
56964977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
56974977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
56984977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
56994977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
57005780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
57014977Sraghus 
57024977Sraghus 	pcs_dev_id = val1;
57034977Sraghus 	pcs_dev_id = (pcs_dev_id << 16);
57044977Sraghus 	pcs_dev_id |= val2;
57054977Sraghus 
57064977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
57074977Sraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
57084977Sraghus 
57094977Sraghus 	return (pcs_dev_id);
57104977Sraghus }
57114977Sraghus 
57124977Sraghus static uint32_t
57134977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
57144977Sraghus {
57154977Sraghus 	uint16_t	val1 = 0;
57164977Sraghus 	uint16_t	val2 = 0;
57174977Sraghus 	uint32_t	phy_id = 0;
57184977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
57194977Sraghus 	npi_status_t	npi_status = NPI_SUCCESS;
57204977Sraghus 
57216075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
57224977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
57234977Sraghus 	    &val1);
57244977Sraghus 	if (npi_status != NPI_SUCCESS) {
57254977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
57264977Sraghus 		    "clause 22 read to reg 2 failed!!!"));
57274977Sraghus 		goto exit;
57284977Sraghus 	}
57294977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
57304977Sraghus 	    &val2);
57314977Sraghus 	if (npi_status != 0) {
57324977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
57334977Sraghus 		    "clause 22 read to reg 3 failed!!!"));
57344977Sraghus 		goto exit;
57354977Sraghus 	}
57364977Sraghus 	phy_id = val1;
57374977Sraghus 	phy_id = (phy_id << 16);
57384977Sraghus 	phy_id |= val2;
57394977Sraghus 
57404977Sraghus exit:
57416075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
57424977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
57434977Sraghus 	    phy_port, phy_id));
57444977Sraghus 
57454977Sraghus 	return (phy_id);
57464977Sraghus }
57474977Sraghus 
57484732Sdavemq /*
57494732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
57504732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
57514732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
57524732Sdavemq  * and the Neptune type.
57534732Sdavemq  */
57544732Sdavemq 
57554732Sdavemq nxge_status_t
57564732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
57574732Sdavemq {
57586261Sjoycey 	int		i, j, l;
57594732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
57604732Sdavemq 	uint32_t	pcs_dev_id = 0;
57614732Sdavemq 	uint32_t	phy_id = 0;
57624782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
57634782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
57644782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
57654732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
57664732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
57675572Ssbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
57685572Ssbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
57694732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
57704732Sdavemq 	nxge_status_t	status = NXGE_OK;
57714732Sdavemq 
57724732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
57734732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
57744732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
57754732Sdavemq 	    nxgep->niu_type));
57764732Sdavemq 
57776495Sspeer 	if (isLDOMguest(nxgep)) {
57786495Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
57796495Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
57806495Sspeer 		return (NXGE_OK);
57816495Sspeer 	}
57826495Sspeer 
57836261Sjoycey 	j = l = 0;
57844732Sdavemq 	total_port_fd = total_phy_fd = 0;
57854732Sdavemq 	/*
57864732Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
57874732Sdavemq 	 * for on chip serdes usages.
57884732Sdavemq 	 */
57894732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
57904977Sraghus 
57914977Sraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
57924732Sdavemq 
57934732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
57944732Sdavemq 			pma_pmd_dev_fd[i] = 1;
57954732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
57966604Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
57974782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
57984782Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
57994782Ssbehera 				    BCM_PHY_ID_MASK;
58005572Ssbehera 				port_fd_arr[j] = (uint8_t)i;
58014732Sdavemq 				j++;
58024732Sdavemq 			}
58034732Sdavemq 		} else {
58044732Sdavemq 			pma_pmd_dev_fd[i] = 0;
58054732Sdavemq 		}
58064732Sdavemq 
58074977Sraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
58084732Sdavemq 
58094732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
58104732Sdavemq 			pcs_dev_fd[i] = 1;
58114732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
58126604Ssbehera 			    "dev %x found", i, pcs_dev_id));
58136261Sjoycey 			if (pma_pmd_dev_fd[i] == 1) {
58146261Sjoycey 				port_pcs_dev_id[j - 1] = pcs_dev_id &
58154782Ssbehera 				    BCM_PHY_ID_MASK;
58166261Sjoycey 			} else {
58176261Sjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
58186261Sjoycey 					port_pcs_dev_id[j] = pcs_dev_id &
58196261Sjoycey 					    BCM_PHY_ID_MASK;
58206261Sjoycey 					port_fd_arr[j] = (uint8_t)i;
58216261Sjoycey 					j++;
58226261Sjoycey 				}
58234732Sdavemq 			}
58244732Sdavemq 		} else {
58254732Sdavemq 			pcs_dev_fd[i] = 0;
58264732Sdavemq 		}
58274732Sdavemq 
58285572Ssbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
58295572Ssbehera 			total_port_fd ++;
58305572Ssbehera 		}
58314732Sdavemq 
58324977Sraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
58334732Sdavemq 
58344732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
58355572Ssbehera 			total_phy_fd ++;
58364732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
58376604Ssbehera 			    "%x found", i, phy_id));
58384782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
58394782Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
58405572Ssbehera 				phy_fd_arr[l] = (uint8_t)i;
58414732Sdavemq 				l++;
58424732Sdavemq 			}
58434732Sdavemq 		}
58444732Sdavemq 	}
58454732Sdavemq 
58464732Sdavemq 	switch (total_port_fd) {
58474732Sdavemq 	case 2:
58484732Sdavemq 		switch (total_phy_fd) {
58494732Sdavemq 		case 2:
58506261Sjoycey 			/* 2 10G, 2 1G RGMII Fiber */
58516261Sjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
58526261Sjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
58536261Sjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
58546261Sjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
58556261Sjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
58566261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
58576261Sjoycey 
58586261Sjoycey 				hw_p->platform_type =
58596261Sjoycey 					    P_NEPTUNE_GENERIC;
58606261Sjoycey 
58616261Sjoycey 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
58626261Sjoycey 
58636261Sjoycey 				hw_p->xcvr_addr[0] = port_fd_arr[0];
58646261Sjoycey 				hw_p->xcvr_addr[1] = port_fd_arr[1];
58656261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
58666261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
58676261Sjoycey 
58686261Sjoycey 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
58696261Sjoycey 				    "ARTM card with 2 10G, 2 1G"));
58706261Sjoycey 			} else {
58716261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58726261Sjoycey 				    "Unsupported neptune type 1"));
58736261Sjoycey 				goto error_exit;
58746261Sjoycey 			}
58756261Sjoycey 			break;
58766261Sjoycey 
58774732Sdavemq 		case 1:
58784732Sdavemq 			/* TODO - 2 10G, 1 1G */
58794732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
58804732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
58814732Sdavemq 			goto error_exit;
58824732Sdavemq 		case 0:
58834732Sdavemq 			/* 2 10G */
58844782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
58854782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
58864782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
58876604Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
58886604Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
58896604Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
58906604Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
58916604Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
58926604Ssbehera 			    (port_pma_pmd_dev_id[1] ==
58936604Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
58944977Sraghus 
58954977Sraghus 				/*
58964977Sraghus 				 * Check the first phy port address against
58974977Sraghus 				 * the known phy start addresses to determine
58984977Sraghus 				 * the platform type.
58994977Sraghus 				 */
59005572Ssbehera 
59015572Ssbehera 				switch (port_fd_arr[0]) {
59025572Ssbehera 				case BCM8704_NEPTUNE_PORT_ADDR_BASE:
59036604Ssbehera 					/*
59046604Ssbehera 					 * The Marvell case also falls into
59056604Ssbehera 					 * this case as
59066604Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
59076604Ssbehera 					 * == BCM8704_NEPTUNE_PORT_ADDR_BASE.
59086604Ssbehera 					 * This is OK for the 2 10G case.
59096604Ssbehera 					 */
59104977Sraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
59114977Sraghus 					hw_p->platform_type =
59124977Sraghus 					    P_NEPTUNE_ATLAS_2PORT;
59135572Ssbehera 					break;
59145572Ssbehera 				case BCM8706_GOA_PORT_ADDR_BASE:
59155572Ssbehera 					if (hw_p->platform_type !=
59165572Ssbehera 					    P_NEPTUNE_NIU) {
59175572Ssbehera 						hw_p->platform_type =
59185572Ssbehera 						    P_NEPTUNE_GENERIC;
59195572Ssbehera 						hw_p->niu_type =
59205572Ssbehera 						    NEPTUNE_2_10GF;
59215572Ssbehera 					}
59225572Ssbehera 					break;
59235572Ssbehera 				default:
59245572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
59254977Sraghus 					    "Unsupported neptune type 2 - 1"));
59264977Sraghus 					goto error_exit;
59274977Sraghus 				}
59285572Ssbehera 
59295572Ssbehera 				for (i = 0; i < 2; i++) {
59305572Ssbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
59315572Ssbehera 				}
59324732Sdavemq 			} else {
59334732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
59344732Sdavemq 				    "Unsupported neptune type 2"));
59354732Sdavemq 				goto error_exit;
59364732Sdavemq 			}
59374732Sdavemq 			break;
59384732Sdavemq 		case 4:
59394732Sdavemq 			/* Maramba with 2 XAUI */
59404782Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
59414782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
59424782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
59434782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
59444782Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
59454782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
59464782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
59474782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
59484732Sdavemq 
59494732Sdavemq 				/*
59504732Sdavemq 				 * Check the first phy port address against
59514732Sdavemq 				 * the known phy start addresses to determine
59524732Sdavemq 				 * the platform type.
59534732Sdavemq 				 */
59545572Ssbehera 				switch (phy_fd_arr[0]) {
59555572Ssbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
59564732Sdavemq 					hw_p->platform_type =
59574732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
59585572Ssbehera 					break;
59595572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
59604732Sdavemq 					hw_p->platform_type =
59614732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
59625572Ssbehera 					break;
59635572Ssbehera 				default:
59644732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
59654732Sdavemq 					    "Unknown port %d...Cannot "
59664732Sdavemq 					    "determine platform type", i));
59674977Sraghus 					goto error_exit;
59684732Sdavemq 				}
59695572Ssbehera 
59704977Sraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
59714977Sraghus 
59725572Ssbehera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
59735572Ssbehera 				hw_p->xcvr_addr[1] = port_fd_arr[1];
59745572Ssbehera 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
59755572Ssbehera 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
59765572Ssbehera 
59774732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
59784732Sdavemq 				    "Maramba with 2 XAUI"));
59794732Sdavemq 			} else {
59804732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
59814732Sdavemq 				    "Unsupported neptune type 3"));
59824732Sdavemq 				goto error_exit;
59834732Sdavemq 			}
59844732Sdavemq 			break;
59854732Sdavemq 		default:
59864732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
59874732Sdavemq 			    "Unsupported neptune type 5"));
59884732Sdavemq 			goto error_exit;
59894732Sdavemq 		}
59904782Ssbehera 		break;
59914732Sdavemq 	case 1:
59924732Sdavemq 		switch (total_phy_fd) {
59934732Sdavemq 		case 3:
59944977Sraghus 			/*
59954977Sraghus 			 * TODO 3 1G, 1 10G mode.
59964977Sraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
59974977Sraghus 			 * 1_10G_3_1G
59984977Sraghus 			 */
59994977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60004977Sraghus 			    "Unsupported neptune type 7"));
60014977Sraghus 			goto error_exit;
60024732Sdavemq 		case 2:
60034732Sdavemq 			/*
60044732Sdavemq 			 * TODO 2 1G, 1 10G mode.
60054732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
60064732Sdavemq 			 * 1_10G_2_1G
60074732Sdavemq 			 */
60084732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60094732Sdavemq 			    "Unsupported neptune type 8"));
60104732Sdavemq 			goto error_exit;
60114732Sdavemq 		case 1:
60124732Sdavemq 			/*
60134732Sdavemq 			 * TODO 1 1G, 1 10G mode.
60144732Sdavemq 			 * Differentiate between 1_1G_1_10G and
60154732Sdavemq 			 * 1_10G_1_1G
60164732Sdavemq 			 */
60174732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60184732Sdavemq 			    "Unsupported neptune type 9"));
60194732Sdavemq 			goto error_exit;
60204732Sdavemq 		case 0:
60215572Ssbehera 			/* 1 10G mode, N2 with 1 XAUI */
60225572Ssbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
60235572Ssbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
60245572Ssbehera 
60255572Ssbehera 				/*
60265572Ssbehera 				 * Check the first phy port address against
60275572Ssbehera 				 * the known phy start addresses to determine
60285572Ssbehera 				 * the platform type.
60295572Ssbehera 				 */
60305572Ssbehera 
60315572Ssbehera 				switch (port_fd_arr[0]) {
60325572Ssbehera 				case BCM8704_N2_PORT_ADDR_BASE:
60335572Ssbehera 				case (BCM8704_N2_PORT_ADDR_BASE + 1):
60345572Ssbehera 				case BCM8706_ALT_GOA_PORT1_ADDR:
60355572Ssbehera 					if (hw_p->platform_type !=
60365572Ssbehera 					    P_NEPTUNE_NIU) {
60375572Ssbehera 						hw_p->platform_type =
60385572Ssbehera 						    P_NEPTUNE_GENERIC;
60395572Ssbehera 						hw_p->niu_type =
60405572Ssbehera 						    NEPTUNE_2_10GF;
60415572Ssbehera 					}
60425572Ssbehera 					break;
60435572Ssbehera 				default:
60445572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
60455572Ssbehera 					    "Unsupported neptune type 10"));
60465572Ssbehera 					goto error_exit;
60475572Ssbehera 				}
60486075Ssbehera 				/*
60496075Ssbehera 				 * For GOA, which is a hot swappable PHY, the
60506075Ssbehera 				 * phy address to function number mapping
60516075Ssbehera 				 * should be preserved, i.e., addr 16 is
60526075Ssbehera 				 * assigned to function 0 and 20 to function 1
60536075Ssbehera 				 * But for Huron XAUI, the assignment should
60546075Ssbehera 				 * be by function number, i.e., whichever
60556075Ssbehera 				 * function number attaches should be
60566075Ssbehera 				 * assigned the available PHY (this is required
60576075Ssbehera 				 * primarily to support pre-production Huron
60586075Ssbehera 				 * boards where function 0 is mapped to addr 17
60596075Ssbehera 				 */
60606075Ssbehera 				if (port_fd_arr[0] ==
60616075Ssbehera 				    BCM8706_ALT_GOA_PORT1_ADDR) {
60626075Ssbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
60636075Ssbehera 				} else {
60646075Ssbehera 					hw_p->xcvr_addr[nxgep->function_num] =
60656075Ssbehera 					    port_fd_arr[0];
60666075Ssbehera 				}
60675572Ssbehera 			} else {
60685572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60695572Ssbehera 				    "Unsupported neptune type 10 - 1"));
60705572Ssbehera 				goto error_exit;
60715572Ssbehera 			}
60725572Ssbehera 			break;
60734732Sdavemq 		case 4:
60744732Sdavemq 			/* Maramba with 1 XAUI */
60754782Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
60764782Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
60774732Sdavemq 
60784732Sdavemq 				/*
60794732Sdavemq 				 * Check the first phy port address against
60804732Sdavemq 				 * the known phy start addresses to determine
60814732Sdavemq 				 * the platform type.
60824732Sdavemq 				 */
60835572Ssbehera 				switch (phy_fd_arr[0]) {
60845572Ssbehera 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
60854732Sdavemq 					hw_p->platform_type =
60864732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
60875572Ssbehera 					break;
60885572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
60894732Sdavemq 					hw_p->platform_type =
60904732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
60915572Ssbehera 					break;
60925572Ssbehera 				default:
60934732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
60944732Sdavemq 					    "Unknown port %d...Cannot "
60955572Ssbehera 					    "determine platform type 10 - 2",
60965572Ssbehera 					    i));
60974977Sraghus 					goto error_exit;
60984977Sraghus 				}
60994977Sraghus 
61005572Ssbehera 				/*
61015572Ssbehera 				 * Check the BCM8704 address to determine
61025572Ssbehera 				 * if XAUI is in port 0 or port 1.
61035572Ssbehera 				 */
61045572Ssbehera 				switch (port_fd_arr[0]) {
61055572Ssbehera 				case BCM8704_MARAMBA_PORT_ADDR_BASE:
61065572Ssbehera 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
61075572Ssbehera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
61085572Ssbehera 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
61095572Ssbehera 						hw_p->xcvr_addr[i] =
61105572Ssbehera 						    phy_fd_arr[i];
61114977Sraghus 					}
61125572Ssbehera 					break;
61135572Ssbehera 				case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1):
61144977Sraghus 					hw_p->niu_type =
61154977Sraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
61165572Ssbehera 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
61175572Ssbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
61185572Ssbehera 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
61195572Ssbehera 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
61205572Ssbehera 					break;
61215572Ssbehera 				default:
61224977Sraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61234977Sraghus 					    "Unsupported neptune type 11"));
61244977Sraghus 					goto error_exit;
61254732Sdavemq 				}
61264732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61274732Sdavemq 				    "Maramba with 1 XAUI"));
61284732Sdavemq 			} else {
61294732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61304732Sdavemq 				    "Unsupported neptune type 12"));
61314732Sdavemq 				goto error_exit;
61324732Sdavemq 			}
61334732Sdavemq 			break;
61344732Sdavemq 		default:
61354732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61364732Sdavemq 			    "Unsupported neptune type 13"));
61374732Sdavemq 			goto error_exit;
61384732Sdavemq 		}
61394732Sdavemq 		break;
61404732Sdavemq 	case 0:
61414732Sdavemq 		switch (total_phy_fd) {
61424732Sdavemq 		case 4:
61434782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
61444782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
61454782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
61464782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
61474732Sdavemq 
61484732Sdavemq 				/*
61494732Sdavemq 				 * Check the first phy port address against
61504732Sdavemq 				 * the known phy start addresses to determine
61514732Sdavemq 				 * the platform type.
61524732Sdavemq 				 */
61535572Ssbehera 				switch (phy_fd_arr[0]) {
61545572Ssbehera 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
61554732Sdavemq 					hw_p->platform_type =
61564732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
61575572Ssbehera 					break;
61585572Ssbehera 				case BCM5464_NEPTUNE_PORT_ADDR_BASE:
61594977Sraghus 					hw_p->platform_type =
61604977Sraghus 					    P_NEPTUNE_ATLAS_4PORT;
61615572Ssbehera 					break;
61625572Ssbehera 				default:
61634977Sraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
61644977Sraghus 					    "Unknown port %d...Cannot "
61654977Sraghus 					    "determine platform type", i));
61664977Sraghus 					goto error_exit;
61674732Sdavemq 				}
61684977Sraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
61695572Ssbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
61705572Ssbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
61715572Ssbehera 				}
61724732Sdavemq 			} else {
61734732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61744732Sdavemq 				    "Unsupported neptune type 14"));
61754732Sdavemq 				goto error_exit;
61764732Sdavemq 			}
61774732Sdavemq 			break;
61784732Sdavemq 		case 3:
61794732Sdavemq 			/* TODO 3 1G mode */
61804732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61814732Sdavemq 			    "Unsupported neptune type 15"));
61824732Sdavemq 			goto error_exit;
61834732Sdavemq 		case 2:
61844732Sdavemq 			/* TODO 2 1G mode */
61856261Sjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
61866261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
61876261Sjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
61886261Sjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
61896261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
61906261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
61916261Sjoycey 			} else {
61926261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
61936261Sjoycey 				    "Unsupported neptune type 16"));
61946261Sjoycey 				goto error_exit;
61956261Sjoycey 			}
61964732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61976261Sjoycey 			    "2 RGMII Fiber ports - RTM"));
61986261Sjoycey 			break;
61996261Sjoycey 
62004732Sdavemq 		case 1:
62014732Sdavemq 			/* TODO 1 1G mode */
62024732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62034732Sdavemq 			    "Unsupported neptune type 17"));
62044732Sdavemq 			goto error_exit;
62054732Sdavemq 		default:
62064732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62074732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
62084732Sdavemq 			    total_phy_fd));
62094732Sdavemq 			goto error_exit;
62104732Sdavemq 		}
62114732Sdavemq 		break;
62124732Sdavemq 	default:
62134732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62144732Sdavemq 		    "Unsupported neptune type 19"));
62154732Sdavemq 		goto error_exit;
62164732Sdavemq 	}
62174732Sdavemq 
62184732Sdavemq scan_exit:
62194732Sdavemq 
62204732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
62214732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
62224732Sdavemq 	return (status);
62234732Sdavemq 
62244732Sdavemq error_exit:
62254732Sdavemq 	return (NXGE_ERROR);
62264732Sdavemq }
62274732Sdavemq 
62284185Sspeer boolean_t
62294185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
62304185Sspeer {
62314185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
62324185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
62334185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
62344185Sspeer 		return (B_FALSE);
62354185Sspeer 	else
62364185Sspeer 		return (B_TRUE);
62374185Sspeer }
62384732Sdavemq 
62394732Sdavemq static void
62404732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
62414732Sdavemq 
62424732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
62434732Sdavemq 	uint8_t xcvr_portn;
62444732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
62454732Sdavemq 
62464732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
62474732Sdavemq 
62484732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
62494732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
62504732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
62514732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
62524732Sdavemq 	}
62534732Sdavemq 	/*
62544732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
62554732Sdavemq 	 * swapped with ethernet port number. This is
62564732Sdavemq 	 * designed for better signal integrity in routing.
62574732Sdavemq 	 */
62584732Sdavemq 	switch (portn) {
62594732Sdavemq 	case 0:
62604732Sdavemq 		xcvr_portn += 3;
62614732Sdavemq 		break;
62624732Sdavemq 	case 1:
62634732Sdavemq 		xcvr_portn += 2;
62644732Sdavemq 		break;
62654732Sdavemq 	case 2:
62664732Sdavemq 		xcvr_portn += 1;
62674732Sdavemq 		break;
62684732Sdavemq 	case 3:
62694732Sdavemq 	default:
62704732Sdavemq 		break;
62714732Sdavemq 	}
62724732Sdavemq 
62736075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62744732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
62754732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
62764732Sdavemq 	if (rs != NPI_SUCCESS) {
62774732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
62784732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
62794732Sdavemq 		    "returned error 0x[%x]", rs));
62806075Ssbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62814732Sdavemq 		return;
62824732Sdavemq 	}
62834732Sdavemq 
62844732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
62854732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
62864732Sdavemq 	if (rs != NPI_SUCCESS) {
62874732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
62884732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
62894732Sdavemq 		    "returned error 0x[%x]", rs));
62904732Sdavemq 	}
62914732Sdavemq 
62926075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62934732Sdavemq }
62945196Ssbehera 
62955196Ssbehera static nxge_status_t
62965196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
62975196Ssbehera {
62985196Ssbehera 	p_nxge_stats_t	statsp;
62995196Ssbehera 	uint8_t		xcvr_portn;
63005196Ssbehera 	p_mii_regs_t	mii_regs;
63015196Ssbehera 	mii_mode_control_stat_t	mode;
63025196Ssbehera 	int		status = NXGE_OK;
63035196Ssbehera 
63045196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
63055196Ssbehera 
63065196Ssbehera 	statsp = nxgep->statsp;
63075196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
63085196Ssbehera 	mii_regs = NULL;
63095196Ssbehera 	mode.value = 0;
63105203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
63115196Ssbehera #if defined(__i386)
63125196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
63135196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
63145196Ssbehera 	    mode.value)) != NXGE_OK) {
63155196Ssbehera 		goto fail;
63165196Ssbehera #else
63175196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
63185196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
63195196Ssbehera 	    mode.value)) != NXGE_OK) {
63205196Ssbehera 		goto fail;
63215196Ssbehera #endif
63225196Ssbehera 	}
63235196Ssbehera #if defined(__i386)
63245196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
63255196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
63265196Ssbehera 	    &mode.value)) != NXGE_OK) {
63275196Ssbehera 		goto fail;
63285196Ssbehera 	}
63295196Ssbehera #else
63305196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
63315196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
63325196Ssbehera 	    &mode.value)) != NXGE_OK) {
63335196Ssbehera 		goto fail;
63345196Ssbehera 	}
63355196Ssbehera #endif
63365196Ssbehera 
63375196Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
63385196Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
63395196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63405196Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
63415196Ssbehera 	}
63425196Ssbehera 
63435196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63445196Ssbehera 	    "nxge_mii_get_link_mode: "
63455196Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
63465203Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
63475196Ssbehera 	    mode.value, nxgep->mac.portmode));
63485196Ssbehera 
63495196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63505196Ssbehera 	    "<== nxge_mii_get_link_mode"));
63515196Ssbehera 	return (status);
63525196Ssbehera fail:
63535196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
63545196Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
63555196Ssbehera 	return (NXGE_ERROR);
63565196Ssbehera }
63575196Ssbehera 
63586439Sml29623 nxge_status_t
63596439Sml29623 nxge_mac_set_framesize(p_nxge_t nxgep)
63606439Sml29623 {
63616439Sml29623 	npi_attr_t		ap;
63626439Sml29623 	uint8_t			portn;
63636439Sml29623 	npi_handle_t		handle;
63646439Sml29623 	npi_status_t		rs = NPI_SUCCESS;
63656439Sml29623 
63666439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
63676439Sml29623 
63686439Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
63696439Sml29623 	handle = nxgep->npi_handle;
63706439Sml29623 
63716439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63726439Sml29623 	    "==> nxge_mac_sec_framesize: port<%d> "
63736439Sml29623 	    "min framesize %d max framesize %d ",
63746439Sml29623 	    portn,
63756439Sml29623 	    nxgep->mac.minframesize,
63766439Sml29623 	    nxgep->mac.maxframesize));
63776439Sml29623 
63786439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
63796439Sml29623 	    MAC_PORT_FRAME_SIZE,
63806439Sml29623 	    nxgep->mac.minframesize,
63816439Sml29623 	    nxgep->mac.maxframesize,
63826439Sml29623 	    rs);
63836439Sml29623 	if (rs != NPI_SUCCESS) {
63846439Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63856439Sml29623 		    "<== nxge_mac_set_framesize: failed to configure "
63866439Sml29623 		    "max/min frame size port %d", portn));
63876439Sml29623 
63886439Sml29623 		return (NXGE_ERROR | rs);
63896439Sml29623 	}
63906439Sml29623 
63916439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63926439Sml29623 	    "<== nxge_mac_set_framesize: port<%d>", portn));
63936439Sml29623 
63946439Sml29623 	return (NXGE_OK);
63956439Sml29623 }
63966439Sml29623 
63975196Ssbehera #ifdef NXGE_DEBUG
63985196Ssbehera static void
63995196Ssbehera nxge_mii_dump(p_nxge_t nxgep)
64005196Ssbehera {
64015196Ssbehera 	p_nxge_stats_t	statsp;
64025196Ssbehera 	uint8_t		xcvr_portn;
64035196Ssbehera 	p_mii_regs_t	mii_regs;
64045196Ssbehera 	mii_bmcr_t	bmcr;
64055196Ssbehera 	mii_bmsr_t	bmsr;
64065196Ssbehera 	mii_idr1_t	idr1;
64075196Ssbehera 	mii_idr2_t	idr2;
64085196Ssbehera 	mii_mode_control_stat_t	mode;
64096495Sspeer 	p_nxge_param_t	param_arr;
64105196Ssbehera 
64115196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
64125196Ssbehera 
64135196Ssbehera 	statsp = nxgep->statsp;
64145196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
64155196Ssbehera 
64165196Ssbehera 	mii_regs = NULL;
64175196Ssbehera 
64185196Ssbehera #if defined(__i386)
64195196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
64205196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
64215196Ssbehera #else
64225196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
64235196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
64245196Ssbehera #endif
64255196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64265196Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
64275196Ssbehera 	    xcvr_portn, bmcr.value));
64285196Ssbehera 
64295196Ssbehera #if defined(__i386)
64305196Ssbehera 	(void) nxge_mii_read(nxgep,
64315196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64325196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
64335196Ssbehera #else
64345196Ssbehera 	(void) nxge_mii_read(nxgep,
64355196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64365196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
64375196Ssbehera #endif
64385196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64395196Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
64405196Ssbehera 	    xcvr_portn, bmsr.value));
64415196Ssbehera 
64425196Ssbehera #if defined(__i386)
64435196Ssbehera 	(void) nxge_mii_read(nxgep,
64445196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64455196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
64465196Ssbehera #else
64475196Ssbehera 	(void) nxge_mii_read(nxgep,
64485196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64495196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
64505196Ssbehera #endif
64515196Ssbehera 
64525196Ssbehera 
64535196Ssbehera #if defined(__i386)
64545196Ssbehera 	(void) nxge_mii_read(nxgep,
64555196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64565196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
64575196Ssbehera #else
64585196Ssbehera 	(void) nxge_mii_read(nxgep,
64595196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
64605196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
64615196Ssbehera #endif
64625196Ssbehera 
64635196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64645196Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
64655196Ssbehera 	    xcvr_portn, idr1.value));
64665196Ssbehera 
64675196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64685196Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
64695196Ssbehera 	    xcvr_portn, idr2.value));
64705196Ssbehera 
64715196Ssbehera 	mode.value = 0;
64725203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
64735196Ssbehera 
64745196Ssbehera #if defined(__i386)
64755196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
64765196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
64775196Ssbehera 
64785196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
64795196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
64805196Ssbehera #else
64815196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
64825196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
64835196Ssbehera 
64845196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
64855196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
64865196Ssbehera #endif
64875196Ssbehera 
64885196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64895196Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
64905196Ssbehera 	    xcvr_portn, mode.value));
64915196Ssbehera }
64925196Ssbehera #endif
6493