xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 5125:43f30c4f3307)
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 /*
223859Sml29623  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <sys/nxge/nxge_impl.h>
293859Sml29623 #include <sys/nxge/nxge_mac.h>
303859Sml29623 
314693Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
324693Stm144005 #define	LM_WAIT_MULTIPLIER	8
334693Stm144005 
343859Sml29623 extern uint32_t nxge_no_link_notify;
354732Sdavemq extern boolean_t nxge_no_msg;
363859Sml29623 extern uint32_t nxge_lb_dbg;
373859Sml29623 extern nxge_os_mutex_t	nxge_mdio_lock;
383859Sml29623 extern nxge_os_mutex_t	nxge_mii_lock;
393859Sml29623 extern boolean_t nxge_jumbo_enable;
403859Sml29623 
414693Stm144005 typedef enum {
424693Stm144005 	CHECK_LINK_RESCHEDULE,
434693Stm144005 	CHECK_LINK_STOP
444693Stm144005 } check_link_state_t;
454693Stm144005 
464693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
474693Stm144005 
483859Sml29623 /*
493859Sml29623  * Ethernet broadcast address definition.
503859Sml29623  */
513859Sml29623 static ether_addr_st etherbroadcastaddr =
523859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
534732Sdavemq /*
544732Sdavemq  * Ethernet zero address definition.
554732Sdavemq  */
564185Sspeer static ether_addr_st etherzeroaddr =
574185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
584732Sdavemq /*
594732Sdavemq  * Supported chip types
604732Sdavemq  */
614732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
624732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
634732Sdavemq 
644732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
654732Sdavemq 				sizeof (uint32_t))
664732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
674732Sdavemq 				sizeof (uint32_t))
684732Sdavemq /*
694732Sdavemq  * static functions
704732Sdavemq  */
714977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
724977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
734977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
744732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
754732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
764732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
774732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
784732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
794732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
804732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
814732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
824732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
834732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
844732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
854732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
864732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
874732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
884732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
894732Sdavemq 
904732Sdavemq /*
914732Sdavemq  * xcvr tables for supported transceivers
924732Sdavemq  */
934732Sdavemq 
944977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
954732Sdavemq 	nxge_n2_serdes_init,
964732Sdavemq 	nxge_10G_xcvr_init,
974732Sdavemq 	nxge_10G_link_intr_stop,
984732Sdavemq 	nxge_10G_link_intr_start,
994732Sdavemq 	nxge_check_10g_link,
1004732Sdavemq 	PCS_XCVR,
1014732Sdavemq 	BCM8704_N2_PORT_ADDR_BASE
1024732Sdavemq };
1034732Sdavemq 
1044977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1054977Sraghus 	nxge_n2_serdes_init,
1064977Sraghus 	nxge_1G_xcvr_init,
1074977Sraghus 	nxge_1G_fiber_link_intr_stop,
1084977Sraghus 	nxge_1G_fiber_link_intr_start,
1094977Sraghus 	nxge_check_mii_link,
1104977Sraghus 	PCS_XCVR,
1114977Sraghus 	0
1124977Sraghus };
1134977Sraghus 
1144732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
1154732Sdavemq 	nxge_neptune_10G_serdes_init,
1164732Sdavemq 	nxge_10G_xcvr_init,
1174732Sdavemq 	nxge_10G_link_intr_stop,
1184732Sdavemq 	nxge_10G_link_intr_start,
1194732Sdavemq 	nxge_check_10g_link,
1204732Sdavemq 	PCS_XCVR,
1214732Sdavemq 	BCM8704_NEPTUNE_PORT_ADDR_BASE
1224732Sdavemq };
1234732Sdavemq 
1244732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
1254732Sdavemq 	NULL,
1264732Sdavemq 	nxge_1G_xcvr_init,
1274732Sdavemq 	nxge_1G_copper_link_intr_stop,
1284732Sdavemq 	nxge_1G_copper_link_intr_start,
1294732Sdavemq 	nxge_check_mii_link,
1304732Sdavemq 	INT_MII_XCVR,
1314732Sdavemq 	BCM5464_NEPTUNE_PORT_ADDR_BASE
1324732Sdavemq };
1334732Sdavemq 
1344732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
1354732Sdavemq 	nxge_1G_serdes_init,
1364732Sdavemq 	nxge_1G_xcvr_init,
1374732Sdavemq 	nxge_1G_fiber_link_intr_stop,
1384732Sdavemq 	nxge_1G_fiber_link_intr_start,
1394732Sdavemq 	nxge_check_mii_link,
1404732Sdavemq 	PCS_XCVR,
1414732Sdavemq 	0
1424732Sdavemq };
1434732Sdavemq 
1444732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
1454732Sdavemq 	nxge_neptune_10G_serdes_init,
1464732Sdavemq 	NULL,
1474732Sdavemq 	NULL,
1484732Sdavemq 	NULL,
1494977Sraghus 	NULL,
1504732Sdavemq 	PCS_XCVR,
1514732Sdavemq 	0
1524732Sdavemq };
1533859Sml29623 
1543859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
1553859Sml29623 
1564977Sraghus nxge_status_t
1574977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep)
1584977Sraghus {
1594977Sraghus 	nxge_status_t status = NXGE_OK;
1604977Sraghus 	char *phy_type;
1614977Sraghus 	char *prop_val;
1624977Sraghus 
1634977Sraghus 	nxgep->mac.portmode = 0;
1644977Sraghus 
1654977Sraghus 	/* Get property from the driver conf. file */
1664977Sraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
1674977Sraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1684977Sraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
1694977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1704977Sraghus 		    "found  conf file: phy-type %s", prop_val));
1714977Sraghus 		if (strcmp("xgsd", prop_val) == 0) {
1724977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
1734977Sraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
1744977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1754977Sraghus 			    "found: 10G Serdes"));
1764977Sraghus 		} else if (strcmp("gsd", prop_val) == 0) {
1774977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
1784977Sraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
1794977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
1804977Sraghus 		} else if (strcmp("mif", prop_val) == 0) {
1814977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
1824977Sraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
1834977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
1844977Sraghus 		} else if (strcmp("pcs", prop_val) == 0) {
1854977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
1864977Sraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
1874977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
1884977Sraghus 		}
1894977Sraghus 
1904977Sraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
1914977Sraghus 		    "phy-type", prop_val);
1924977Sraghus 		ddi_prop_free(prop_val);
1934977Sraghus 
1944977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
1954977Sraghus 		    "Got phy type [0x%x] from conf file",
1964977Sraghus 		    nxgep->mac.portmode));
1974977Sraghus 
1984977Sraghus 		return (NXGE_OK);
1994977Sraghus 	}
2004977Sraghus /*
2014977Sraghus  * TODO add MDIO support for Monza RTM card, Glendale (also Goa) -
2024977Sraghus  * only N2-NIU
2034977Sraghus  */
2044977Sraghus 	if (nxgep->niu_type == N2_NIU) {
2054977Sraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
2064977Sraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
2074977Sraghus 			if (strcmp("xgf", prop_val) == 0) {
2084977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2094977Sraghus 				    XPCS_XCVR;
2104977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
2114977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2124977Sraghus 				    "10G Fiber Xcvr"));
2134977Sraghus 			} else if (strcmp("mif", prop_val) == 0) {
2144977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2154977Sraghus 				    INT_MII_XCVR;
2164977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
2174977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2184977Sraghus 				    "1G Copper Xcvr"));
2194977Sraghus 			} else if (strcmp("pcs", prop_val) == 0) {
2204977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2214977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
2224977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2234977Sraghus 				    "1G Fiber Xcvr"));
2244977Sraghus 			} else if (strcmp("xgc", prop_val) == 0) {
2254977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
2264977Sraghus 				    XPCS_XCVR;
2274977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
2284977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2294977Sraghus 				    "10G Copper Xcvr"));
2304977Sraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
2314977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2324977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
2334977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2344977Sraghus 				    "OBP: 10G Serdes"));
2354977Sraghus 			} else if (strcmp("gsd", prop_val) == 0) {
2364977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2374977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
2384977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2394977Sraghus 				    "OBP: 1G Serdes"));
2404977Sraghus 			} else {
2414977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2424977Sraghus 				    "Unknown phy-type: %s", prop_val));
2434977Sraghus 				ddi_prop_free(prop_val);
2444977Sraghus 				return (NXGE_ERROR);
2454977Sraghus 			}
2464977Sraghus 			status = NXGE_OK;
2474977Sraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
2484977Sraghus 			    nxgep->dip, "phy-type", prop_val);
2494977Sraghus 			ddi_prop_free(prop_val);
2504977Sraghus 
2514977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
2524977Sraghus 			    "Got phy type [0x%x] from OBP",
2534977Sraghus 			    nxgep->mac.portmode));
2544977Sraghus 
2554977Sraghus 			return (status);
2564977Sraghus 		} else {
2574977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2584977Sraghus 			    "Exiting...phy-type property not found"));
2594977Sraghus 			return (NXGE_ERROR);
2604977Sraghus 		}
2614977Sraghus 	}
2624977Sraghus 
2634977Sraghus 
2644977Sraghus 	if (!nxgep->vpd_info.present) {
2654977Sraghus 		return (NXGE_OK);
2664977Sraghus 	}
2674977Sraghus 
2684977Sraghus 	if (!nxgep->vpd_info.ver_valid) {
2694977Sraghus 		goto read_seeprom;
2704977Sraghus 	}
2714977Sraghus 
2724977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2734977Sraghus 	    "Reading phy type from expansion ROM"));
2744977Sraghus 	/*
2754977Sraghus 	 * Try to read the phy type from the vpd data read off the
2764977Sraghus 	 * expansion ROM.
2774977Sraghus 	 */
2784977Sraghus 	phy_type = nxgep->vpd_info.phy_type;
2794977Sraghus 
2804977Sraghus 	if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') {
2814977Sraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
2824977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
2834977Sraghus 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
2844977Sraghus 	    phy_type[2] == 'f') {
2854977Sraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
2864977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2874977Sraghus 	} else if (phy_type[0] == 'p' && phy_type[1] == 'c' &&
2884977Sraghus 	    phy_type[2] == 's') {
2894977Sraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
2904977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
2914977Sraghus 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
2924977Sraghus 	    phy_type[2] == 'c') {
2934977Sraghus 		nxgep->mac.portmode = PORT_10G_COPPER;
2944977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2954977Sraghus 	} else {
2964977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2974977Sraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
2984977Sraghus 		    phy_type[0], phy_type[1], phy_type[2]));
2994977Sraghus 		goto read_seeprom;
3004977Sraghus 	}
3014977Sraghus 
3024977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3034977Sraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
3044977Sraghus 
3054977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
3064977Sraghus 	return (status);
3074977Sraghus 
3084977Sraghus read_seeprom:
3094977Sraghus 	/*
3104977Sraghus 	 * read the phy type from the SEEPROM - NCR registers
3114977Sraghus 	 */
3124977Sraghus 	status = nxge_espc_phy_type_get(nxgep);
3134977Sraghus 	if (status != NXGE_OK) {
3144977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3154977Sraghus 		    "Failed to get phy type"));
3164977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3174977Sraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
3184977Sraghus 	}
3194977Sraghus 
3204977Sraghus 	return (status);
3214977Sraghus 
3224977Sraghus }
3234977Sraghus 
3244732Sdavemq /* Set up the PHY specific values. */
3254732Sdavemq 
3264732Sdavemq nxge_status_t
3274732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
3284732Sdavemq {
3294732Sdavemq 	nxge_status_t	status = NXGE_OK;
3304732Sdavemq 	uint32_t	port_type;
3314732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3324977Sraghus 	uint32_t	pcs_id = 0;
3334977Sraghus 	uint32_t	pma_pmd_id = 0;
3344977Sraghus 	uint32_t	phy_id = 0;
3354732Sdavemq 
3364732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
3374732Sdavemq 	    portn));
3384732Sdavemq 
3394977Sraghus 	switch (nxgep->niu_type) {
3404977Sraghus 	case N2_NIU:
3414977Sraghus 		switch (nxgep->mac.portmode) {
3424977Sraghus 		case PORT_1G_FIBER:
3434977Sraghus 		case PORT_1G_SERDES:
3444977Sraghus 			nxgep->xcvr = nxge_n2_1G_table;
3454977Sraghus 			nxgep->xcvr.xcvr_addr = portn;
3464977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
3474977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
3484977Sraghus 			    "Serdes"));
3494977Sraghus 			break;
3504977Sraghus 		case PORT_10G_FIBER:
3514977Sraghus 		case PORT_10G_SERDES:
3524977Sraghus 			nxgep->xcvr = nxge_n2_10G_table;
3534977Sraghus 			nxgep->xcvr.xcvr_addr += portn;
3544977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
3554977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
3564977Sraghus 			    "Serdes"));
3574977Sraghus 			break;
3584977Sraghus 		default:
3594977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3604977Sraghus 			    "<== nxge_setup_xcvr_table: "
3614977Sraghus 			    "Unable to determine NIU portmode"));
3624977Sraghus 			return (NXGE_ERROR);
3634977Sraghus 		}
3644977Sraghus 		break;
3654977Sraghus 	default:
3664977Sraghus 		if (nxgep->mac.portmode == 0) {
3674977Sraghus 			/*
3684977Sraghus 			 * Would be the case for platforms like Maramba
3694977Sraghus 			 * in which the phy type could not be got from conf
3704977Sraghus 			 * file, OBP, VPD or Serial PROM.
3714977Sraghus 			 */
3724977Sraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
3734977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3744977Sraghus 				    "<== nxge_setup_xcvr_table:"
3754977Sraghus 				    " Invalid Neptune type [0x%x]",
3764977Sraghus 				    nxgep->niu_type));
3774977Sraghus 				return (NXGE_ERROR);
3784977Sraghus 			}
3794977Sraghus 
3804977Sraghus 			port_type = nxgep->niu_type >>
3814977Sraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
3824977Sraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
3834977Sraghus 
3844977Sraghus 			switch (port_type) {
3854977Sraghus 
3864977Sraghus 			case NXGE_PORT_1G_COPPER:
3874977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
3884977Sraghus 				break;
3894977Sraghus 			case NXGE_PORT_10G_COPPER:
3904977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
3914977Sraghus 				break;
3924977Sraghus 			case NXGE_PORT_1G_FIBRE:
3934977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
3944977Sraghus 				break;
3954977Sraghus 			case NXGE_PORT_10G_FIBRE:
3964977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
3974977Sraghus 				break;
3984977Sraghus 			case NXGE_PORT_1G_SERDES:
3994977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4004977Sraghus 				break;
4014977Sraghus 			case NXGE_PORT_10G_SERDES:
4024977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4034977Sraghus 				break;
4044977Sraghus 			case NXGE_PORT_1G_RGMII_FIBER:
4054977Sraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
4064977Sraghus 				break;
4074977Sraghus 			default:
4084977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4094977Sraghus 				    "<== nxge_setup_xcvr_table: "
4104977Sraghus 				    "Unknown port-type: 0x%x", port_type));
4114977Sraghus 				return (NXGE_ERROR);
4124977Sraghus 			}
4134977Sraghus 		}
4144977Sraghus 
4154977Sraghus 		switch (nxgep->mac.portmode) {
4164977Sraghus 		case PORT_1G_COPPER:
4174977Sraghus 		case PORT_1G_RGMII_FIBER:
4184732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
4194977Sraghus 
4204977Sraghus 			/*
4214977Sraghus 			 * For Altas 4-1G copper, Xcvr port numbers are
4224977Sraghus 			 * swapped with ethernet port number. This is
4234977Sraghus 			 * designed for better signal integrity in
4244977Sraghus 			 * routing. This is also the case for the
4254977Sraghus 			 * on-board Neptune copper ports on the Maramba
4264977Sraghus 			 * platform.
4274977Sraghus 			 */
4284977Sraghus 			switch (nxgep->platform_type) {
4294977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
4304732Sdavemq 				nxgep->xcvr.xcvr_addr =
4314732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
4324977Sraghus 				break;
4334977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
4344732Sdavemq 				nxgep->xcvr.xcvr_addr =
4354732Sdavemq 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
4364977Sraghus 				break;
4374977Sraghus 			default:
4384977Sraghus 				break;
4394732Sdavemq 			}
4404732Sdavemq 			/*
4414732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
4424732Sdavemq 			 * swapped with ethernet port number. This is
4434977Sraghus 			 * designed for better signal integrity in
4444977Sraghus 			 * routing. This is also the case for the
4454977Sraghus 			 * on-board Neptune copper ports on the Maramba
4464977Sraghus 			 * platform.
4474732Sdavemq 			 */
4484977Sraghus 			switch (nxgep->platform_type) {
4494977Sraghus 			case P_NEPTUNE_ATLAS_4PORT:
4504977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
4514977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
4524977Sraghus 				switch (portn) {
4534977Sraghus 				case 0:
4544977Sraghus 					nxgep->xcvr.xcvr_addr += 3;
4554977Sraghus 					break;
4564977Sraghus 				case 1:
4574977Sraghus 					nxgep->xcvr.xcvr_addr += 2;
4584977Sraghus 					break;
4594977Sraghus 				case 2:
4604977Sraghus 					nxgep->xcvr.xcvr_addr += 1;
4614977Sraghus 					break;
4624977Sraghus 				case 3:
4634977Sraghus 					break;
4644977Sraghus 				default:
4654977Sraghus 					return (NXGE_ERROR);
4664977Sraghus 				}
4674732Sdavemq 				break;
4684732Sdavemq 			default:
4694977Sraghus 				break;
4704732Sdavemq 			}
4714977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
4724977Sraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
4734977Sraghus 			    "Copper" : "RGMII Fiber"));
4744732Sdavemq 			break;
4754977Sraghus 		case PORT_10G_COPPER:
4764732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
4774732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
4784732Sdavemq 			break;
4794977Sraghus 		case PORT_1G_FIBER:
4804977Sraghus 		case PORT_1G_SERDES:
4814732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
4824977Sraghus 			nxgep->xcvr.xcvr_addr = portn;
4834977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
4844977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
4854977Sraghus 			    "Fiber" : "Serdes"));
4864732Sdavemq 			break;
4874977Sraghus 		case PORT_10G_FIBER:
4884977Sraghus 		case PORT_10G_SERDES:
4894732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
4904977Sraghus 			switch (nxgep->platform_type) {
4914977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
4924977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
4934732Sdavemq 				nxgep->xcvr.xcvr_addr =
4944732Sdavemq 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
4954732Sdavemq 				/*
4964732Sdavemq 				 * Switch off LED for corresponding copper
4974732Sdavemq 				 * port
4984732Sdavemq 				 */
4994732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
5004977Sraghus 				break;
5014977Sraghus 			default:
5024977Sraghus 				break;
5034732Sdavemq 			}
5044732Sdavemq 			nxgep->xcvr.xcvr_addr += portn;
5054977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
5064977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
5074977Sraghus 			    "Fiber" : "Serdes"));
5084732Sdavemq 			break;
5094732Sdavemq 		default:
5104732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5114732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
5124732Sdavemq 			return (NXGE_ERROR);
5134732Sdavemq 		}
5144732Sdavemq 	}
5154732Sdavemq 
5164732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
5174732Sdavemq 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
5184977Sraghus 
5194977Sraghus 	/*
5204977Sraghus 	 * Get the actual device ID value returned by MDIO read.
5214977Sraghus 	 */
5224977Sraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
5234977Sraghus 
5244977Sraghus 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr.xcvr_addr);
5254977Sraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
5264977Sraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
5274977Sraghus 	} else {
5284977Sraghus 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr.xcvr_addr);
5294977Sraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
5304977Sraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
5314977Sraghus 		} else {
5324977Sraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
5334977Sraghus 			    nxgep->xcvr.xcvr_addr);
5344977Sraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
5354977Sraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
5364977Sraghus 			}
5374977Sraghus 		}
5384977Sraghus 	}
5394977Sraghus 
5404732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
5414732Sdavemq 
5424977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
5434977Sraghus 	    "[0x%x] platform type[0x%x]", nxgep->niu_type,
5444977Sraghus 	    nxgep->platform_type));
5454977Sraghus 
5464732Sdavemq 	return (status);
5474732Sdavemq }
5484732Sdavemq 
5493859Sml29623 /* Initialize the entire MAC and physical layer */
5503859Sml29623 
5513859Sml29623 nxge_status_t
5523859Sml29623 nxge_mac_init(p_nxge_t nxgep)
5533859Sml29623 {
5543859Sml29623 	uint8_t			portn;
5553859Sml29623 	nxge_status_t		status = NXGE_OK;
5563859Sml29623 
5573859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5583859Sml29623 
5593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
5603859Sml29623 
5613859Sml29623 	nxgep->mac.portnum = portn;
5623859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
5633859Sml29623 
5643859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
5653859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
5663859Sml29623 
5673859Sml29623 	/* Initialize XIF to configure a network mode */
5683859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
5693859Sml29623 		goto fail;
5703859Sml29623 	}
5713859Sml29623 
5723859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
5733859Sml29623 		goto fail;
5743859Sml29623 	}
5753859Sml29623 
5763859Sml29623 	/* Initialize TX and RX MACs */
5773859Sml29623 	/*
5783859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
5793859Sml29623 	 */
5803859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
5813859Sml29623 		goto fail;
5823859Sml29623 
5833859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
5843859Sml29623 		goto fail;
5853859Sml29623 
5863859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
5873859Sml29623 		goto fail;
5883859Sml29623 
5893859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
5903859Sml29623 		goto fail;
5913859Sml29623 
5923859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
5933859Sml29623 		goto fail;
5943859Sml29623 
5953859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
5963859Sml29623 		goto fail;
5973859Sml29623 
5983859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
5993859Sml29623 
6004977Sraghus 
6013859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
6023859Sml29623 
6033859Sml29623 	return (NXGE_OK);
6043859Sml29623 fail:
6053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6063859Sml29623 			"nxge_mac_init: failed to initialize MAC port<%d>",
6073859Sml29623 			portn));
6083859Sml29623 	return (status);
6093859Sml29623 }
6103859Sml29623 
6113859Sml29623 /* Initialize the Ethernet Link */
6123859Sml29623 
6133859Sml29623 nxge_status_t
6143859Sml29623 nxge_link_init(p_nxge_t nxgep)
6153859Sml29623 {
6163859Sml29623 	nxge_status_t		status = NXGE_OK;
6174977Sraghus 	nxge_port_mode_t	portmode;
6183859Sml29623 #ifdef	NXGE_DEBUG
6193859Sml29623 	uint8_t			portn;
6203859Sml29623 
6213859Sml29623 	portn = nxgep->mac.portnum;
6223859Sml29623 
6233859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
6243859Sml29623 #endif
6253859Sml29623 
6264977Sraghus 	portmode = nxgep->mac.portmode;
6274977Sraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
6284977Sraghus 	    (portmode != PORT_1G_SERDES)) {
6293859Sml29623 		/* Workaround to get link up in both NIU ports */
6304977Sraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
6313859Sml29623 			goto fail;
6324977Sraghus 		}
6333859Sml29623 	}
6343859Sml29623 	NXGE_DELAY(200000);
6353859Sml29623 	/* Initialize internal serdes */
6363859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
6373859Sml29623 		goto fail;
6383859Sml29623 	NXGE_DELAY(200000);
6393859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
6403859Sml29623 		goto fail;
6413859Sml29623 
6423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
6433859Sml29623 
6443859Sml29623 	return (NXGE_OK);
6453859Sml29623 
6463859Sml29623 fail:
6473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6483859Sml29623 		"nxge_link_init: ",
6493859Sml29623 		"failed to initialize Ethernet link on port<%d>",
6503859Sml29623 		portn));
6513859Sml29623 
6523859Sml29623 	return (status);
6533859Sml29623 }
6543859Sml29623 
6553859Sml29623 
6563859Sml29623 /* Initialize the XIF sub-block within the MAC */
6573859Sml29623 
6583859Sml29623 nxge_status_t
6593859Sml29623 nxge_xif_init(p_nxge_t nxgep)
6603859Sml29623 {
6613859Sml29623 	uint32_t		xif_cfg = 0;
6623859Sml29623 	npi_attr_t		ap;
6633859Sml29623 	uint8_t			portn;
6643859Sml29623 	nxge_port_t		portt;
6653859Sml29623 	nxge_port_mode_t	portmode;
6663859Sml29623 	p_nxge_stats_t		statsp;
6673859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
6683859Sml29623 	npi_handle_t		handle;
6693859Sml29623 
6703859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6713859Sml29623 
6723859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
6733859Sml29623 
6743859Sml29623 	handle = nxgep->npi_handle;
6753859Sml29623 	portmode = nxgep->mac.portmode;
6763859Sml29623 	portt = nxgep->mac.porttype;
6773859Sml29623 	statsp = nxgep->statsp;
6783859Sml29623 
6793859Sml29623 	if (portt == PORT_TYPE_XMAC) {
6803859Sml29623 
6813859Sml29623 		/* Setup XIF Configuration for XMAC */
6823859Sml29623 
6833859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
6844977Sraghus 		    (portmode == PORT_10G_COPPER) ||
6854977Sraghus 		    (portmode == PORT_10G_SERDES))
6863859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
6873859Sml29623 
6883859Sml29623 		if (portmode == PORT_1G_COPPER) {
6893859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
6903859Sml29623 		}
6913859Sml29623 
6923859Sml29623 		/* Set MAC Internal Loopback if necessary */
6933859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
6943859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
6953859Sml29623 
6963859Sml29623 		if (statsp->mac_stats.link_speed == 100)
6973859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
6983859Sml29623 
6993859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
7003859Sml29623 
7014977Sraghus 		if ((portmode == PORT_10G_FIBER) ||
7024977Sraghus 		    (portmode == PORT_10G_SERDES)) {
7033859Sml29623 			if (statsp->mac_stats.link_up) {
7043859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
7053859Sml29623 			} else {
7063859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
7073859Sml29623 			}
7083859Sml29623 		}
7093859Sml29623 
7103859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
7113859Sml29623 		if (rs != NPI_SUCCESS)
7123859Sml29623 			goto fail;
7133859Sml29623 
7143859Sml29623 		nxgep->mac.xif_config = xif_cfg;
7153859Sml29623 
7163859Sml29623 		/* Set Port Mode */
7173859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
7184977Sraghus 		    (portmode == PORT_10G_COPPER) ||
7194977Sraghus 		    (portmode == PORT_10G_SERDES)) {
7203859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
7213859Sml29623 						MAC_XGMII_MODE, rs);
7223859Sml29623 			if (rs != NPI_SUCCESS)
7233859Sml29623 				goto fail;
7243859Sml29623 			if (statsp->mac_stats.link_up) {
7253859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
7263859Sml29623 					goto fail;
7273859Sml29623 			} else {
7283859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
7293859Sml29623 					goto fail;
7303859Sml29623 			}
7313859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
7324977Sraghus 		    (portmode == PORT_1G_COPPER) ||
7334977Sraghus 		    (portmode == PORT_1G_SERDES)) {
7343859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
7353859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
7363859Sml29623 							MAC_GMII_MODE, rs);
7373859Sml29623 			} else {
7383859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
7393859Sml29623 							MAC_MII_MODE, rs);
7403859Sml29623 			}
7413859Sml29623 			if (rs != NPI_SUCCESS)
7423859Sml29623 				goto fail;
7433859Sml29623 		} else {
7443859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7453859Sml29623 					"nxge_xif_init: Unknown port mode (%d)"
7463859Sml29623 					" for port<%d>", portmode, portn));
7473859Sml29623 			goto fail;
7483859Sml29623 		}
7493859Sml29623 
7503859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
7513859Sml29623 
7523859Sml29623 		/* Setup XIF Configuration for BMAC */
7533859Sml29623 
7543859Sml29623 		if (portmode == PORT_1G_COPPER) {
7553859Sml29623 			if (statsp->mac_stats.link_speed == 100)
7563859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
7573859Sml29623 		}
7583859Sml29623 
7593859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
7603859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
7613859Sml29623 
7623859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
7633859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
7643859Sml29623 
7653859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
7663859Sml29623 
7673859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
7683859Sml29623 		if (rs != NPI_SUCCESS)
7693859Sml29623 			goto fail;
7703859Sml29623 		nxgep->mac.xif_config = xif_cfg;
7713859Sml29623 	}
7723859Sml29623 
7733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
7743859Sml29623 	return (NXGE_OK);
7753859Sml29623 fail:
7763859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7773859Sml29623 			"nxge_xif_init: Failed to initialize XIF port<%d>",
7783859Sml29623 			portn));
7793859Sml29623 	return (NXGE_ERROR | rs);
7803859Sml29623 }
7813859Sml29623 
7823859Sml29623 /* Initialize the PCS sub-block in the MAC */
7833859Sml29623 
7843859Sml29623 nxge_status_t
7853859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
7863859Sml29623 {
7873859Sml29623 	pcs_cfg_t		pcs_cfg;
7883859Sml29623 	uint32_t		val;
7893859Sml29623 	uint8_t			portn;
7903859Sml29623 	nxge_port_mode_t	portmode;
7913859Sml29623 	npi_handle_t		handle;
7923859Sml29623 	p_nxge_stats_t		statsp;
7933859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
7943859Sml29623 
7953859Sml29623 	handle = nxgep->npi_handle;
7963859Sml29623 	portmode = nxgep->mac.portmode;
7973859Sml29623 	portn = nxgep->mac.portnum;
7983859Sml29623 	statsp = nxgep->statsp;
7993859Sml29623 
8003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
8013859Sml29623 
8024977Sraghus 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
8034977Sraghus 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
8044977Sraghus 			goto fail;
8054977Sraghus 		}
8064977Sraghus 
8073859Sml29623 		/* Initialize port's PCS */
8083859Sml29623 		pcs_cfg.value = 0;
8093859Sml29623 		pcs_cfg.bits.w0.enable = 1;
8103859Sml29623 		pcs_cfg.bits.w0.mask = 1;
8113859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
8123859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
8134977Sraghus 
8144977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8154977Sraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
8164977Sraghus 		    portn, pcs_cfg.value));
8173859Sml29623 	} else if ((portmode == PORT_10G_FIBER) ||
8184977Sraghus 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
8193859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
8203859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
8213859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
8223859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
8233859Sml29623 
8243859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
8253859Sml29623 			goto fail;
8263859Sml29623 
8273859Sml29623 		/* Set XPCS Internal Loopback if necessary */
8283859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
8293859Sml29623 						XPCS_REG_CONTROL1, &val))
8303859Sml29623 						!= NPI_SUCCESS)
8313859Sml29623 			goto fail;
8323859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
8333859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
8343859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
8353859Sml29623 		else
8363859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
8373859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
8383859Sml29623 						XPCS_REG_CONTROL1, val))
8393859Sml29623 						!= NPI_SUCCESS)
8403859Sml29623 			goto fail;
8413859Sml29623 
8423859Sml29623 		/* Clear descw errors */
8433859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
8443859Sml29623 						XPCS_REG_DESCWERR_COUNTER, 0))
8453859Sml29623 						!= NPI_SUCCESS)
8463859Sml29623 			goto fail;
8473859Sml29623 		/* Clear symbol errors */
8483859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
8493859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
8503859Sml29623 					!= NPI_SUCCESS)
8513859Sml29623 			goto fail;
8523859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
8533859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
8543859Sml29623 					!= NPI_SUCCESS)
8553859Sml29623 			goto fail;
8563859Sml29623 
8573859Sml29623 	} else if (portmode == PORT_1G_COPPER) {
8583859Sml29623 		if (portn < 4) {
8593859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
8603859Sml29623 					PCS_DATAPATH_MODE_MII);
8613859Sml29623 		}
8623859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
8633859Sml29623 			goto fail;
8643859Sml29623 
8653859Sml29623 	} else {
8663859Sml29623 		goto fail;
8673859Sml29623 	}
8683859Sml29623 pass:
8693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
8703859Sml29623 	return (NXGE_OK);
8713859Sml29623 fail:
8723859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8733859Sml29623 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
8743859Sml29623 			portn));
8753859Sml29623 	return (NXGE_ERROR | rs);
8763859Sml29623 }
8773859Sml29623 
8783859Sml29623 /* Initialize the Internal Serdes */
8793859Sml29623 
8803859Sml29623 nxge_status_t
8813859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
8823859Sml29623 {
8833859Sml29623 	p_nxge_stats_t		statsp;
8843859Sml29623 #ifdef	NXGE_DEBUG
8853859Sml29623 	uint8_t			portn;
8863859Sml29623 #endif
8873859Sml29623 	nxge_status_t		status = NXGE_OK;
8883859Sml29623 
8893859Sml29623 #ifdef	NXGE_DEBUG
8903859Sml29623 	portn = nxgep->mac.portnum;
8913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8924732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
8933859Sml29623 #endif
8943859Sml29623 
8954732Sdavemq 	if (nxgep->xcvr.serdes_init) {
8964732Sdavemq 		statsp = nxgep->statsp;
8974732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
8984732Sdavemq 		if (status != NXGE_OK)
8993859Sml29623 			goto fail;
9004732Sdavemq 		statsp->mac_stats.serdes_inits++;
9013859Sml29623 	}
9023859Sml29623 
9033859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
9044732Sdavemq 	    portn));
9053859Sml29623 
9063859Sml29623 	return (NXGE_OK);
9073859Sml29623 
9083859Sml29623 fail:
9093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9104732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
9114732Sdavemq 	    portn));
9123859Sml29623 
9133859Sml29623 	return (status);
9143859Sml29623 }
9153859Sml29623 
9163859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
9173859Sml29623 
9184732Sdavemq static nxge_status_t
9193859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
9203859Sml29623 {
9213859Sml29623 	uint8_t portn;
9223859Sml29623 	int chan;
9233859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
9244977Sraghus 	esr_ti_cfgpll_l_t pll_sts_l;
9253859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
9263859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
9273859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
9283859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
9294977Sraghus #ifdef NXGE_DEBUG
9304977Sraghus 	esr_ti_testcfg_t cfg;
9314977Sraghus #endif
9323859Sml29623 	esr_ti_testcfg_t test_cfg;
9333859Sml29623 	nxge_status_t status = NXGE_OK;
9343859Sml29623 
9353859Sml29623 	portn = nxgep->mac.portnum;
9363859Sml29623 
9373859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
9383859Sml29623 			portn));
9393859Sml29623 
9403859Sml29623 	tx_cfg_l.value = 0;
9413859Sml29623 	tx_cfg_h.value = 0;
9423859Sml29623 	rx_cfg_l.value = 0;
9433859Sml29623 	rx_cfg_h.value = 0;
9443859Sml29623 	pll_cfg_l.value = 0;
9454977Sraghus 	pll_sts_l.value = 0;
9463859Sml29623 	test_cfg.value = 0;
9473859Sml29623 
9484977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
9494977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
9503859Sml29623 		/* 0x0E01 */
9513859Sml29623 		tx_cfg_l.bits.entx = 1;
9523859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
9533859Sml29623 
9543859Sml29623 		/* 0x9101 */
9553859Sml29623 		rx_cfg_l.bits.enrx = 1;
9563859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
9573859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
9583859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
9593859Sml29623 
9603859Sml29623 		/* 0x0008 */
9613859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
9623859Sml29623 
9633859Sml29623 		/* Set loopback mode if necessary */
9643859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
9653859Sml29623 			tx_cfg_l.bits.entest = 1;
9663859Sml29623 			rx_cfg_l.bits.entest = 1;
9673859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
9683859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
9693859Sml29623 				ESR_N2_DEV_ADDR,
9703859Sml29623 				ESR_N2_TEST_CFG_REG, test_cfg.value))
9713859Sml29623 				!= NXGE_OK)
9723859Sml29623 			goto fail;
9733859Sml29623 		}
9743859Sml29623 
9753859Sml29623 		/* Use default PLL value */
9763859Sml29623 
9774977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
9784977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
9793859Sml29623 
9803859Sml29623 		/* 0x0E21 */
9813859Sml29623 		tx_cfg_l.bits.entx = 1;
9823859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
9833859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
9843859Sml29623 
9853859Sml29623 		/* 0x9121 */
9863859Sml29623 		rx_cfg_l.bits.enrx = 1;
9873859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
9883859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
9893859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
9903859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
9913859Sml29623 
9924977Sraghus 		if (portn == 0) {
9934977Sraghus 			/* 0x8 */
9944977Sraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
9954977Sraghus 		}
9963859Sml29623 
9973859Sml29623 		/* MPY = 0x100 */
9983859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
9993859Sml29623 
10003859Sml29623 		/* Set PLL */
10013859Sml29623 		pll_cfg_l.bits.enpll = 1;
10024977Sraghus 		pll_sts_l.bits.enpll = 1;
10033859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10043859Sml29623 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
10053859Sml29623 				!= NXGE_OK)
10063859Sml29623 			goto fail;
10074977Sraghus 
10084977Sraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10094977Sraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
10104977Sraghus 			goto fail;
10114977Sraghus 
10124977Sraghus #ifdef  NXGE_DEBUG
10134977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
10144977Sraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
10154977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10164977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
10174977Sraghus 		    portn, pll_cfg_l.value, cfg.value));
10184977Sraghus 
10194977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
10204977Sraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
10214977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10224977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
10234977Sraghus 		    portn, pll_sts_l.value, cfg.value));
10244977Sraghus #endif
10254977Sraghus 
10264977Sraghus 		/* Set loopback mode if necessary */
10274977Sraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
10284977Sraghus 			tx_cfg_l.bits.entest = 1;
10294977Sraghus 			rx_cfg_l.bits.entest = 1;
10304977Sraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
10314977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10324977Sraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
10334977Sraghus 			    portn, test_cfg.value));
10344977Sraghus 			if ((status = nxge_mdio_write(nxgep, portn,
10354977Sraghus 			    ESR_N2_DEV_ADDR,
10364977Sraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
10374977Sraghus 				goto fail;
10384977Sraghus 			}
10394977Sraghus 		}
10403859Sml29623 	} else {
10413859Sml29623 		goto fail;
10423859Sml29623 	}
10433859Sml29623 
10443859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
10453859Sml29623 
10463859Sml29623 	NXGE_DELAY(20);
10473859Sml29623 
10483859Sml29623 	/* init TX channels */
10493859Sml29623 	for (chan = 0; chan < 4; chan++) {
10503859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10513859Sml29623 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
10523859Sml29623 				!= NXGE_OK)
10533859Sml29623 			goto fail;
10543859Sml29623 
10553859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10563859Sml29623 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
10573859Sml29623 				!= NXGE_OK)
10583859Sml29623 			goto fail;
10594977Sraghus 
10604977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10614977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
10624977Sraghus 		    portn, chan, tx_cfg_l.value));
10634977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10644977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
10654977Sraghus 		    portn, chan, tx_cfg_h.value));
10663859Sml29623 	}
10673859Sml29623 
10683859Sml29623 	/* init RX channels */
10693859Sml29623 	for (chan = 0; chan < 4; chan++) {
10703859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10713859Sml29623 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
10723859Sml29623 				!= NXGE_OK)
10733859Sml29623 			goto fail;
10743859Sml29623 
10753859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
10763859Sml29623 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
10773859Sml29623 				!= NXGE_OK)
10783859Sml29623 			goto fail;
10794977Sraghus 
10804977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10814977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
10824977Sraghus 		    portn, chan, rx_cfg_l.value));
10834977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10844977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
10854977Sraghus 		    portn, chan, rx_cfg_h.value));
10863859Sml29623 	}
10873859Sml29623 
10883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
10893859Sml29623 			portn));
10903859Sml29623 
10913859Sml29623 	return (NXGE_OK);
10923859Sml29623 fail:
10933859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10943859Sml29623 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
10953859Sml29623 				portn));
10963859Sml29623 
10973859Sml29623 	return (status);
10983859Sml29623 }
10993859Sml29623 
11004732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
11014732Sdavemq 
11024732Sdavemq static nxge_status_t
11034732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
11043859Sml29623 {
11053859Sml29623 	npi_handle_t		handle;
11063859Sml29623 	uint8_t			portn;
11073859Sml29623 	int			chan;
11083859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
11093859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
11103859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
11113859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
11123859Sml29623 	uint64_t		val;
11133859Sml29623 	uint16_t		val16l;
11143859Sml29623 	uint16_t		val16h;
11153859Sml29623 	nxge_status_t		status = NXGE_OK;
11163859Sml29623 
11173859Sml29623 	portn = nxgep->mac.portnum;
11183859Sml29623 
11193859Sml29623 	if ((portn != 0) && (portn != 1))
11203859Sml29623 		return (NXGE_OK);
11213859Sml29623 
11224732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11234732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
11243859Sml29623 
11253859Sml29623 	handle = nxgep->npi_handle;
11264732Sdavemq 	switch (portn) {
11274732Sdavemq 	case 0:
11284732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
11294732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
11304732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
11314732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
11324732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
11334732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
11344732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
11354732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
11364732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
11374732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
11384732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
11394732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
11404732Sdavemq 
11414732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
11424732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
11434732Sdavemq 			ESR_REG_WR(handle,
11444732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
11454732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
11464732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
11474732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
11484732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
11494732Sdavemq 		} else {
11504732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
11513859Sml29623 		}
11524732Sdavemq 		break;
11534732Sdavemq 	case 1:
11544732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
11554732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
11564732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
11574732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
11584732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
11594732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
11604732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
11614732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
11624732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
11634732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
11644732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
11654732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
11664732Sdavemq 
11674732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
11684732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
11694732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
11704732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
11714732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
11724732Sdavemq 		} else {
11734732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
11743859Sml29623 		}
11754732Sdavemq 		break;
11764732Sdavemq 	default:
11774732Sdavemq 		/* Nothing to do here */
11784732Sdavemq 		goto done;
11794732Sdavemq 	}
11804732Sdavemq 
11814732Sdavemq 	/* init TX RX channels */
11824732Sdavemq 	for (chan = 0; chan < 4; chan++) {
11834732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
11844732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
11854732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
11863859Sml29623 			goto fail;
11874732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
11884732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
11894732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
11903859Sml29623 			goto fail;
11913859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
11924732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
11934732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
11943859Sml29623 			goto fail;
11953859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
11964732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
11974732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
11984732Sdavemq 			goto fail;
11994732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
12004732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
12014732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
12024732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
12034732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
12044732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
12054732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
12064732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
12074732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
12084732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
12094732Sdavemq 			goto fail;
12104732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
12114732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
12124732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
12134732Sdavemq 			goto fail;
12144732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
12154732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
12164732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
12174732Sdavemq 			goto fail;
12184732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
12194732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
12204732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
12213859Sml29623 			goto fail;
12223859Sml29623 		}
12233859Sml29623 
12244732Sdavemq 	/* Apply Tx core reset */
12254732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
12264732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
12274732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
12284732Sdavemq 		goto fail;
12294732Sdavemq 
12304732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
12314732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
12324732Sdavemq 	    NXGE_OK)
12334732Sdavemq 		goto fail;
12344732Sdavemq 
12354732Sdavemq 	NXGE_DELAY(200);
12364732Sdavemq 
12374732Sdavemq 	/* Apply Rx core reset */
12384732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
12394732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
12404732Sdavemq 	    NXGE_OK)
12414732Sdavemq 		goto fail;
12424732Sdavemq 
12434732Sdavemq 	NXGE_DELAY(200);
12444732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
12454732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
12464732Sdavemq 		goto fail;
12474732Sdavemq 
12484732Sdavemq 	NXGE_DELAY(200);
12494732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
12504732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
12514732Sdavemq 	    &val16l)) != NXGE_OK)
12524732Sdavemq 		goto fail;
12534732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
12544732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
12554732Sdavemq 		goto fail;
12564732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
12574732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
12584732Sdavemq 		    "Failed to reset port<%d> XAUI Serdes", portn));
12594732Sdavemq 	}
12604732Sdavemq 
12614732Sdavemq 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
12624732Sdavemq 
12634732Sdavemq 	if (portn == 0) {
12644732Sdavemq 		if ((val & ESR_SIG_P0_BITS_MASK) !=
12653859Sml29623 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
12663859Sml29623 					ESR_SIG_XSERDES_RDY_P0 |
12673859Sml29623 					ESR_SIG_XDETECT_P0_CH3 |
12683859Sml29623 					ESR_SIG_XDETECT_P0_CH2 |
12693859Sml29623 					ESR_SIG_XDETECT_P0_CH1 |
12703859Sml29623 					ESR_SIG_XDETECT_P0_CH0)) {
12714732Sdavemq 			goto fail;
12724732Sdavemq 		}
12734732Sdavemq 	} else if (portn == 1) {
12744732Sdavemq 		if ((val & ESR_SIG_P1_BITS_MASK) !=
12753859Sml29623 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
12763859Sml29623 					ESR_SIG_XSERDES_RDY_P1 |
12773859Sml29623 					ESR_SIG_XDETECT_P1_CH3 |
12783859Sml29623 					ESR_SIG_XDETECT_P1_CH2 |
12793859Sml29623 					ESR_SIG_XDETECT_P1_CH1 |
12803859Sml29623 					ESR_SIG_XDETECT_P1_CH0)) {
12813859Sml29623 			goto fail;
12823859Sml29623 		}
12833859Sml29623 	}
12843859Sml29623 
12853859Sml29623 done:
12864732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12874732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
12884732Sdavemq 
12893859Sml29623 	return (NXGE_OK);
12903859Sml29623 fail:
12914732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12924732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
12934732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
12943859Sml29623 
12953859Sml29623 	return (status);
12963859Sml29623 }
12973859Sml29623 
12984732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
12994732Sdavemq 
13004732Sdavemq static nxge_status_t
13014732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
13023859Sml29623 {
13034732Sdavemq 	npi_handle_t		handle;
13044732Sdavemq 	uint8_t			portn;
13054732Sdavemq 	uint64_t		val;
13063859Sml29623 
13073859Sml29623 	portn = nxgep->mac.portnum;
13084732Sdavemq 
13094732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13104732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
13114732Sdavemq 
13124732Sdavemq 	handle = nxgep->npi_handle;
13134732Sdavemq 
13144732Sdavemq 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
13154732Sdavemq 	val &= ~ESR_PLL_CFG_FBDIV_2;
13164732Sdavemq 	switch (portn) {
13174732Sdavemq 	case 0:
13184732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_0;
13194732Sdavemq 		break;
13204732Sdavemq 	case 1:
13214732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_1;
13224732Sdavemq 		break;
13234732Sdavemq 	case 2:
13244732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_2;
13254732Sdavemq 		break;
13264732Sdavemq 	case 3:
13274732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_3;
13284732Sdavemq 		break;
13294732Sdavemq 	default:
13304732Sdavemq 		goto fail;
13313859Sml29623 	}
13323859Sml29623 
13334732Sdavemq 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
13344732Sdavemq 
13354732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13364732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
13373859Sml29623 	return (NXGE_OK);
13384732Sdavemq fail:
13394732Sdavemq 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
13404732Sdavemq 	    "nxge_1G_serdes_init: "
13414732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
13424732Sdavemq 	    portn));
13434732Sdavemq 
13444732Sdavemq 	return (NXGE_ERROR);
13453859Sml29623 }
13463859Sml29623 
13474732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */
13484732Sdavemq 
13494732Sdavemq static nxge_status_t
13504732Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep)
13513859Sml29623 {
13523859Sml29623 	p_nxge_stats_t		statsp;
13533859Sml29623 	uint16_t		val;
13543859Sml29623 #ifdef	NXGE_DEBUG
13553859Sml29623 	uint8_t			portn;
13563859Sml29623 	uint16_t		val1;
13573859Sml29623 #endif
13583859Sml29623 	uint8_t			phy_port_addr;
13593859Sml29623 	pmd_tx_control_t	tx_ctl;
13603859Sml29623 	control_t		ctl;
13613859Sml29623 	phyxs_control_t		phyxs_ctl;
13623859Sml29623 	pcs_control_t		pcs_ctl;
13633859Sml29623 	uint32_t		delay = 0;
13643859Sml29623 	optics_dcntr_t		op_ctr;
13653859Sml29623 	nxge_status_t		status = NXGE_OK;
13663859Sml29623 #ifdef	NXGE_DEBUG
13673859Sml29623 	portn = nxgep->mac.portnum;
13683859Sml29623 #endif
13694732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
13704732Sdavemq 	    portn));
13714732Sdavemq 
13724732Sdavemq 	statsp = nxgep->statsp;
13734732Sdavemq 
13744977Sraghus 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
13754977Sraghus 		goto done;
13764977Sraghus 	}
13774977Sraghus 
13784732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
13794732Sdavemq 
13804732Sdavemq 	/* Disable Link LEDs */
13814732Sdavemq 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
13824732Sdavemq 		goto fail;
13834732Sdavemq 
13844732Sdavemq 	/* Set Clause 45 */
13854732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
13864732Sdavemq 
13874732Sdavemq 	/* Reset the transceiver */
13884732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
13894732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
13904732Sdavemq 		goto fail;
13914732Sdavemq 
13924732Sdavemq 	phyxs_ctl.bits.reset = 1;
13934732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
13944732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
13954732Sdavemq 		goto fail;
13964732Sdavemq 
13974732Sdavemq 	do {
13984732Sdavemq 		drv_usecwait(500);
13994732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14004732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
14014732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
14024732Sdavemq 			goto fail;
14034732Sdavemq 		delay++;
14044732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
14054732Sdavemq 	if (delay == 100) {
14064732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
14074732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
14084732Sdavemq 		status = NXGE_ERROR;
14094732Sdavemq 		goto fail;
14104732Sdavemq 	}
14114732Sdavemq 
14124732Sdavemq 	/* Set to 0x7FBF */
14134732Sdavemq 	ctl.value = 0;
14144732Sdavemq 	ctl.bits.res1 = 0x3F;
14154732Sdavemq 	ctl.bits.optxon_lvl = 1;
14164732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
14174732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
14184732Sdavemq 	ctl.bits.optxflt_lvl = 1;
14194732Sdavemq 	ctl.bits.opprflt_lvl = 1;
14204732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
14214732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
14224732Sdavemq 	ctl.bits.optxrst_lvl = 1;
14234732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
14244732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
14254732Sdavemq 	    != NXGE_OK)
14264732Sdavemq 		goto fail;
14274732Sdavemq 
14284732Sdavemq 	/* Set to 0x164 */
14294732Sdavemq 	tx_ctl.value = 0;
14304732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
14314732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
14324732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
14334732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
14344732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
14354732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
14364732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
14374732Sdavemq 		goto fail;
14384732Sdavemq 	/*
14394732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
14404732Sdavemq 	 * back these registers twice after written.
14414732Sdavemq 	 */
14424732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14434732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
14444732Sdavemq 	    != NXGE_OK)
14454732Sdavemq 		goto fail;
14464732Sdavemq 
14474732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14484732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
14494732Sdavemq 	    != NXGE_OK)
14504732Sdavemq 		goto fail;
14514732Sdavemq 
14524732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14534732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
14544732Sdavemq 	    != NXGE_OK)
14554732Sdavemq 		goto fail;
14564732Sdavemq 
14574732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14584732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
14594732Sdavemq 	    != NXGE_OK)
14604732Sdavemq 		goto fail;
14614732Sdavemq 
14624732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
14634732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14644732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
14654732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
14664732Sdavemq 		goto fail;
14674732Sdavemq 	op_ctr.bits.gpio_sel = 0x3;
14684732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
14694732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
14704732Sdavemq 	    op_ctr.value)) != NXGE_OK)
14714732Sdavemq 		goto fail;
14724732Sdavemq 
14734732Sdavemq 	NXGE_DELAY(1000000);
14744732Sdavemq 
14754732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
14764732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
14774732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
14784732Sdavemq 	    != NXGE_OK)
14794732Sdavemq 		goto fail;
14804732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
14814732Sdavemq 		pcs_ctl.bits.loopback = 1;
14824732Sdavemq 	else
14834732Sdavemq 		pcs_ctl.bits.loopback = 0;
14844732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
14854732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
14864732Sdavemq 	    != NXGE_OK)
14874732Sdavemq 		goto fail;
14884732Sdavemq 
14894732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
14904732Sdavemq 	if (status != NXGE_OK)
14914732Sdavemq 		goto fail;
14924732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14934732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
14944732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
14954732Sdavemq 	if (status != NXGE_OK)
14964732Sdavemq 		goto fail;
14974732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14984732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
14994732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
15004732Sdavemq 	if (status != NXGE_OK)
15014732Sdavemq 		goto fail;
15024732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15034732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
15044732Sdavemq 
15054732Sdavemq #ifdef	NXGE_DEBUG
15064732Sdavemq 	/* Diagnose link issue if link is not up */
15074732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
15084732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
15094732Sdavemq 	    &val);
15104732Sdavemq 	if (status != NXGE_OK)
15114732Sdavemq 		goto fail;
15124732Sdavemq 
15134732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
15144732Sdavemq 				BCM8704_USER_DEV3_ADDR,
15154732Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
15164732Sdavemq 				&val);
15174732Sdavemq 	if (status != NXGE_OK)
15184732Sdavemq 		goto fail;
15194732Sdavemq 
15204732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
15214732Sdavemq 				BCM8704_USER_DEV3_ADDR,
15224732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
15234732Sdavemq 				&val1);
15244732Sdavemq 	if (status != NXGE_OK)
15254732Sdavemq 		goto fail;
15264732Sdavemq 
15274732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
15284732Sdavemq 				BCM8704_USER_DEV3_ADDR,
15294732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
15304732Sdavemq 				&val1);
15314732Sdavemq 	if (status != NXGE_OK)
15324732Sdavemq 		goto fail;
15334732Sdavemq 
15344732Sdavemq 	if (val != 0x3FC) {
15354732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
15364732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15374732Sdavemq 			    "Cable not connected to peer or bad"
15384732Sdavemq 			    " cable on port<%d>\n", portn));
15394732Sdavemq 		} else if (val == 0x639C) {
15404732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15414732Sdavemq 			    "Optical module (XFP) is bad or absent"
15424732Sdavemq 			    " on port<%d>\n", portn));
15434732Sdavemq 		}
15444732Sdavemq 	}
15454732Sdavemq #endif
15464732Sdavemq 
15474977Sraghus done:
15484732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
15494732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
15504732Sdavemq 
15514732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
15524732Sdavemq 	    portn));
15534732Sdavemq 	return (NXGE_OK);
15544732Sdavemq 
15554732Sdavemq fail:
15564732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15574732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
15584732Sdavemq 	    "port<%d>", portn));
15594732Sdavemq 	return (status);
15604732Sdavemq }
15614732Sdavemq 
15624732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
15634732Sdavemq 
15644732Sdavemq static nxge_status_t
15654732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
15664732Sdavemq {
15674732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
15684732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
15694732Sdavemq 	nxge_status_t		status = NXGE_OK;
15704732Sdavemq 
15714977Sraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
15724977Sraghus 		statsp->mac_stats.cap_1000fdx =
15734977Sraghus 		    param_arr[param_anar_1000fdx].value;
15744977Sraghus 		goto done;
15754977Sraghus 	}
15764977Sraghus 
15774732Sdavemq 	/* Set Clause 22 */
15784732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
15794732Sdavemq 
15804732Sdavemq 	/* Set capability flags */
15814732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
15824977Sraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
15834977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
15844977Sraghus 		statsp->mac_stats.cap_100fdx =
15854977Sraghus 		    param_arr[param_anar_100fdx].value;
15864977Sraghus 		statsp->mac_stats.cap_10fdx =
15874977Sraghus 		    param_arr[param_anar_10fdx].value;
15884977Sraghus 	}
15894732Sdavemq 
15904732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
15914977Sraghus done:
15924732Sdavemq 	return (status);
15934732Sdavemq }
15944732Sdavemq 
15954732Sdavemq /* Initialize transceiver */
15964732Sdavemq 
15974732Sdavemq nxge_status_t
15984732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
15994732Sdavemq {
16004732Sdavemq 	p_nxge_stats_t		statsp;
16014732Sdavemq #ifdef	NXGE_DEBUG
16024732Sdavemq 	uint8_t			portn;
16034732Sdavemq #endif
16044732Sdavemq 
16054732Sdavemq 	nxge_status_t		status = NXGE_OK;
16064732Sdavemq #ifdef	NXGE_DEBUG
16074732Sdavemq 	portn = nxgep->mac.portnum;
16084732Sdavemq #endif
16093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
16103859Sml29623 	statsp = nxgep->statsp;
16113859Sml29623 
16123859Sml29623 	/*
16133859Sml29623 	 * Initialize the xcvr statistics.
16143859Sml29623 	 */
16153859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
16163859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
16173859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
16183859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
16193859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
16203859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
16213859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
16223859Sml29623 	statsp->mac_stats.cap_pause = 0;
16233859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
16243859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
16253859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
16263859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
16273859Sml29623 
16283859Sml29623 	/*
16293859Sml29623 	 * Initialize the link statistics.
16303859Sml29623 	 */
16313859Sml29623 	statsp->mac_stats.link_T4 = 0;
16323859Sml29623 	statsp->mac_stats.link_asmpause = 0;
16333859Sml29623 	statsp->mac_stats.link_pause = 0;
16343859Sml29623 
16354732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
16364732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
16373859Sml29623 		if (status != NXGE_OK)
16383859Sml29623 			goto fail;
16394732Sdavemq 		statsp->mac_stats.xcvr_inits++;
16403859Sml29623 	}
16413859Sml29623 
16424732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
16434732Sdavemq 	    portn));
16443859Sml29623 	return (NXGE_OK);
16453859Sml29623 
16463859Sml29623 fail:
16473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16484732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
16494732Sdavemq 	    portn));
16503859Sml29623 	return (status);
16513859Sml29623 }
16523859Sml29623 
16534977Sraghus /* Look for transceiver type */
16544977Sraghus 
16554977Sraghus nxge_status_t
16564977Sraghus nxge_xcvr_find(p_nxge_t nxgep)
16574977Sraghus {
16584977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16594977Sraghus 	    "==> nxge_xcvr_find: port<%d>", nxgep->mac.portnum));
16604977Sraghus 
16614977Sraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
16624977Sraghus 		return (NXGE_ERROR);
16634977Sraghus 
16644977Sraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
16654977Sraghus 		return (NXGE_ERROR);
16664977Sraghus 
16674977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
16684977Sraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
16694977Sraghus 
16704977Sraghus 	return (NXGE_OK);
16714977Sraghus }
16723859Sml29623 
16733859Sml29623 /* Initialize the TxMAC sub-block */
16743859Sml29623 
16753859Sml29623 nxge_status_t
16763859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
16773859Sml29623 {
16783859Sml29623 	npi_attr_t		ap;
16793859Sml29623 	uint8_t			portn;
16803859Sml29623 	nxge_port_mode_t	portmode;
16813859Sml29623 	nxge_port_t		portt;
16823859Sml29623 	npi_handle_t		handle;
16833859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
16843859Sml29623 
16853859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
16863859Sml29623 	portt    = nxgep->mac.porttype;
16873859Sml29623 	handle   = nxgep->npi_handle;
16883859Sml29623 	portmode = nxgep->mac.portmode;
16893859Sml29623 
16903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
16913859Sml29623 			portn));
16923859Sml29623 
16933859Sml29623 	/* Set Max and Min Frame Size */
16943859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
16953859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
16963859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
16973859Sml29623 	} else {
16983859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
16993859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
17003859Sml29623 	}
17013859Sml29623 
17023859Sml29623 	if (rs != NPI_SUCCESS)
17033859Sml29623 		goto fail;
17043859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value ||
17053859Sml29623 		nxgep->mac.is_jumbo == B_TRUE)
17063859Sml29623 		nxgep->mac.maxframesize = 0x2400;
17073859Sml29623 	else
17083859Sml29623 		nxgep->mac.maxframesize = 0x5EE + 4;
17093859Sml29623 	nxgep->mac.minframesize = 64;
17103859Sml29623 
17113859Sml29623 	if (portt == PORT_TYPE_XMAC) {
17123859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
17133859Sml29623 				0)) != NPI_SUCCESS)
17143859Sml29623 			goto fail;
17153859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
17163859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
17174977Sraghus 		    (portmode == PORT_10G_COPPER) ||
17184977Sraghus 		    (portmode == PORT_10G_SERDES)) {
17193859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
17203859Sml29623 					XGMII_IPG_12_15, rs);
17213859Sml29623 			if (rs != NPI_SUCCESS)
17223859Sml29623 				goto fail;
17233859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
17243859Sml29623 		} else {
17253859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
17263859Sml29623 					MII_GMII_IPG_12, rs);
17273859Sml29623 			if (rs != NPI_SUCCESS)
17283859Sml29623 				goto fail;
17293859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
17303859Sml29623 		}
17313859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
17323859Sml29623 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
17333859Sml29623 			goto fail;
17343859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
17353859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
17363859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
17373859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
17383859Sml29623 
17393859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
17403859Sml29623 							!= NPI_SUCCESS)
17413859Sml29623 			goto fail;
17423859Sml29623 
17433859Sml29623 	} else {
17443859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
17453859Sml29623 				0)) != NPI_SUCCESS)
17463859Sml29623 			goto fail;
17473859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
17483859Sml29623 
17493859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
17503859Sml29623 				rs);
17513859Sml29623 		if (rs != NPI_SUCCESS)
17523859Sml29623 			goto fail;
17533859Sml29623 		nxgep->mac.ctrltype = 0x8808;
17543859Sml29623 
17553859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
17563859Sml29623 		if (rs != NPI_SUCCESS)
17573859Sml29623 			goto fail;
17583859Sml29623 		nxgep->mac.pa_size = 0x7;
17593859Sml29623 
17603859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
17613859Sml29623 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
17623859Sml29623 			goto fail;
17633859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
17643859Sml29623 	}
17653859Sml29623 
17663859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
17673859Sml29623 			portn));
17683859Sml29623 
17693859Sml29623 	return (NXGE_OK);
17703859Sml29623 fail:
17713859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17723859Sml29623 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
17733859Sml29623 					portn));
17743859Sml29623 
17753859Sml29623 	return (NXGE_ERROR | rs);
17763859Sml29623 }
17773859Sml29623 
17783859Sml29623 /* Initialize the RxMAC sub-block */
17793859Sml29623 
17803859Sml29623 nxge_status_t
17813859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
17823859Sml29623 {
17833859Sml29623 	npi_attr_t		ap;
17843859Sml29623 	uint32_t		i;
17853859Sml29623 	uint16_t		hashtab_e;
17863859Sml29623 	p_hash_filter_t		hash_filter;
17873859Sml29623 	nxge_port_t		portt;
17883859Sml29623 	uint8_t			portn;
17893859Sml29623 	npi_handle_t		handle;
17903859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
17913859Sml29623 	uint16_t 		*addr16p;
17923859Sml29623 	uint16_t 		addr0, addr1, addr2;
17933859Sml29623 	xmac_rx_config_t	xconfig;
17943859Sml29623 	bmac_rx_config_t	bconfig;
17953859Sml29623 
17963859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
17973859Sml29623 
17983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
17993859Sml29623 			portn));
18003859Sml29623 	handle = nxgep->npi_handle;
18013859Sml29623 	portt = nxgep->mac.porttype;
18023859Sml29623 
18033859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
18043859Sml29623 	addr0 = ntohs(addr16p[2]);
18053859Sml29623 	addr1 = ntohs(addr16p[1]);
18063859Sml29623 	addr2 = ntohs(addr16p[0]);
18073859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
18083859Sml29623 		rs);
18093859Sml29623 
18103859Sml29623 	if (rs != NPI_SUCCESS)
18113859Sml29623 		goto fail;
18123859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
18133859Sml29623 	if (rs != NPI_SUCCESS)
18143859Sml29623 		goto fail;
18153859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
18163859Sml29623 	if (rs != NPI_SUCCESS)
18173859Sml29623 		goto fail;
18183859Sml29623 
18193859Sml29623 	/*
18203859Sml29623 	 * Load the multicast hash filter bits.
18213859Sml29623 	 */
18223859Sml29623 	hash_filter = nxgep->hash_filter;
18233859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
18243859Sml29623 		if (hash_filter != NULL) {
18253859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
18263859Sml29623 				(NMCFILTER_REGS - 1) - i];
18273859Sml29623 		} else {
18283859Sml29623 			hashtab_e = 0;
18293859Sml29623 		}
18303859Sml29623 
18313859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
18323859Sml29623 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
18333859Sml29623 			goto fail;
18343859Sml29623 	}
18353859Sml29623 
18363859Sml29623 	if (portt == PORT_TYPE_XMAC) {
18373859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
18383859Sml29623 				0)) != NPI_SUCCESS)
18393859Sml29623 			goto fail;
18403859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
18413859Sml29623 
18423859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
18433859Sml29623 
18443859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
18453859Sml29623 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
18463859Sml29623 			~CFG_XMAC_RX_STRIP_CRC;
18473859Sml29623 
18483859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
18493859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
18503859Sml29623 
18513859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
18523859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
18533859Sml29623 
18543859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
18553859Sml29623 
18563859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
18573859Sml29623 					xconfig)) != NPI_SUCCESS)
18583859Sml29623 			goto fail;
18593859Sml29623 		nxgep->mac.rx_config = xconfig;
18603859Sml29623 
18613859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
18623859Sml29623 
18633859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
18643859Sml29623 							!= NPI_SUCCESS)
18653859Sml29623 			goto fail;
18663859Sml29623 	} else {
18673859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
18683859Sml29623 
18693859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
18703859Sml29623 					0) != NPI_SUCCESS)
18713859Sml29623 			goto fail;
18723859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
18733859Sml29623 
18743859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
18753859Sml29623 			~CFG_BMAC_RX_STRIP_CRC;
18763859Sml29623 
18773859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
18783859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
18793859Sml29623 
18803859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
18813859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
18823859Sml29623 
18833859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
18843859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
18853859Sml29623 					bconfig)) != NPI_SUCCESS)
18863859Sml29623 			goto fail;
18873859Sml29623 		nxgep->mac.rx_config = bconfig;
18883859Sml29623 
18893859Sml29623 		/* Always enable comparison of mac unique address */
18903859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
18913859Sml29623 					!= NPI_SUCCESS)
18923859Sml29623 			goto fail;
18933859Sml29623 	}
18943859Sml29623 
18953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
18963859Sml29623 			portn));
18973859Sml29623 
18983859Sml29623 	return (NXGE_OK);
18993859Sml29623 
19003859Sml29623 fail:
19013859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19023859Sml29623 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
19033859Sml29623 				portn));
19043859Sml29623 
19053859Sml29623 	return (NXGE_ERROR | rs);
19063859Sml29623 }
19073859Sml29623 
19083859Sml29623 /* Enable TXMAC */
19093859Sml29623 
19103859Sml29623 nxge_status_t
19113859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
19123859Sml29623 {
19133859Sml29623 	npi_handle_t	handle;
19143859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
19153859Sml29623 	nxge_status_t	status = NXGE_OK;
19163859Sml29623 
19173859Sml29623 	handle = nxgep->npi_handle;
19183859Sml29623 
19193859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
19203859Sml29623 			nxgep->mac.portnum));
19213859Sml29623 
19223859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
19233859Sml29623 		goto fail;
19243859Sml29623 
19253859Sml29623 	/* based on speed */
19263859Sml29623 	nxgep->msg_min = ETHERMIN;
19273859Sml29623 
19283859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
19293859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
19303859Sml29623 						CFG_XMAC_TX)) != NPI_SUCCESS)
19313859Sml29623 			goto fail;
19323859Sml29623 	} else {
19333859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
19343859Sml29623 						CFG_BMAC_TX)) != NPI_SUCCESS)
19353859Sml29623 			goto fail;
19363859Sml29623 	}
19373859Sml29623 
19383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
19393859Sml29623 			nxgep->mac.portnum));
19403859Sml29623 
19413859Sml29623 	return (NXGE_OK);
19423859Sml29623 fail:
19433859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19443859Sml29623 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
19453859Sml29623 			nxgep->mac.portnum));
19463859Sml29623 	if (rs != NPI_SUCCESS)
19473859Sml29623 		return (NXGE_ERROR | rs);
19483859Sml29623 	else
19493859Sml29623 		return (status);
19503859Sml29623 }
19513859Sml29623 
19523859Sml29623 /* Disable TXMAC */
19533859Sml29623 
19543859Sml29623 nxge_status_t
19553859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
19563859Sml29623 {
19573859Sml29623 	npi_handle_t	handle;
19583859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
19593859Sml29623 
19603859Sml29623 	handle = nxgep->npi_handle;
19613859Sml29623 
19623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
19633859Sml29623 			nxgep->mac.portnum));
19643859Sml29623 
19653859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
19663859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
19673859Sml29623 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
19683859Sml29623 			goto fail;
19693859Sml29623 	} else {
19703859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
19713859Sml29623 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
19723859Sml29623 			goto fail;
19733859Sml29623 	}
19743859Sml29623 
19753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
19763859Sml29623 			nxgep->mac.portnum));
19773859Sml29623 	return (NXGE_OK);
19783859Sml29623 fail:
19793859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19803859Sml29623 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
19813859Sml29623 			nxgep->mac.portnum));
19823859Sml29623 	return (NXGE_ERROR | rs);
19833859Sml29623 }
19843859Sml29623 
19853859Sml29623 /* Enable RXMAC */
19863859Sml29623 
19873859Sml29623 nxge_status_t
19883859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
19893859Sml29623 {
19903859Sml29623 	npi_handle_t	handle;
19913859Sml29623 	uint8_t 	portn;
19923859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
19933859Sml29623 	nxge_status_t	status = NXGE_OK;
19943859Sml29623 
19953859Sml29623 	handle = nxgep->npi_handle;
19963859Sml29623 	portn = nxgep->mac.portnum;
19973859Sml29623 
19983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
19993859Sml29623 			portn));
20003859Sml29623 
20013859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
20023859Sml29623 		goto fail;
20033859Sml29623 
20043859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
20053859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
20063859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
20073859Sml29623 			goto fail;
20083859Sml29623 	} else {
20093859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
20103859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
20113859Sml29623 			goto fail;
20123859Sml29623 	}
20133859Sml29623 
20143859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
20153859Sml29623 			portn));
20163859Sml29623 
20173859Sml29623 	return (NXGE_OK);
20183859Sml29623 fail:
20193859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20203859Sml29623 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
20213859Sml29623 			portn));
20223859Sml29623 
20233859Sml29623 	if (rs != NPI_SUCCESS)
20243859Sml29623 		return (NXGE_ERROR | rs);
20253859Sml29623 	else
20263859Sml29623 		return (status);
20273859Sml29623 }
20283859Sml29623 
20293859Sml29623 /* Disable RXMAC */
20303859Sml29623 
20313859Sml29623 nxge_status_t
20323859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
20333859Sml29623 {
20343859Sml29623 	npi_handle_t	handle;
20353859Sml29623 	uint8_t		portn;
20363859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
20373859Sml29623 
20383859Sml29623 	handle = nxgep->npi_handle;
20393859Sml29623 	portn = nxgep->mac.portnum;
20403859Sml29623 
20413859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
20423859Sml29623 			portn));
20433859Sml29623 
20443859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
20453859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
20463859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
20473859Sml29623 			goto fail;
20483859Sml29623 	} else {
20493859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
20503859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
20513859Sml29623 			goto fail;
20523859Sml29623 	}
20533859Sml29623 
20543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
20553859Sml29623 			portn));
20563859Sml29623 	return (NXGE_OK);
20573859Sml29623 fail:
20583859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20593859Sml29623 			"nxgep_rx_mac_disable: ",
20603859Sml29623 			"Failed to disable port<%d> RxMAC",
20613859Sml29623 			portn));
20623859Sml29623 
20633859Sml29623 	return (NXGE_ERROR | rs);
20643859Sml29623 }
20653859Sml29623 
20663859Sml29623 /* Reset TXMAC */
20673859Sml29623 
20683859Sml29623 nxge_status_t
20693859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
20703859Sml29623 {
20713859Sml29623 	npi_handle_t	handle;
20723859Sml29623 	uint8_t		portn;
20733859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
20743859Sml29623 
20753859Sml29623 	handle = nxgep->npi_handle;
20763859Sml29623 	portn = nxgep->mac.portnum;
20773859Sml29623 
20783859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
20793859Sml29623 			portn));
20803859Sml29623 
20813859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
20823859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
20833859Sml29623 		    != NPI_SUCCESS)
20843859Sml29623 			goto fail;
20853859Sml29623 	} else {
20863859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
20873859Sml29623 					!= NPI_SUCCESS)
20883859Sml29623 			goto fail;
20893859Sml29623 	}
20903859Sml29623 
20913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
20923859Sml29623 			portn));
20933859Sml29623 
20943859Sml29623 	return (NXGE_OK);
20953859Sml29623 fail:
20963859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20973859Sml29623 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
20983859Sml29623 			portn));
20993859Sml29623 
21003859Sml29623 	return (NXGE_ERROR | rs);
21013859Sml29623 }
21023859Sml29623 
21033859Sml29623 /* Reset RXMAC */
21043859Sml29623 
21053859Sml29623 nxge_status_t
21063859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
21073859Sml29623 {
21083859Sml29623 	npi_handle_t	handle;
21093859Sml29623 	uint8_t		portn;
21103859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
21113859Sml29623 
21123859Sml29623 	handle = nxgep->npi_handle;
21133859Sml29623 	portn = nxgep->mac.portnum;
21143859Sml29623 
21153859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
21163859Sml29623 			portn));
21173859Sml29623 
21183859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
21193859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
21203859Sml29623 		    != NPI_SUCCESS)
21213859Sml29623 		goto fail;
21223859Sml29623 	} else {
21233859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
21243859Sml29623 					!= NPI_SUCCESS)
21253859Sml29623 		goto fail;
21263859Sml29623 	}
21273859Sml29623 
21283859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
21293859Sml29623 			portn));
21303859Sml29623 
21313859Sml29623 	return (NXGE_OK);
21323859Sml29623 fail:
21333859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21343859Sml29623 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
21353859Sml29623 			portn));
21363859Sml29623 	return (NXGE_ERROR | rs);
21373859Sml29623 }
21383859Sml29623 
21394732Sdavemq /* 10G fiber link interrupt start routine */
21404732Sdavemq 
21414732Sdavemq static nxge_status_t
21424732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
21434732Sdavemq {
21444732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
21454732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
21464732Sdavemq 
21474732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
21484732Sdavemq 
21494732Sdavemq 	if (rs != NPI_SUCCESS)
21504732Sdavemq 		return (NXGE_ERROR | rs);
21514732Sdavemq 	else
21524732Sdavemq 		return (NXGE_OK);
21534732Sdavemq }
21544732Sdavemq 
21554732Sdavemq /* 10G fiber link interrupt stop routine */
21564732Sdavemq 
21574732Sdavemq static nxge_status_t
21584732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
21594732Sdavemq {
21604732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
21614732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
21624732Sdavemq 
21634732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
21644732Sdavemq 
21654732Sdavemq 	if (rs != NPI_SUCCESS)
21664732Sdavemq 		return (NXGE_ERROR | rs);
21674732Sdavemq 	else
21684732Sdavemq 		return (NXGE_OK);
21694732Sdavemq }
21704732Sdavemq 
21714732Sdavemq /* 1G fiber link interrupt start routine */
21724732Sdavemq 
21734732Sdavemq static nxge_status_t
21744732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
21754732Sdavemq {
21764732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
21774732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
21784732Sdavemq 
21794732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
21804732Sdavemq 	if (rs != NPI_SUCCESS)
21814732Sdavemq 		return (NXGE_ERROR | rs);
21824732Sdavemq 	else
21834732Sdavemq 		return (NXGE_OK);
21844732Sdavemq }
21854732Sdavemq 
21864732Sdavemq /* 1G fiber link interrupt stop routine */
21874732Sdavemq 
21884732Sdavemq static nxge_status_t
21894732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
21904732Sdavemq {
21914732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
21924732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
21934732Sdavemq 
21944732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
21954732Sdavemq 
21964732Sdavemq 	if (rs != NPI_SUCCESS)
21974732Sdavemq 		return (NXGE_ERROR | rs);
21984732Sdavemq 	else
21994732Sdavemq 		return (NXGE_OK);
22004732Sdavemq }
22014732Sdavemq 
22024732Sdavemq /* 1G copper link interrupt start routine */
22034732Sdavemq 
22044732Sdavemq static nxge_status_t
22054732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
22064732Sdavemq {
22074732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
22084732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
22094732Sdavemq 
22104732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
22114732Sdavemq 	    MII_BMSR, BMSR_LSTATUS);
22124732Sdavemq 
22134732Sdavemq 	if (rs != NPI_SUCCESS)
22144732Sdavemq 		return (NXGE_ERROR | rs);
22154732Sdavemq 	else
22164732Sdavemq 		return (NXGE_OK);
22174732Sdavemq }
22184732Sdavemq 
22194732Sdavemq /* 1G copper link interrupt stop routine */
22204732Sdavemq 
22214732Sdavemq static nxge_status_t
22224732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
22234732Sdavemq {
22244732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
22254732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
22264732Sdavemq 
22274732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
22284732Sdavemq 
22294732Sdavemq 	if (rs != NPI_SUCCESS)
22304732Sdavemq 		return (NXGE_ERROR | rs);
22314732Sdavemq 	else
22324732Sdavemq 		return (NXGE_OK);
22334732Sdavemq }
22344732Sdavemq 
22354732Sdavemq /* Enable/Disable Link Status change interrupt */
22363859Sml29623 
22373859Sml29623 nxge_status_t
22383859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
22393859Sml29623 {
22404732Sdavemq 	uint8_t		portn;
22414732Sdavemq 	nxge_status_t	status = NXGE_OK;
22423859Sml29623 
22433859Sml29623 	portn = nxgep->mac.portnum;
22443859Sml29623 
22453859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
22464732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
22474732Sdavemq 		return (NXGE_OK);
22484732Sdavemq 
22494732Sdavemq 	if (enable == LINK_INTR_START)
22504732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
22514732Sdavemq 	else if (enable == LINK_INTR_STOP)
22524732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
22534732Sdavemq 	if (status != NXGE_OK)
22544732Sdavemq 		goto fail;
22553859Sml29623 
22563859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
22573859Sml29623 
22583859Sml29623 	return (NXGE_OK);
22593859Sml29623 fail:
22603859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
22613859Sml29623 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
22623859Sml29623 			portn));
22633859Sml29623 
22644732Sdavemq 	return (status);
22653859Sml29623 }
22663859Sml29623 
22673859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
22683859Sml29623 
22693859Sml29623 nxge_status_t
22703859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
22713859Sml29623 {
22723859Sml29623 	p_nxge_param_t	param_arr;
22733859Sml29623 	p_nxge_stats_t	statsp;
22743859Sml29623 	uint8_t		xcvr_portn;
22753859Sml29623 	p_mii_regs_t	mii_regs;
22763859Sml29623 	mii_bmcr_t	bmcr;
22773859Sml29623 	mii_bmsr_t	bmsr;
22783859Sml29623 	mii_anar_t	anar;
22793859Sml29623 	mii_gcr_t	gcr;
22803859Sml29623 	mii_esr_t	esr;
22813859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
22823859Sml29623 	int		status = NXGE_OK;
22833859Sml29623 
22843859Sml29623 	uint_t delay;
22853859Sml29623 
22863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
22873859Sml29623 
22883859Sml29623 	param_arr = nxgep->param_arr;
22893859Sml29623 	statsp = nxgep->statsp;
22903859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
22913859Sml29623 
22923859Sml29623 	mii_regs = NULL;
22933859Sml29623 
22943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
22953859Sml29623 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
22963859Sml29623 
22973859Sml29623 	/*
22983859Sml29623 	 * Reset the transceiver.
22993859Sml29623 	 */
23003859Sml29623 	delay = 0;
23013859Sml29623 	bmcr.value = 0;
23023859Sml29623 	bmcr.bits.reset = 1;
23033859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2304*5125Sjoycey #if defined(__i386)
2305*5125Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2306*5125Sjoycey #else
23073859Sml29623 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2308*5125Sjoycey #endif
23093859Sml29623 		goto fail;
23103859Sml29623 	do {
23113859Sml29623 		drv_usecwait(500);
23123859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
2313*5125Sjoycey #if defined(__i386)
2314*5125Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
2315*5125Sjoycey #else
23163859Sml29623 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
2317*5125Sjoycey #endif
23183859Sml29623 				!= NXGE_OK)
23193859Sml29623 			goto fail;
23203859Sml29623 		delay++;
23213859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
23223859Sml29623 	if (delay == 1000) {
23233859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
23243859Sml29623 		goto fail;
23253859Sml29623 	}
23263859Sml29623 
23273859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2328*5125Sjoycey #if defined(__i386)
2329*5125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
2330*5125Sjoycey #else
23313859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
2332*5125Sjoycey #endif
23333859Sml29623 			&bmsr.value)) != NXGE_OK)
23343859Sml29623 		goto fail;
23353859Sml29623 
23363859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
23373859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
23383859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
23393859Sml29623 	param_arr[param_anar_100hdx].value = 0;
23403859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
23413859Sml29623 	param_arr[param_anar_10hdx].value = 0;
23423859Sml29623 
23433859Sml29623 	/*
23443859Sml29623 	 * Initialize the xcvr statistics.
23453859Sml29623 	 */
23463859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
23473859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
23483859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
23493859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
23503859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
23513859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
23523859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
23533859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
23543859Sml29623 
23553859Sml29623 	/*
23563859Sml29623 	 * Initialise the xcvr advertised capability statistics.
23573859Sml29623 	 */
23583859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
23593859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
23603859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
23613859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
23623859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
23633859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
23643859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
23653859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
23663859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
23673859Sml29623 					param_arr[param_anar_asmpause].value;
23683859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
23693859Sml29623 
23703859Sml29623 
23713859Sml29623 	/*
23723859Sml29623 	 * Check for extended status just in case we're
23733859Sml29623 	 * running a Gigibit phy.
23743859Sml29623 	 */
23753859Sml29623 	if (bmsr.bits.extend_status) {
23763859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
2377*5125Sjoycey #if defined(__i386)
2378*5125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
2379*5125Sjoycey #else
23803859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
2381*5125Sjoycey #endif
23823859Sml29623 				!= NXGE_OK)
23833859Sml29623 			goto fail;
23843859Sml29623 		param_arr[param_anar_1000fdx].value &=
23853859Sml29623 					esr.bits.link_1000fdx;
23863859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
23873859Sml29623 
23883859Sml29623 		statsp->mac_stats.cap_1000fdx =
23893859Sml29623 			(esr.bits.link_1000Xfdx ||
23903859Sml29623 				esr.bits.link_1000fdx);
23913859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
23923859Sml29623 	} else {
23933859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
23943859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
23953859Sml29623 	}
23963859Sml29623 
23973859Sml29623 	/*
23983859Sml29623 	 * Initialize 1G Statistics once the capability is established.
23993859Sml29623 	 */
24003859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
24013859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
24023859Sml29623 
24033859Sml29623 	/*
24043859Sml29623 	 * Initialise the link statistics.
24053859Sml29623 	 */
24063859Sml29623 	statsp->mac_stats.link_T4 = 0;
24073859Sml29623 	statsp->mac_stats.link_asmpause = 0;
24083859Sml29623 	statsp->mac_stats.link_pause = 0;
24093859Sml29623 	statsp->mac_stats.link_speed = 0;
24103859Sml29623 	statsp->mac_stats.link_duplex = 0;
24113859Sml29623 	statsp->mac_stats.link_up = 0;
24123859Sml29623 
24133859Sml29623 	/*
24143859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
24153859Sml29623 	 */
24163859Sml29623 	bmcr.value = 0;
24173859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2418*5125Sjoycey #if defined(__i386)
2419*5125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
2420*5125Sjoycey #else
24213859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
2422*5125Sjoycey #endif
24233859Sml29623 		goto fail;
24243859Sml29623 
24253859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
24263859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
24273859Sml29623 		bmcr.bits.loopback = 1;
24283859Sml29623 		bmcr.bits.enable_autoneg = 0;
24293859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
24303859Sml29623 			bmcr.bits.speed_1000_sel = 1;
24313859Sml29623 		bmcr.bits.duplex_mode = 1;
24323859Sml29623 		param_arr[param_autoneg].value = 0;
24333859Sml29623 	} else {
24343859Sml29623 		bmcr.bits.loopback = 0;
24353859Sml29623 	}
24363859Sml29623 
24373859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
24383859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
24393859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
24403859Sml29623 		param_arr[param_autoneg].value = 0;
24413859Sml29623 		bcm5464r_aux.value = 0;
24423859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
24433859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
24443859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
24453859Sml29623 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
24463859Sml29623 				!= NXGE_OK)
24473859Sml29623 			goto fail;
24483859Sml29623 	}
24493859Sml29623 
24503859Sml29623 	if (param_arr[param_autoneg].value) {
24513859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
24523859Sml29623 				"Restarting Auto-negotiation."));
24533859Sml29623 		/*
24543859Sml29623 		 * Setup our Auto-negotiation advertisement register.
24553859Sml29623 		 */
24563859Sml29623 		anar.value = 0;
24573859Sml29623 		anar.bits.selector = 1;
24583859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
24593859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
24603859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
24613859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
24623859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
24633859Sml29623 		anar.bits.cap_asmpause = 0;
24643859Sml29623 		anar.bits.cap_pause = 0;
24653859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
24663859Sml29623 			param_arr[param_anar_100fdx].value ||
24673859Sml29623 			param_arr[param_anar_10fdx].value) {
24683859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
24693859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
24703859Sml29623 		}
24713859Sml29623 
24723859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
2473*5125Sjoycey #if defined(__i386)
2474*5125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
2475*5125Sjoycey #else
24763859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
2477*5125Sjoycey #endif
24783859Sml29623 				!= NXGE_OK)
24793859Sml29623 			goto fail;
24803859Sml29623 		if (bmsr.bits.extend_status) {
24813859Sml29623 			gcr.value = 0;
24823859Sml29623 			gcr.bits.ms_mode_en =
24833859Sml29623 				param_arr[param_master_cfg_enable].value;
24843859Sml29623 			gcr.bits.master =
24853859Sml29623 				param_arr[param_master_cfg_value].value;
24863859Sml29623 			gcr.bits.link_1000fdx =
24873859Sml29623 				param_arr[param_anar_1000fdx].value;
24883859Sml29623 			gcr.bits.link_1000hdx =
24893859Sml29623 				param_arr[param_anar_1000hdx].value;
24903859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2491*5125Sjoycey #if defined(__i386)
2492*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
2493*5125Sjoycey #else
24943859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
2495*5125Sjoycey #endif
24963859Sml29623 				!= NXGE_OK)
24973859Sml29623 				goto fail;
24983859Sml29623 		}
24993859Sml29623 
25003859Sml29623 		bmcr.bits.enable_autoneg = 1;
25013859Sml29623 		bmcr.bits.restart_autoneg = 1;
25023859Sml29623 
25033859Sml29623 	} else {
25043859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
25053859Sml29623 		bmcr.bits.speed_1000_sel =
25063859Sml29623 			param_arr[param_anar_1000fdx].value |
25073859Sml29623 				param_arr[param_anar_1000hdx].value;
25083859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
25093859Sml29623 			(param_arr[param_anar_100fdx].value |
25103859Sml29623 				param_arr[param_anar_100hdx].value);
25113859Sml29623 		if (bmcr.bits.speed_1000_sel) {
25123859Sml29623 			statsp->mac_stats.link_speed = 1000;
25133859Sml29623 			gcr.value = 0;
25143859Sml29623 			gcr.bits.ms_mode_en =
25153859Sml29623 				param_arr[param_master_cfg_enable].value;
25163859Sml29623 			gcr.bits.master =
25173859Sml29623 				param_arr[param_master_cfg_value].value;
25183859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2519*5125Sjoycey #if defined(__i386)
2520*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
2521*5125Sjoycey #else
25223859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr),
2523*5125Sjoycey #endif
25243859Sml29623 				gcr.value))
25253859Sml29623 				!= NXGE_OK)
25263859Sml29623 				goto fail;
25273859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
25283859Sml29623 				bmcr.bits.duplex_mode = 1;
25293859Sml29623 				statsp->mac_stats.link_duplex = 2;
25303859Sml29623 			} else
25313859Sml29623 				statsp->mac_stats.link_duplex = 1;
25323859Sml29623 		} else if (bmcr.bits.speed_sel) {
25333859Sml29623 			statsp->mac_stats.link_speed = 100;
25343859Sml29623 			if (param_arr[param_anar_100fdx].value) {
25353859Sml29623 				bmcr.bits.duplex_mode = 1;
25363859Sml29623 				statsp->mac_stats.link_duplex = 2;
25373859Sml29623 			} else
25383859Sml29623 				statsp->mac_stats.link_duplex = 1;
25393859Sml29623 		} else {
25403859Sml29623 			statsp->mac_stats.link_speed = 10;
25413859Sml29623 			if (param_arr[param_anar_10fdx].value) {
25423859Sml29623 				bmcr.bits.duplex_mode = 1;
25433859Sml29623 				statsp->mac_stats.link_duplex = 2;
25443859Sml29623 			} else
25453859Sml29623 				statsp->mac_stats.link_duplex = 1;
25463859Sml29623 		}
25473859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
25483859Sml29623 			statsp->mac_stats.link_asmpause =
25493859Sml29623 						statsp->mac_stats.cap_asmpause;
25503859Sml29623 			statsp->mac_stats.link_pause =
25513859Sml29623 						statsp->mac_stats.cap_pause;
25523859Sml29623 		}
25533859Sml29623 
25543859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
25553859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
25563859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
25573859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
25583859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
25593859Sml29623 				gcr.value = 0;
25603859Sml29623 				gcr.bits.ms_mode_en = 1;
25613859Sml29623 				gcr.bits.master = 1;
25623859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
2563*5125Sjoycey #if defined(__i386)
2564*5125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
2565*5125Sjoycey #else
25663859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gcr),
2567*5125Sjoycey #endif
25683859Sml29623 					gcr.value))
25693859Sml29623 					!= NXGE_OK)
25703859Sml29623 					goto fail;
25713859Sml29623 				bmcr.value = 0;
25723859Sml29623 				bmcr.bits.speed_1000_sel = 1;
25733859Sml29623 				statsp->mac_stats.link_speed = 1000;
25743859Sml29623 			} else if (statsp->port_stats.lb_mode
25753859Sml29623 			    == nxge_lb_ext100) {
25763859Sml29623 				/* BCM5464R 100mbps external loopback mode */
25773859Sml29623 				bmcr.value = 0;
25783859Sml29623 				bmcr.bits.speed_sel = 1;
25793859Sml29623 				bmcr.bits.duplex_mode = 1;
25803859Sml29623 				statsp->mac_stats.link_speed = 100;
25813859Sml29623 			} else if (statsp->port_stats.lb_mode
25823859Sml29623 			    == nxge_lb_ext10) {
25833859Sml29623 				/* BCM5464R 10mbps external loopback mode */
25843859Sml29623 				bmcr.value = 0;
25853859Sml29623 				bmcr.bits.duplex_mode = 1;
25863859Sml29623 				statsp->mac_stats.link_speed = 10;
25873859Sml29623 			}
25883859Sml29623 		}
25893859Sml29623 	}
25903859Sml29623 
25913859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2592*5125Sjoycey #if defined(__i386)
2593*5125Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
2594*5125Sjoycey #else
25953859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
2596*5125Sjoycey #endif
25973859Sml29623 			bmcr.value)) != NXGE_OK)
25983859Sml29623 		goto fail;
25993859Sml29623 
26003859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2601*5125Sjoycey #if defined(__i386)
2602*5125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
2603*5125Sjoycey #else
26043859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
2605*5125Sjoycey #endif
26063859Sml29623 		goto fail;
26073859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
26083859Sml29623 
26093859Sml29623 	/*
26103859Sml29623 	 * Initialize the xcvr status kept in the context structure.
26113859Sml29623 	 */
26123859Sml29623 	nxgep->soft_bmsr.value = 0;
26133859Sml29623 
26143859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2615*5125Sjoycey #if defined(__i386)
2616*5125Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
2617*5125Sjoycey #else
26183859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
2619*5125Sjoycey #endif
26203859Sml29623 			&nxgep->bmsr.value)) != NXGE_OK)
26213859Sml29623 		goto fail;
26223859Sml29623 
26233859Sml29623 	statsp->mac_stats.xcvr_inits++;
26243859Sml29623 	nxgep->bmsr.value = 0;
26253859Sml29623 
26263859Sml29623 fail:
26273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
26283859Sml29623 			"<== nxge_mii_xcvr_init status 0x%x", status));
26293859Sml29623 	return (status);
26303859Sml29623 }
26313859Sml29623 
26323859Sml29623 /* Read from a MII compliant register */
26333859Sml29623 
26343859Sml29623 nxge_status_t
26353859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
26363859Sml29623 		uint16_t *value)
26373859Sml29623 {
26383859Sml29623 	npi_status_t rs = NPI_SUCCESS;
26393859Sml29623 
26403859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
26413859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
26423859Sml29623 
26433859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
26443859Sml29623 
26453859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
26463859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
26473859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
26483859Sml29623 			goto fail;
26494977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
26504977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
26513859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
26523859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
26533859Sml29623 			goto fail;
26543859Sml29623 	} else
26553859Sml29623 		goto fail;
26563859Sml29623 
26573859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
26583859Sml29623 
26593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
26603859Sml29623 			"xcvr_reg<%d> value=0x%x",
26613859Sml29623 			xcvr_portn, xcvr_reg, *value));
26623859Sml29623 	return (NXGE_OK);
26633859Sml29623 fail:
26643859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
26653859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26663859Sml29623 			"nxge_mii_read: Failed to read mii on xcvr %d",
26673859Sml29623 			xcvr_portn));
26683859Sml29623 
26693859Sml29623 	return (NXGE_ERROR | rs);
26703859Sml29623 }
26713859Sml29623 
26723859Sml29623 /* Write to a MII compliant Register */
26733859Sml29623 
26743859Sml29623 nxge_status_t
26753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
26763859Sml29623 		uint16_t value)
26773859Sml29623 {
26783859Sml29623 	npi_status_t rs = NPI_SUCCESS;
26793859Sml29623 
26803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
26813859Sml29623 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
26823859Sml29623 			value));
26833859Sml29623 
26843859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
26853859Sml29623 
26863859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
26873859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
26883859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
26893859Sml29623 			goto fail;
26904977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
26914977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
26923859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
26933859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
26943859Sml29623 			goto fail;
26953859Sml29623 	} else
26963859Sml29623 		goto fail;
26973859Sml29623 
26983859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
26993859Sml29623 
27003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
27013859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
27023859Sml29623 	return (NXGE_OK);
27033859Sml29623 fail:
27043859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
27053859Sml29623 
27063859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27073859Sml29623 			"nxge_mii_write: Failed to write mii on xcvr %d",
27083859Sml29623 			xcvr_portn));
27093859Sml29623 
27103859Sml29623 	return (NXGE_ERROR | rs);
27113859Sml29623 }
27123859Sml29623 
27133859Sml29623 /* Perform read from Clause45 serdes / transceiver device */
27143859Sml29623 
27153859Sml29623 nxge_status_t
27163859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
27173859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
27183859Sml29623 {
27193859Sml29623 	npi_status_t rs = NPI_SUCCESS;
27203859Sml29623 
27213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
27223859Sml29623 			xcvr_portn));
27233859Sml29623 
27243859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
27253859Sml29623 
27263859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
27273859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
27283859Sml29623 		goto fail;
27293859Sml29623 
27303859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
27313859Sml29623 
27323859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
27333859Sml29623 			xcvr_portn));
27343859Sml29623 	return (NXGE_OK);
27353859Sml29623 fail:
27363859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
27373859Sml29623 
27383859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27393859Sml29623 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
27403859Sml29623 			xcvr_portn));
27413859Sml29623 
27423859Sml29623 	return (NXGE_ERROR | rs);
27433859Sml29623 }
27443859Sml29623 
27453859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
27463859Sml29623 
27473859Sml29623 nxge_status_t
27483859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
27493859Sml29623 		uint16_t xcvr_reg, uint16_t value)
27503859Sml29623 {
27513859Sml29623 	npi_status_t rs = NPI_SUCCESS;
27523859Sml29623 
27533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
27543859Sml29623 			xcvr_portn));
27553859Sml29623 
27563859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
27573859Sml29623 
27583859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
27593859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
27603859Sml29623 		goto fail;
27613859Sml29623 
27623859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
27633859Sml29623 
27643859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
27653859Sml29623 			xcvr_portn));
27663859Sml29623 	return (NXGE_OK);
27673859Sml29623 fail:
27683859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
27693859Sml29623 
27703859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27713859Sml29623 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
27723859Sml29623 			xcvr_portn));
27733859Sml29623 
27743859Sml29623 	return (NXGE_ERROR | rs);
27753859Sml29623 }
27763859Sml29623 
27773859Sml29623 
27783859Sml29623 /* Check MII to see if there is any link status change */
27793859Sml29623 
27803859Sml29623 nxge_status_t
27813859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
27823859Sml29623 		nxge_link_state_t *link_up)
27833859Sml29623 {
27843859Sml29623 	p_nxge_param_t	param_arr;
27853859Sml29623 	p_nxge_stats_t	statsp;
27863859Sml29623 	p_mii_regs_t	mii_regs;
27873859Sml29623 	p_mii_bmsr_t	soft_bmsr;
27883859Sml29623 	mii_anar_t	anar;
27893859Sml29623 	mii_anlpar_t	anlpar;
27903859Sml29623 	mii_anar_t	an_common;
27913859Sml29623 	mii_aner_t	aner;
27923859Sml29623 	mii_gsr_t	gsr;
27933859Sml29623 	nxge_status_t	status = NXGE_OK;
27943859Sml29623 
27953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
27963859Sml29623 
27973859Sml29623 	mii_regs = NULL;
27983859Sml29623 	param_arr = nxgep->param_arr;
27993859Sml29623 	statsp = nxgep->statsp;
28003859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
28013859Sml29623 	*link_up = LINK_NO_CHANGE;
28023859Sml29623 
28033859Sml29623 	if (bmsr_ints.bits.link_status) {
28043859Sml29623 		if (bmsr.bits.link_status) {
28053859Sml29623 			soft_bmsr->bits.link_status = 1;
28063859Sml29623 		} else {
28073859Sml29623 			statsp->mac_stats.link_up = 0;
28083859Sml29623 			soft_bmsr->bits.link_status = 0;
28093859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
28103859Sml29623 					"Link down cable problem"));
28113859Sml29623 			*link_up = LINK_IS_DOWN;
28123859Sml29623 		}
28133859Sml29623 	}
28143859Sml29623 
28153859Sml29623 	if (param_arr[param_autoneg].value) {
28163859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
28173859Sml29623 			if (bmsr.bits.auto_neg_complete)
28183859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
28193859Sml29623 			else
28203859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
28213859Sml29623 		}
28223859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
28233859Sml29623 			statsp->mac_stats.link_T4 = 0;
28243859Sml29623 			statsp->mac_stats.link_speed = 0;
28253859Sml29623 			statsp->mac_stats.link_duplex = 0;
28263859Sml29623 			statsp->mac_stats.link_asmpause = 0;
28273859Sml29623 			statsp->mac_stats.link_pause = 0;
28283859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
28293859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
28303859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
28313859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
28323859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
28333859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
28343859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
28353859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
28363859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
28373859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
28383859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
28393859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
28403859Sml29623 		}
28413859Sml29623 	} else
28423859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
28433859Sml29623 
28443859Sml29623 	if ((bmsr_ints.bits.link_status ||
28453859Sml29623 		bmsr_ints.bits.auto_neg_complete) &&
28463859Sml29623 		soft_bmsr->bits.link_status &&
28473859Sml29623 		soft_bmsr->bits.auto_neg_complete) {
28483859Sml29623 		statsp->mac_stats.link_up = 1;
28493859Sml29623 		if (param_arr[param_autoneg].value) {
28503859Sml29623 			if ((status = nxge_mii_read(nxgep,
28513859Sml29623 				statsp->mac_stats.xcvr_portn,
2852*5125Sjoycey #if defined(__i386)
2853*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
2854*5125Sjoycey #else
28553859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anar),
2856*5125Sjoycey #endif
28573859Sml29623 					&anar.value)) != NXGE_OK)
28583859Sml29623 				goto fail;
28593859Sml29623 			if ((status = nxge_mii_read(nxgep,
28603859Sml29623 				statsp->mac_stats.xcvr_portn,
2861*5125Sjoycey #if defined(__i386)
2862*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
2863*5125Sjoycey #else
28643859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
2865*5125Sjoycey #endif
28663859Sml29623 					&anlpar.value)) != NXGE_OK)
28673859Sml29623 				goto fail;
28683859Sml29623 			if ((status = nxge_mii_read(nxgep,
28693859Sml29623 				statsp->mac_stats.xcvr_portn,
2870*5125Sjoycey #if defined(__i386)
2871*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
2872*5125Sjoycey #else
28733859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->aner),
2874*5125Sjoycey #endif
28753859Sml29623 					&aner.value)) != NXGE_OK)
28763859Sml29623 				goto fail;
28773859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
28783859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
28793859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
28803859Sml29623 							anlpar.bits.cap_100fdx;
28813859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
28823859Sml29623 							anlpar.bits.cap_100hdx;
28833859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
28843859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
28853859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
28863859Sml29623 						anlpar.bits.cap_asmpause;
28873859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
28883859Sml29623 			an_common.value = anar.value & anlpar.value;
28893859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
28903859Sml29623 				param_arr[param_anar_1000hdx].value) {
28913859Sml29623 				if ((status = nxge_mii_read(nxgep,
28923859Sml29623 					statsp->mac_stats.xcvr_portn,
2893*5125Sjoycey #if defined(__i386)
2894*5125Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
2895*5125Sjoycey #else
28963859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gsr),
2897*5125Sjoycey #endif
28983859Sml29623 						&gsr.value))
28993859Sml29623 						!= NXGE_OK)
29003859Sml29623 					goto fail;
29013859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
29023859Sml29623 					gsr.bits.link_1000fdx;
29033859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
29043859Sml29623 					gsr.bits.link_1000hdx;
29053859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
29063859Sml29623 					gsr.bits.link_1000fdx) {
29073859Sml29623 					statsp->mac_stats.link_speed = 1000;
29083859Sml29623 					statsp->mac_stats.link_duplex = 2;
29093859Sml29623 				} else if (
29103859Sml29623 					param_arr[param_anar_1000hdx].value &&
29113859Sml29623 						gsr.bits.link_1000hdx) {
29123859Sml29623 					statsp->mac_stats.link_speed = 1000;
29133859Sml29623 					statsp->mac_stats.link_duplex = 1;
29143859Sml29623 				}
29153859Sml29623 			}
29163859Sml29623 			if ((an_common.value != 0) &&
29173859Sml29623 					!(statsp->mac_stats.link_speed)) {
29183859Sml29623 				if (an_common.bits.cap_100T4) {
29193859Sml29623 					statsp->mac_stats.link_T4 = 1;
29203859Sml29623 					statsp->mac_stats.link_speed = 100;
29213859Sml29623 					statsp->mac_stats.link_duplex = 1;
29223859Sml29623 				} else if (an_common.bits.cap_100fdx) {
29233859Sml29623 					statsp->mac_stats.link_speed = 100;
29243859Sml29623 					statsp->mac_stats.link_duplex = 2;
29253859Sml29623 				} else if (an_common.bits.cap_100hdx) {
29263859Sml29623 					statsp->mac_stats.link_speed = 100;
29273859Sml29623 					statsp->mac_stats.link_duplex = 1;
29283859Sml29623 				} else if (an_common.bits.cap_10fdx) {
29293859Sml29623 					statsp->mac_stats.link_speed = 10;
29303859Sml29623 					statsp->mac_stats.link_duplex = 2;
29313859Sml29623 				} else if (an_common.bits.cap_10hdx) {
29323859Sml29623 					statsp->mac_stats.link_speed = 10;
29333859Sml29623 					statsp->mac_stats.link_duplex = 1;
29343859Sml29623 				} else {
29353859Sml29623 					goto fail;
29363859Sml29623 				}
29373859Sml29623 			}
29383859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
29393859Sml29623 				statsp->mac_stats.link_asmpause =
29403859Sml29623 					an_common.bits.cap_asmpause;
29413859Sml29623 				if (statsp->mac_stats.link_asmpause)
29423859Sml29623 				if ((statsp->mac_stats.cap_pause == 0) &&
29433859Sml29623 						(statsp->mac_stats.lp_cap_pause
29443859Sml29623 						== 1))
29453859Sml29623 						statsp->mac_stats.link_pause
29463859Sml29623 						= 0;
29473859Sml29623 					else
29483859Sml29623 						statsp->mac_stats.link_pause
29493859Sml29623 						= 1;
29503859Sml29623 				else
29513859Sml29623 					statsp->mac_stats.link_pause =
29523859Sml29623 						an_common.bits.cap_pause;
29533859Sml29623 			}
29543859Sml29623 		}
29553859Sml29623 		*link_up = LINK_IS_UP;
29563859Sml29623 	}
29573859Sml29623 
29583859Sml29623 	if (nxgep->link_notify) {
29593859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
29603859Sml29623 				LINK_IS_DOWN);
29613859Sml29623 		nxgep->link_notify = B_FALSE;
29623859Sml29623 	}
29633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
29643859Sml29623 	return (NXGE_OK);
29653859Sml29623 fail:
29663859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
29673859Sml29623 			"nxge_mii_check: Unable to check MII"));
29683859Sml29623 	return (status);
29693859Sml29623 }
29703859Sml29623 
29714977Sraghus /* Check PCS to see if there is any link status change */
29724977Sraghus nxge_status_t
29734977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
29744977Sraghus {
29754977Sraghus 	p_nxge_stats_t	statsp;
29764977Sraghus 	nxge_status_t	status = NXGE_OK;
29774977Sraghus 	boolean_t	linkup;
29784977Sraghus 
29794977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
29804977Sraghus 
29814977Sraghus 	statsp = nxgep->statsp;
29824977Sraghus 	*link_up = LINK_NO_CHANGE;
29834977Sraghus 
29844977Sraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
29854977Sraghus 	if (linkup) {
29864977Sraghus 		if (nxgep->link_notify ||
29874977Sraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
29884977Sraghus 			statsp->mac_stats.link_up = 1;
29894977Sraghus 			statsp->mac_stats.link_speed = 1000;
29904977Sraghus 			statsp->mac_stats.link_duplex = 2;
29914977Sraghus 			*link_up = LINK_IS_UP;
29924977Sraghus 			nxgep->link_notify = B_FALSE;
29934977Sraghus 		}
29944977Sraghus 	} else {
29954977Sraghus 		if (nxgep->link_notify ||
29964977Sraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
29974977Sraghus 			statsp->mac_stats.link_up = 0;
29984977Sraghus 			statsp->mac_stats.link_speed = 0;
29994977Sraghus 			statsp->mac_stats.link_duplex = 0;
30004977Sraghus 			*link_up = LINK_IS_DOWN;
30014977Sraghus 			nxgep->link_notify = B_FALSE;
30024977Sraghus 		}
30034977Sraghus 	}
30044977Sraghus 
30054977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
30064977Sraghus 	return (NXGE_OK);
30074977Sraghus fail:
30084977Sraghus 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
30094977Sraghus 	    "nxge_pcs_check: Unable to check PCS"));
30104977Sraghus 	return (status);
30114977Sraghus }
30124977Sraghus 
30133859Sml29623 /* Add a multicast address entry into the HW hash table */
30143859Sml29623 
30153859Sml29623 nxge_status_t
30163859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
30173859Sml29623 {
30183859Sml29623 	uint32_t mchash;
30193859Sml29623 	p_hash_filter_t hash_filter;
30203859Sml29623 	uint16_t hash_bit;
30213859Sml29623 	boolean_t rx_init = B_FALSE;
30223859Sml29623 	uint_t j;
30233859Sml29623 	nxge_status_t status = NXGE_OK;
30243859Sml29623 
30253859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
30263859Sml29623 
30273859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
30283859Sml29623 	mchash = crc32_mchash(addrp);
30293859Sml29623 	if (nxgep->hash_filter == NULL) {
30303859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
30313859Sml29623 			"Allocating hash filter storage."));
30323859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
30333859Sml29623 					KM_SLEEP);
30343859Sml29623 	}
30353859Sml29623 	hash_filter = nxgep->hash_filter;
30363859Sml29623 	j = mchash / HASH_REG_WIDTH;
30373859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
30383859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
30393859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
30403859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
30413859Sml29623 		hash_filter->hash_ref_cnt++;
30423859Sml29623 		rx_init = B_TRUE;
30433859Sml29623 	}
30443859Sml29623 	if (rx_init) {
30453859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
30463859Sml29623 			goto fail;
30473859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
30483859Sml29623 			goto fail;
30493859Sml29623 	}
30503859Sml29623 
30513859Sml29623 	RW_EXIT(&nxgep->filter_lock);
30523859Sml29623 
30533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
30543859Sml29623 
30553859Sml29623 	return (NXGE_OK);
30563859Sml29623 fail:
30573859Sml29623 	RW_EXIT(&nxgep->filter_lock);
30583859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
30593859Sml29623 					"Unable to add multicast address"));
30603859Sml29623 	return (status);
30613859Sml29623 }
30623859Sml29623 
30633859Sml29623 /* Remove a multicast address entry from the HW hash table */
30643859Sml29623 
30653859Sml29623 nxge_status_t
30663859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
30673859Sml29623 {
30683859Sml29623 	uint32_t mchash;
30693859Sml29623 	p_hash_filter_t hash_filter;
30703859Sml29623 	uint16_t hash_bit;
30713859Sml29623 	boolean_t rx_init = B_FALSE;
30723859Sml29623 	uint_t j;
30733859Sml29623 	nxge_status_t status = NXGE_OK;
30743859Sml29623 
30753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
30763859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
30773859Sml29623 	mchash = crc32_mchash(addrp);
30783859Sml29623 	if (nxgep->hash_filter == NULL) {
30793859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
30803859Sml29623 			"Hash filter already de_allocated."));
30813859Sml29623 		RW_EXIT(&nxgep->filter_lock);
30823859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
30833859Sml29623 		return (NXGE_OK);
30843859Sml29623 	}
30853859Sml29623 	hash_filter = nxgep->hash_filter;
30863859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
30873859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
30883859Sml29623 		j = mchash / HASH_REG_WIDTH;
30893859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
30903859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
30913859Sml29623 		hash_filter->hash_ref_cnt--;
30923859Sml29623 		rx_init = B_TRUE;
30933859Sml29623 	}
30943859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
30953859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
30963859Sml29623 			"De-allocating hash filter storage."));
30973859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
30983859Sml29623 		nxgep->hash_filter = NULL;
30993859Sml29623 	}
31003859Sml29623 
31013859Sml29623 	if (rx_init) {
31023859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
31033859Sml29623 			goto fail;
31043859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
31053859Sml29623 			goto fail;
31063859Sml29623 	}
31073859Sml29623 	RW_EXIT(&nxgep->filter_lock);
31083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
31093859Sml29623 
31103859Sml29623 	return (NXGE_OK);
31113859Sml29623 fail:
31123859Sml29623 	RW_EXIT(&nxgep->filter_lock);
31133859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
31143859Sml29623 			"Unable to remove multicast address"));
31153859Sml29623 
31163859Sml29623 	return (status);
31173859Sml29623 }
31183859Sml29623 
31193859Sml29623 /* Set MAC address into MAC address HW registers */
31203859Sml29623 
31213859Sml29623 nxge_status_t
31223859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
31233859Sml29623 {
31243859Sml29623 	nxge_status_t status = NXGE_OK;
31253859Sml29623 
31263859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
31273859Sml29623 
31283859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
31293859Sml29623 	/*
31303859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
31313859Sml29623 	 */
31323859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
31333859Sml29623 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
31343859Sml29623 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
31353859Sml29623 		goto nxge_set_mac_addr_exit;
31363859Sml29623 	}
31373859Sml29623 	nxgep->ouraddr = *addrp;
31383859Sml29623 	/*
31393859Sml29623 	 * Set new interface local address and re-init device.
31403859Sml29623 	 * This is destructive to any other streams attached
31413859Sml29623 	 * to this device.
31423859Sml29623 	 */
31433859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
31443859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
31453859Sml29623 		goto fail;
31463859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
31473859Sml29623 		goto fail;
31483859Sml29623 
31493859Sml29623 	RW_EXIT(&nxgep->filter_lock);
31503859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
31513859Sml29623 	goto nxge_set_mac_addr_end;
31523859Sml29623 nxge_set_mac_addr_exit:
31533859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
31543859Sml29623 nxge_set_mac_addr_end:
31553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
31563859Sml29623 
31573859Sml29623 	return (NXGE_OK);
31583859Sml29623 fail:
31593859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
31603859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
31613859Sml29623 			"Unable to set mac address"));
31623859Sml29623 	return (status);
31633859Sml29623 }
31643859Sml29623 
31654693Stm144005 static
31664693Stm144005 check_link_state_t
31674693Stm144005 nxge_check_link_stop(
31684693Stm144005 	nxge_t *nxge)
31694693Stm144005 {
31704693Stm144005 	/* If the poll has been cancelled, return STOP. */
31714693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
31724693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
31734693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
31744693Stm144005 		nxge->nxge_link_poll_timerid = 0;
31754693Stm144005 		cv_broadcast(&nxge->poll_cv);
31764693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
31774693Stm144005 
31784693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
31794693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
31804693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
31814693Stm144005 		    nxge->mac.portnum));
31824693Stm144005 		return (CHECK_LINK_STOP);
31834693Stm144005 	}
31844693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
31854693Stm144005 
31864693Stm144005 	return (CHECK_LINK_RESCHEDULE);
31874693Stm144005 }
31884693Stm144005 
31893859Sml29623 /* Check status of MII (MIF or PCS) link */
31903859Sml29623 
31914732Sdavemq static nxge_status_t
31923859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
31933859Sml29623 {
31943859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
31953859Sml29623 	mii_anlpar_t anlpar;
31963859Sml29623 	mii_gsr_t gsr;
31973859Sml29623 	p_mii_regs_t mii_regs;
31983859Sml29623 	nxge_status_t status = NXGE_OK;
31993859Sml29623 	uint8_t portn;
32003859Sml29623 	nxge_link_state_t link_up;
32013859Sml29623 
32024693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
32034693Stm144005 		return (NXGE_ERROR);
32044693Stm144005 
32054693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
32064693Stm144005 		return (NXGE_OK);
32074693Stm144005 
32083859Sml29623 	portn = nxgep->mac.portnum;
32093859Sml29623 
32103859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
32114693Stm144005 	    portn));
32123859Sml29623 
32133859Sml29623 	mii_regs = NULL;
32143859Sml29623 
32153859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
32163859Sml29623 
32173859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
32183859Sml29623 		goto nxge_check_mii_link_exit;
32193859Sml29623 
32204977Sraghus 	switch (nxgep->mac.portmode) {
32214977Sraghus 	default:
32223859Sml29623 		if ((status = nxge_mii_read(nxgep,
32234977Sraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
3224*5125Sjoycey #if defined(__i386)
3225*5125Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3226*5125Sjoycey #else
32274977Sraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3228*5125Sjoycey #endif
32294977Sraghus 		    &bmsr_data.value)) != NXGE_OK) {
32303859Sml29623 			goto fail;
32313859Sml29623 		}
32324977Sraghus 
32334977Sraghus 		if (nxgep->param_arr[param_autoneg].value) {
32344977Sraghus 			if ((status = nxge_mii_read(nxgep,
32354977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
3236*5125Sjoycey #if defined(__i386)
3237*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
3238*5125Sjoycey #else
32394977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
3240*5125Sjoycey #endif
32414977Sraghus 				&gsr.value)) != NXGE_OK)
32424977Sraghus 				goto fail;
32434977Sraghus 			if ((status = nxge_mii_read(nxgep,
32444977Sraghus 				nxgep->statsp->mac_stats.xcvr_portn,
3245*5125Sjoycey #if defined(__i386)
3246*5125Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
3247*5125Sjoycey #else
32484977Sraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
3249*5125Sjoycey #endif
32504977Sraghus 				&anlpar.value)) != NXGE_OK)
32514977Sraghus 				goto fail;
32524977Sraghus 			if (nxgep->statsp->mac_stats.link_up &&
32534977Sraghus 				((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
32544977Sraghus 					gsr.bits.link_1000fdx) ||
32554977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
32564977Sraghus 					gsr.bits.link_1000hdx) ||
32574977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_100T4 ^
32584977Sraghus 					anlpar.bits.cap_100T4) ||
32594977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_100fdx ^
32604977Sraghus 					anlpar.bits.cap_100fdx) ||
32614977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_100hdx ^
32624977Sraghus 					anlpar.bits.cap_100hdx) ||
32634977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_10fdx ^
32644977Sraghus 					anlpar.bits.cap_10fdx) ||
32654977Sraghus 				(nxgep->statsp->mac_stats.lp_cap_10hdx ^
32664977Sraghus 					anlpar.bits.cap_10hdx))) {
32674977Sraghus 				bmsr_data.bits.link_status = 0;
32684977Sraghus 			}
32694977Sraghus 		}
32704977Sraghus 
32714977Sraghus 		/* Workaround for link down issue */
32724977Sraghus 		if (bmsr_data.value == 0) {
32734977Sraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
32744977Sraghus 			goto nxge_check_mii_link_exit;
32754977Sraghus 		}
32764977Sraghus 
32774977Sraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
32784977Sraghus 		nxgep->bmsr.value = bmsr_data.value;
32794977Sraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
32804977Sraghus 		    &link_up)) != NXGE_OK) {
32814977Sraghus 			goto fail;
32824977Sraghus 		}
32834977Sraghus 		break;
32844977Sraghus 
32854977Sraghus 	case PORT_1G_SERDES:
32864977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
32874977Sraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
32884977Sraghus 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
32894977Sraghus 		    != NXGE_OK) {
32904977Sraghus 			goto fail;
32914977Sraghus 		}
32924977Sraghus 		break;
32933859Sml29623 	}
32943859Sml29623 
32953859Sml29623 nxge_check_mii_link_exit:
32963859Sml29623 	RW_EXIT(&nxgep->filter_lock);
32973859Sml29623 	if (link_up == LINK_IS_UP) {
32983859Sml29623 		nxge_link_is_up(nxgep);
32993859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
33003859Sml29623 		nxge_link_is_down(nxgep);
33013859Sml29623 	}
33023859Sml29623 
33033859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
33043859Sml29623 
33053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
33064977Sraghus 				portn));
33073859Sml29623 	return (NXGE_OK);
33083859Sml29623 
33093859Sml29623 fail:
33103859Sml29623 	RW_EXIT(&nxgep->filter_lock);
33113859Sml29623 
33123859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
33133859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33144977Sraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
33154977Sraghus 			portn));
33163859Sml29623 	return (status);
33173859Sml29623 }
33183859Sml29623 
33193859Sml29623 
33203859Sml29623 /*ARGSUSED*/
33214732Sdavemq static nxge_status_t
33223859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
33233859Sml29623 {
33243859Sml29623 	uint8_t		portn;
33253859Sml29623 	nxge_status_t	status = NXGE_OK;
33263859Sml29623 	boolean_t	link_up;
33274977Sraghus 	boolean_t	xpcs_up, xmac_up;
33284977Sraghus 	uint32_t	val;
33294977Sraghus 	npi_status_t	rs;
33303859Sml29623 
33314693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
33324693Stm144005 		return (NXGE_ERROR);
33334693Stm144005 
33344693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
33354693Stm144005 		return (NXGE_OK);
33364693Stm144005 
33373859Sml29623 	portn = nxgep->mac.portnum;
33383859Sml29623 
33393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
33404693Stm144005 	    portn));
33413859Sml29623 
33424977Sraghus 	switch (nxgep->mac.portmode) {
33434977Sraghus 	default:
33444977Sraghus 		status = nxge_check_bcm8704_link(nxgep, &link_up);
33454977Sraghus 		if (status != NXGE_OK)
33464977Sraghus 			goto fail;
33474977Sraghus 		break;
33484977Sraghus 	case PORT_10G_SERDES:
33494977Sraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
33504977Sraghus 		    XPCS_REG_STATUS1, &val);
33514977Sraghus 		if (rs != 0)
33524977Sraghus 			goto fail;
33534977Sraghus 
33544977Sraghus 		link_up = B_FALSE;
33554977Sraghus 		xmac_up = B_FALSE;
33564977Sraghus 		xpcs_up = B_FALSE;
33574977Sraghus 		if (val & XPCS_STATUS1_RX_LINK_STATUS_UP) {
33584977Sraghus 			xpcs_up = B_TRUE;
33594977Sraghus 		}
33604977Sraghus 
33614977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
33624977Sraghus 		    "==> nxge_check_10g_link port<%d> "
33634977Sraghus 		    "XPCS_REG_STATUS1 0x%x xpcs_up %d",
33644977Sraghus 		    portn, val, xpcs_up));
33654977Sraghus 		/*
33664977Sraghus 		 * Read the xMAC internal signal 2 register.
33674977Sraghus 		 * This register should be the superset of the XPCS when wanting
33684977Sraghus 		 * to get the link status. If this register read is proved to be
33694977Sraghus 		 * reliable, there is no need to read the XPCS register.
33704977Sraghus 		 */
33714977Sraghus 		xmac_up = B_TRUE;
33724977Sraghus 		XMAC_REG_RD(nxgep->npi_handle, portn, XMAC_INTERN2_REG, &val);
33734977Sraghus 		if (val & XMAC_IS2_LOCAL_FLT_OC_SYNC) { /* link is down */
33744977Sraghus 			xmac_up = B_FALSE;
33754977Sraghus 		}
33764977Sraghus 
33774977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
33784977Sraghus 		    "==> nxge_check_10g_link port<%d> "
33794977Sraghus 		    "XMAC_INTERN2_REG 0x%x xmac_up %d",
33804977Sraghus 		    portn, val, xmac_up));
33814977Sraghus 
33824977Sraghus 		if (xpcs_up && xmac_up) {
33834977Sraghus 			link_up = B_TRUE;
33844977Sraghus 		}
33854977Sraghus 		break;
33864977Sraghus 	}
33873859Sml29623 
33883859Sml29623 	if (link_up) {
33893859Sml29623 		if (nxgep->link_notify ||
33903859Sml29623 			nxgep->statsp->mac_stats.link_up == 0) {
33913859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
33923859Sml29623 				goto fail;
33933859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
33943859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
33953859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
33963859Sml29623 
33973859Sml29623 			nxge_link_is_up(nxgep);
33983859Sml29623 			nxgep->link_notify = B_FALSE;
33993859Sml29623 		}
34003859Sml29623 	} else {
34013859Sml29623 		if (nxgep->link_notify ||
34023859Sml29623 			nxgep->statsp->mac_stats.link_up == 1) {
34033859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
34043859Sml29623 				goto fail;
34053859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
34064977Sraghus 					"Link down cable problem"));
34073859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
34083859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
34093859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
34103859Sml29623 
34113859Sml29623 			nxge_link_is_down(nxgep);
34123859Sml29623 			nxgep->link_notify = B_FALSE;
34133859Sml29623 		}
34143859Sml29623 	}
34153859Sml29623 
34163859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
34173859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
34184693Stm144005 	    portn));
34193859Sml29623 	return (NXGE_OK);
34203859Sml29623 
34213859Sml29623 fail:
34224693Stm144005 	(void) nxge_check_link_stop(nxgep);
34234693Stm144005 
34243859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
34254693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
34264693Stm144005 	    portn));
34273859Sml29623 	return (status);
34283859Sml29623 }
34293859Sml29623 
34303859Sml29623 
34313859Sml29623 /* Declare link down */
34323859Sml29623 
34333859Sml29623 void
34343859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
34353859Sml29623 {
34364732Sdavemq 	p_nxge_stats_t statsp;
34374732Sdavemq 	char link_stat_msg[64];
34384732Sdavemq 
34393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
34403859Sml29623 
34414732Sdavemq 	statsp = nxgep->statsp;
34424732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
34434732Sdavemq 	    statsp->mac_stats.xcvr_portn);
34444732Sdavemq 
34454732Sdavemq 	if (nxge_no_msg == B_FALSE) {
34464732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
34474732Sdavemq 	}
34484732Sdavemq 
34493859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
34503859Sml29623 
34513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
34523859Sml29623 }
34533859Sml29623 
34543859Sml29623 /* Declare link up */
34553859Sml29623 
34563859Sml29623 void
34573859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
34583859Sml29623 {
34594732Sdavemq 	p_nxge_stats_t statsp;
34604732Sdavemq 	char link_stat_msg[64];
34613859Sml29623 	uint32_t val;
34623859Sml29623 
34633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
34643859Sml29623 
34654732Sdavemq 	statsp = nxgep->statsp;
34664732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
34674732Sdavemq 	    statsp->mac_stats.xcvr_portn,
34684732Sdavemq 	    statsp->mac_stats.link_speed);
34694732Sdavemq 
34704732Sdavemq 	if (statsp->mac_stats.link_T4)
34714732Sdavemq 		(void) strcat(link_stat_msg, "T4");
34724732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
34734732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
34744732Sdavemq 	else
34754732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
34764732Sdavemq 
34773859Sml29623 	(void) nxge_xif_init(nxgep);
34783859Sml29623 
34793859Sml29623 	/* Clean up symbol errors incurred during link transition */
34804977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
34814977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
34823859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
34833859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
34843859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
34853859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
34863859Sml29623 	}
34873859Sml29623 
34884732Sdavemq 	if (nxge_no_msg == B_FALSE) {
34894732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
34904732Sdavemq 	}
34914732Sdavemq 
34923859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
34933859Sml29623 
34943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
34953859Sml29623 }
34963859Sml29623 
34973859Sml29623 /*
34983859Sml29623  * Calculate the bit in the multicast address filter
34993859Sml29623  * that selects the given * address.
35003859Sml29623  * Note: For GEM, the last 8-bits are used.
35013859Sml29623  */
35023859Sml29623 uint32_t
35033859Sml29623 crc32_mchash(p_ether_addr_t addr)
35043859Sml29623 {
35053859Sml29623 	uint8_t *cp;
35063859Sml29623 	uint32_t crc;
35073859Sml29623 	uint32_t c;
35083859Sml29623 	int byte;
35093859Sml29623 	int bit;
35103859Sml29623 
35113859Sml29623 	cp = (uint8_t *)addr;
35123859Sml29623 	crc = (uint32_t)0xffffffff;
35133859Sml29623 	for (byte = 0; byte < 6; byte++) {
35143859Sml29623 		c = (uint32_t)cp[byte];
35153859Sml29623 		for (bit = 0; bit < 8; bit++) {
35163859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
35173859Sml29623 				crc = (crc >> 1)^0xedb88320;
35183859Sml29623 			else
35193859Sml29623 				crc = (crc >> 1);
35203859Sml29623 			c >>= 1;
35213859Sml29623 		}
35223859Sml29623 	}
35233859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
35243859Sml29623 }
35253859Sml29623 
35263859Sml29623 /* Reset serdes */
35273859Sml29623 
35283859Sml29623 nxge_status_t
35293859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
35303859Sml29623 {
35313859Sml29623 	npi_handle_t		handle;
35323859Sml29623 
35333859Sml29623 	handle = nxgep->npi_handle;
35343859Sml29623 
35353859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
35363859Sml29623 	drv_usecwait(500);
35373859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
35383859Sml29623 
35393859Sml29623 	return (NXGE_OK);
35403859Sml29623 }
35413859Sml29623 
35423859Sml29623 /* Monitor link status using interrupt or polling */
35433859Sml29623 
35443859Sml29623 nxge_status_t
35453859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
35463859Sml29623 {
35473859Sml29623 	nxge_status_t status = NXGE_OK;
35483859Sml29623 
35493859Sml29623 	/*
35504693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
35514693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
35523859Sml29623 	 */
35534977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
35544977Sraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
35554977Sraghus 	    (nxgep->mac.portnum > 1))
35563859Sml29623 		return (NXGE_OK);
35573859Sml29623 
35583859Sml29623 	if (nxgep->statsp == NULL) {
35593859Sml29623 		/* stats has not been allocated. */
35603859Sml29623 		return (NXGE_OK);
35613859Sml29623 	}
35623859Sml29623 	/* Don't check link if we're not in internal loopback mode */
35633859Sml29623 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
35643859Sml29623 		return (NXGE_OK);
35653859Sml29623 
35663859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35674693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
35684693Stm144005 	    nxgep->mac.portnum, enable));
35693859Sml29623 	if (enable == LINK_MONITOR_START) {
35703859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
35713859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
35724693Stm144005 			    != NXGE_OK)
35733859Sml29623 				goto fail;
35743859Sml29623 		} else {
35754693Stm144005 			timeout_id_t timerid;
35764693Stm144005 
35774693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
35784693Stm144005 				return (NXGE_OK);
35794693Stm144005 
35804732Sdavemq 			if (nxgep->xcvr.check_link) {
35814732Sdavemq 				timerid = timeout(
35824732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
35834693Stm144005 				    nxgep,
35844693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
35854732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
35864732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
35874732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
35884732Sdavemq 			} else {
35894693Stm144005 				return (NXGE_ERROR);
35903859Sml29623 			}
35913859Sml29623 		}
35923859Sml29623 	} else {
35933859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
35943859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
35954693Stm144005 			    != NXGE_OK)
35963859Sml29623 				goto fail;
35973859Sml29623 		} else {
35984693Stm144005 			clock_t rv;
35994693Stm144005 
36004693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
36014693Stm144005 
36024693Stm144005 			/* If <timerid> == 0, the link monitor has */
36034693Stm144005 			/* never been started, or just now stopped. */
36044693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
36054693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
36064693Stm144005 				return (NXGE_OK);
36074693Stm144005 			}
36084693Stm144005 
36094693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
36104693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
36114693Stm144005 			    &nxgep->poll_lock,
36124693Stm144005 			    ddi_get_lbolt() +
36134693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
36144693Stm144005 			    LINK_MONITOR_PERIOD));
36154693Stm144005 			if (rv == -1) {
36164693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36174693Stm144005 				    "==> stopping port %d: "
36184693Stm144005 				    "cv_timedwait(%d) timed out",
36194693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
36204693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
36213859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
36223859Sml29623 			}
36234693Stm144005 
36244693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
36253859Sml29623 		}
36263859Sml29623 	}
36273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36284693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
36294693Stm144005 	    nxgep->mac.portnum, enable));
36303859Sml29623 	return (NXGE_OK);
36313859Sml29623 fail:
36323859Sml29623 	return (status);
36333859Sml29623 }
36343859Sml29623 
36353859Sml29623 /* Set promiscous mode */
36363859Sml29623 
36373859Sml29623 nxge_status_t
36383859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
36393859Sml29623 {
36403859Sml29623 	nxge_status_t status = NXGE_OK;
36413859Sml29623 
36424732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
36433859Sml29623 
36443859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
36453859Sml29623 
36463859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
36473859Sml29623 
36483859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
36493859Sml29623 		goto fail;
36503859Sml29623 	}
36513859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
36523859Sml29623 		goto fail;
36533859Sml29623 	}
36543859Sml29623 
36553859Sml29623 	RW_EXIT(&nxgep->filter_lock);
36563859Sml29623 
36573859Sml29623 	if (on)
36583859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
36593859Sml29623 	else
36603859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
36613859Sml29623 
36623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
36633859Sml29623 
36643859Sml29623 	return (NXGE_OK);
36653859Sml29623 fail:
36663859Sml29623 	RW_EXIT(&nxgep->filter_lock);
36673859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
36684732Sdavemq 	    "Unable to set promisc (%d)", on));
36693859Sml29623 
36703859Sml29623 	return (status);
36713859Sml29623 }
36723859Sml29623 
36733859Sml29623 /*ARGSUSED*/
36743859Sml29623 uint_t
36753859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
36763859Sml29623 {
36773859Sml29623 #ifdef	NXGE_DEBUG
36783859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
36793859Sml29623 #endif
36803859Sml29623 #if NXGE_MIF
36813859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
36823859Sml29623 	uint32_t		status;
36833859Sml29623 	npi_handle_t		handle;
36843859Sml29623 	uint8_t			portn;
36853859Sml29623 	p_nxge_stats_t		statsp;
36863859Sml29623 #endif
36873859Sml29623 
36883859Sml29623 #ifdef	NXGE_MIF
36893859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
36903859Sml29623 		nxgep = ldvp->nxgep;
36913859Sml29623 	}
36923859Sml29623 	nxgep = ldvp->nxgep;
36933859Sml29623 #endif
36943859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
36953859Sml29623 
36963859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
36973859Sml29623 	return (DDI_INTR_CLAIMED);
36983859Sml29623 
36993859Sml29623 mif_intr_fail:
37003859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
37013859Sml29623 	return (DDI_INTR_UNCLAIMED);
37023859Sml29623 }
37033859Sml29623 
37043859Sml29623 /*ARGSUSED*/
37053859Sml29623 uint_t
37063859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
37073859Sml29623 {
37083859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
37093859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
37103859Sml29623 	p_nxge_ldg_t		ldgp;
37113859Sml29623 	uint32_t		status;
37123859Sml29623 	npi_handle_t		handle;
37133859Sml29623 	uint8_t			portn;
37143859Sml29623 	p_nxge_stats_t		statsp;
37153859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
37163859Sml29623 
37173859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
37183859Sml29623 		nxgep = ldvp->nxgep;
37193859Sml29623 	}
37203859Sml29623 
37213859Sml29623 	ldgp = ldvp->ldgp;
37223859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
37234732Sdavemq 	    "group %d", ldgp->ldg));
37243859Sml29623 
37253859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
37263859Sml29623 	/*
37273859Sml29623 	 * This interrupt handler is for a specific
37283859Sml29623 	 * mac port.
37293859Sml29623 	 */
37303859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
37313859Sml29623 	portn = nxgep->mac.portnum;
37323859Sml29623 
37333859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
37344732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
37353859Sml29623 
37363859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
37373859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
37383859Sml29623 					(xmac_tx_iconfig_t *)&status);
37393859Sml29623 		if (rs != NPI_SUCCESS)
37403859Sml29623 			goto npi_fail;
37413859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
37423859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
37433859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
37443859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37453859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
37463859Sml29623 			}
37473859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
37483859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
37493859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37503859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
37513859Sml29623 			}
37523859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
37533859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
37543859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37553859Sml29623 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
37563859Sml29623 			}
37573859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
37583859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
37593859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37603859Sml29623 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
37613859Sml29623 			}
37623859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
37633859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
37643859Sml29623 							XTXMAC_BYTE_CNT_MASK;
37653859Sml29623 			}
37663859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
37673859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
37683859Sml29623 							XTXMAC_FRM_CNT_MASK;
37693859Sml29623 			}
37703859Sml29623 		}
37713859Sml29623 
37723859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
37733859Sml29623 					(xmac_rx_iconfig_t *)&status);
37743859Sml29623 		if (rs != NPI_SUCCESS)
37753859Sml29623 			goto npi_fail;
37763859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
37773859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
37783859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
37793859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
37803859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
37813859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37823859Sml29623 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
37833859Sml29623 			}
37843859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
37853859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
37863859Sml29623 							XRXMAC_CRC_ER_CNT_MASK;
37873859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37883859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
37893859Sml29623 			}
37903859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
37913859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
37923859Sml29623 							MAC_LEN_ER_CNT_MASK;
37933859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
37943859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
37953859Sml29623 			}
37963859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
37973859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
37983859Sml29623 							XRXMAC_CD_VIO_CNT_MASK;
37993859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38003859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
38013859Sml29623 			}
38023859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
38033859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
38043859Sml29623 							XRXMAC_BT_CNT_MASK;
38053859Sml29623 			}
38063859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
38073859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
38083859Sml29623 							XRXMAC_HIST_CNT1_MASK;
38093859Sml29623 			}
38103859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
38113859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
38123859Sml29623 							XRXMAC_HIST_CNT2_MASK;
38133859Sml29623 			}
38143859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
38153859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
38163859Sml29623 							XRXMAC_HIST_CNT3_MASK;
38173859Sml29623 			}
38183859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
38193859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
38203859Sml29623 							XRXMAC_HIST_CNT4_MASK;
38213859Sml29623 			}
38223859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
38233859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
38243859Sml29623 							XRXMAC_HIST_CNT5_MASK;
38253859Sml29623 			}
38263859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
38273859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
38283859Sml29623 							XRXMAC_HIST_CNT6_MASK;
38293859Sml29623 			}
38303859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
38313859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
38323859Sml29623 							XRXMAC_BC_FRM_CNT_MASK;
38333859Sml29623 			}
38343859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
38353859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
38363859Sml29623 							XRXMAC_MC_FRM_CNT_MASK;
38373859Sml29623 			}
38383859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
38393859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
38403859Sml29623 							XRXMAC_FRAG_CNT_MASK;
38413859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38423859Sml29623 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
38433859Sml29623 			}
38443859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
38453859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
38463859Sml29623 							XRXMAC_AL_ER_CNT_MASK;
38473859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38483859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
38493859Sml29623 			}
38503859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
38513859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
38523859Sml29623 							XMAC_LINK_FLT_CNT_MASK;
38533859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38543859Sml29623 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
38553859Sml29623 			}
38563859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
38573859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
38583859Sml29623 			}
38593859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
38603859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
38613859Sml29623 			}
38623859Sml29623 		}
38633859Sml29623 
38643859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
38653859Sml29623 						(xmac_ctl_iconfig_t *)&status);
38663859Sml29623 		if (rs != NPI_SUCCESS)
38673859Sml29623 			goto npi_fail;
38683859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
38693859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
38703859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
38713859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
38723859Sml29623 				statsp->xmac_stats.tx_pause_state++;
38733859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
38743859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
38753859Sml29623 		}
38763859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
38773859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
38783859Sml29623 						(bmac_tx_iconfig_t *)&status);
38793859Sml29623 		if (rs != NPI_SUCCESS)
38803859Sml29623 			goto npi_fail;
38813859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
38823859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
38833859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
38843859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38853859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
38863859Sml29623 			}
38873859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
38883859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
38893859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
38903859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
38913859Sml29623 			}
38923859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
38933859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
38943859Sml29623 							BTXMAC_BYTE_CNT_MASK;
38953859Sml29623 			}
38963859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
38973859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
38983859Sml29623 							BTXMAC_FRM_CNT_MASK;
38993859Sml29623 			}
39003859Sml29623 		}
39013859Sml29623 
39023859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
39033859Sml29623 						(bmac_rx_iconfig_t *)&status);
39043859Sml29623 		if (rs != NPI_SUCCESS)
39053859Sml29623 			goto npi_fail;
39063859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
39073859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
39083859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
39093859Sml29623 			}
39103859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
39113859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
39123859Sml29623 							RXMAC_FRM_CNT_MASK;
39133859Sml29623 			}
39143859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
39153859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
39163859Sml29623 							BMAC_CRC_ER_CNT_MASK;
39173859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
39183859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
39193859Sml29623 			}
39203859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
39213859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
39223859Sml29623 							MAC_LEN_ER_CNT_MASK;
39233859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
39243859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
39253859Sml29623 			}
39263859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
39273859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
39283859Sml29623 							BMAC_CD_VIO_CNT_MASK;
39293859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
39303859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
39313859Sml29623 			}
39323859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
39333859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
39343859Sml29623 							BRXMAC_BYTE_CNT_MASK;
39353859Sml29623 			}
39363859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
39373859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
39383859Sml29623 							BMAC_AL_ER_CNT_MASK;
39393859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
39403859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
39413859Sml29623 			}
39423859Sml29623 
39433859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
39443859Sml29623 						(bmac_ctl_iconfig_t *)&status);
39453859Sml29623 			if (rs != NPI_SUCCESS)
39463859Sml29623 				goto npi_fail;
39473859Sml29623 
39483859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
39493859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
39503859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
39513859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
39523859Sml29623 					statsp->bmac_stats.tx_pause_state++;
39533859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
39543859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
39553859Sml29623 			}
39563859Sml29623 		}
39573859Sml29623 
39583859Sml29623 	if (ldgp->nldvs == 1) {
39593859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
39603859Sml29623 			B_TRUE, ldgp->ldg_timer);
39613859Sml29623 	}
39623859Sml29623 
39633859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
39643859Sml29623 	return (DDI_INTR_CLAIMED);
39653859Sml29623 
39663859Sml29623 npi_fail:
39673859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
39683859Sml29623 	return (DDI_INTR_UNCLAIMED);
39693859Sml29623 }
39703859Sml29623 
39713859Sml29623 nxge_status_t
39723859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
39733859Sml29623 {
39743859Sml29623 	uint8_t		phy_port_addr;
39753859Sml29623 	nxge_status_t	status = NXGE_OK;
39763859Sml29623 	boolean_t	rx_sig_ok;
39773859Sml29623 	boolean_t	pcs_blk_lock;
39783859Sml29623 	boolean_t	link_align;
39793859Sml29623 	uint16_t	val1, val2, val3;
39803859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
39813859Sml29623 	uint16_t	val_debug;
39823859Sml29623 	uint16_t	val;
39833859Sml29623 #endif
39843859Sml29623 
39853859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
39863859Sml29623 
39873859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
39883859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
39893859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
39903859Sml29623 	if ((val_debug & ~0x200) != 0) {
39913859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
39923859Sml29623 				nxgep->mac.portnum, val_debug);
39933859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
39943859Sml29623 				&val_debug);
39953859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
39963859Sml29623 				nxgep->mac.portnum, val_debug);
39973859Sml29623 	}
39983859Sml29623 
39993859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
40003859Sml29623 					XPCS_REG_DESCWERR_COUNTER, &val);
40013859Sml29623 	if (val != 0)
40023859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
40033859Sml29623 
40043859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
40053859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
40063859Sml29623 	if (val != 0)
40073859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
40083859Sml29623 
40093859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
40103859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
40113859Sml29623 	if (val != 0)
40123859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
40133859Sml29623 #endif
40143859Sml29623 
40153859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
40163859Sml29623 
40173859Sml29623 	/* Check Device 1 Register 0xA bit0 */
40183859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
40193859Sml29623 			BCM8704_PMA_PMD_DEV_ADDR,
40203859Sml29623 			BCM8704_PMD_RECEIVE_SIG_DETECT,
40213859Sml29623 			&val1);
40223859Sml29623 	if (status != NXGE_OK)
40233859Sml29623 		goto fail;
40243859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
40253859Sml29623 
40263859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
40273859Sml29623 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
40283859Sml29623 			BCM8704_PCS_DEV_ADDR,
40293859Sml29623 			BCM8704_10GBASE_R_PCS_STATUS_REG,
40303859Sml29623 			&val2)) != NPI_SUCCESS)
40313859Sml29623 		goto fail;
40323859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
40333859Sml29623 
40343859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
40353859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
40363859Sml29623 			BCM8704_PHYXS_ADDR,
40373859Sml29623 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
40383859Sml29623 			&val3);
40393859Sml29623 	if (status != NXGE_OK)
40403859Sml29623 		goto fail;
40413859Sml29623 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
40423859Sml29623 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
40433859Sml29623 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
40443859Sml29623 
40453859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
40463859Sml29623 	/* Temp workaround for link down issue */
40473859Sml29623 	if (pcs_blk_lock == B_FALSE) {
40483859Sml29623 		if (val2 != 0x4) {
40493859Sml29623 			pcs_blk_lock = B_TRUE;
40503859Sml29623 			cmn_err(CE_NOTE,
40513859Sml29623 				"!LINK DEBUG: port%d PHY Dev3 "
40523859Sml29623 				"Reg 0x20 = 0x%x\n",
40533859Sml29623 				nxgep->mac.portnum, val2);
40543859Sml29623 		}
40553859Sml29623 	}
40563859Sml29623 
40573859Sml29623 	if (link_align == B_FALSE) {
40583859Sml29623 		if (val3 != 0x140f) {
40593859Sml29623 			link_align = B_TRUE;
40603859Sml29623 			cmn_err(CE_NOTE,
40613859Sml29623 				"!LINK DEBUG: port%d PHY Dev4 "
40623859Sml29623 				"Reg 0x18 = 0x%x\n",
40633859Sml29623 				nxgep->mac.portnum, val3);
40643859Sml29623 		}
40653859Sml29623 	}
40663859Sml29623 
40673859Sml29623 	if (rx_sig_ok == B_FALSE) {
40683859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
40693859Sml29623 			rx_sig_ok = B_TRUE;
40703859Sml29623 			cmn_err(CE_NOTE,
40713859Sml29623 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
40723859Sml29623 				nxgep->mac.portnum);
40733859Sml29623 		}
40743859Sml29623 	}
40753859Sml29623 #endif
40763859Sml29623 
40773859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
40783859Sml29623 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
40793859Sml29623 
40803859Sml29623 	return (NXGE_OK);
40813859Sml29623 fail:
40823859Sml29623 	return (status);
40833859Sml29623 }
40843859Sml29623 
40853859Sml29623 nxge_status_t
40863859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
40873859Sml29623 {
40883859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
40894732Sdavemq 	    != NPI_SUCCESS)
40903859Sml29623 		return (NXGE_ERROR);
40913859Sml29623 	else
40923859Sml29623 		return (NXGE_OK);
40933859Sml29623 }
40943859Sml29623 
40953859Sml29623 nxge_status_t
40963859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
40973859Sml29623 {
40983859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
40994732Sdavemq 	    != NPI_SUCCESS)
41003859Sml29623 		return (NXGE_ERROR);
41013859Sml29623 	else
41023859Sml29623 		return (NXGE_OK);
41033859Sml29623 }
41044185Sspeer 
41054732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
41064732Sdavemq 
41074732Sdavemq static boolean_t
41084732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
41094732Sdavemq {
41104732Sdavemq 	int		i;
41114732Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
41124732Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
41134732Sdavemq 	boolean_t	found = B_FALSE;
41144732Sdavemq 
41154732Sdavemq 	switch (type) {
41164732Sdavemq 	case CLAUSE_45_TYPE:
41174732Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
41184782Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
41194782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
41204732Sdavemq 				found = B_TRUE;
41214732Sdavemq 				break;
41224732Sdavemq 			}
41234732Sdavemq 		}
41244732Sdavemq 		break;
41254732Sdavemq 	case CLAUSE_22_TYPE:
41264732Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
41274782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
41284782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
41294732Sdavemq 				found = B_TRUE;
41304732Sdavemq 				break;
41314732Sdavemq 			}
41324732Sdavemq 		}
41334732Sdavemq 		break;
41344732Sdavemq 	default:
41354732Sdavemq 		break;
41364732Sdavemq 	}
41374732Sdavemq 
41384732Sdavemq 	return (found);
41394732Sdavemq }
41404732Sdavemq 
41414977Sraghus static uint32_t
41424977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
41434977Sraghus {
41444977Sraghus 	uint16_t	val1 = 0;
41454977Sraghus 	uint16_t	val2 = 0;
41464977Sraghus 	uint32_t	pma_pmd_dev_id = 0;
41474977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
41484977Sraghus 
41494977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
41504977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
41514977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
41524977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
41534977Sraghus 
41544977Sraghus 	pma_pmd_dev_id = val1;
41554977Sraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
41564977Sraghus 	pma_pmd_dev_id |= val2;
41574977Sraghus 
41584977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
41594977Sraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
41604977Sraghus 
41614977Sraghus 	return (pma_pmd_dev_id);
41624977Sraghus }
41634977Sraghus 
41644977Sraghus static uint32_t
41654977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
41664977Sraghus {
41674977Sraghus 	uint16_t	val1 = 0;
41684977Sraghus 	uint16_t	val2 = 0;
41694977Sraghus 	uint32_t	pcs_dev_id = 0;
41704977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
41714977Sraghus 
41724977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
41734977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
41744977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
41754977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
41764977Sraghus 
41774977Sraghus 	pcs_dev_id = val1;
41784977Sraghus 	pcs_dev_id = (pcs_dev_id << 16);
41794977Sraghus 	pcs_dev_id |= val2;
41804977Sraghus 
41814977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
41824977Sraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
41834977Sraghus 
41844977Sraghus 	return (pcs_dev_id);
41854977Sraghus }
41864977Sraghus 
41874977Sraghus static uint32_t
41884977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
41894977Sraghus {
41904977Sraghus 	uint16_t	val1 = 0;
41914977Sraghus 	uint16_t	val2 = 0;
41924977Sraghus 	uint32_t	phy_id = 0;
41934977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
41944977Sraghus 	npi_status_t	npi_status = NPI_SUCCESS;
41954977Sraghus 
41964977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
41974977Sraghus 	    &val1);
41984977Sraghus 	if (npi_status != NPI_SUCCESS) {
41994977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
42004977Sraghus 		    "clause 22 read to reg 2 failed!!!"));
42014977Sraghus 		goto exit;
42024977Sraghus 	}
42034977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
42044977Sraghus 	    &val2);
42054977Sraghus 	if (npi_status != 0) {
42064977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
42074977Sraghus 		    "clause 22 read to reg 3 failed!!!"));
42084977Sraghus 		goto exit;
42094977Sraghus 	}
42104977Sraghus 	phy_id = val1;
42114977Sraghus 	phy_id = (phy_id << 16);
42124977Sraghus 	phy_id |= val2;
42134977Sraghus 
42144977Sraghus exit:
42154977Sraghus 
42164977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
42174977Sraghus 	    phy_port, phy_id));
42184977Sraghus 
42194977Sraghus 	return (phy_id);
42204977Sraghus }
42214977Sraghus 
42224732Sdavemq /*
42234732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
42244732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
42254732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
42264732Sdavemq  * and the Neptune type.
42274732Sdavemq  */
42284732Sdavemq 
42294732Sdavemq nxge_status_t
42304732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
42314732Sdavemq {
42324732Sdavemq 	int		i, j, k, l;
42334732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
42344732Sdavemq 	uint32_t	pcs_dev_id = 0;
42354732Sdavemq 	uint32_t	phy_id = 0;
42364782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
42374782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
42384782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
42394732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
42404732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
42414732Sdavemq 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
42424732Sdavemq 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
42434732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
42444732Sdavemq 	nxge_status_t	status = NXGE_OK;
42454732Sdavemq 	int		prt_id = -1;
42464732Sdavemq 
42474732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
42484732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42494732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
42504732Sdavemq 	    nxgep->niu_type));
42514732Sdavemq 
42524732Sdavemq 	j = k = l = 0;
42534732Sdavemq 	total_port_fd = total_phy_fd = 0;
42544732Sdavemq 	/*
42554732Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
42564732Sdavemq 	 * for on chip serdes usages.
42574732Sdavemq 	 */
42584732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
42594977Sraghus 
42604977Sraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
42614732Sdavemq 
42624732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
42634732Sdavemq 			pma_pmd_dev_fd[i] = 1;
42644732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
42654732Sdavemq 			    "PMA/PMD dev found", i));
42664782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
42674782Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
42684782Ssbehera 				    BCM_PHY_ID_MASK;
42694732Sdavemq 				j++;
42704732Sdavemq 			}
42714732Sdavemq 		} else {
42724732Sdavemq 			pma_pmd_dev_fd[i] = 0;
42734732Sdavemq 		}
42744732Sdavemq 
42754977Sraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
42764732Sdavemq 
42774732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
42784732Sdavemq 			pcs_dev_fd[i] = 1;
42794732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
42804732Sdavemq 			    "dev found", i));
42814782Ssbehera 			if (k < NXGE_PORTS_NEPTUNE) {
42824782Ssbehera 				port_pcs_dev_id[k] = pcs_dev_id &
42834782Ssbehera 				    BCM_PHY_ID_MASK;
42844732Sdavemq 				k++;
42854732Sdavemq 			}
42864732Sdavemq 		} else {
42874732Sdavemq 			pcs_dev_fd[i] = 0;
42884732Sdavemq 		}
42894732Sdavemq 
42904732Sdavemq 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
42914732Sdavemq 			port_fd[i] = 1;
42924732Sdavemq 		else
42934732Sdavemq 			port_fd[i] = 0;
42944732Sdavemq 		total_port_fd += port_fd[i];
42954732Sdavemq 
42964977Sraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
42974732Sdavemq 
42984732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
42994732Sdavemq 			phy_fd[i] = 1;
43004732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
43014732Sdavemq 			    "found", i));
43024782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
43034782Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
43044732Sdavemq 				l++;
43054732Sdavemq 			}
43064732Sdavemq 		} else {
43074732Sdavemq 			phy_fd[i] = 0;
43084732Sdavemq 		}
43094732Sdavemq 		total_phy_fd += phy_fd[i];
43104732Sdavemq 	}
43114732Sdavemq 
43124732Sdavemq 	switch (total_port_fd) {
43134732Sdavemq 	case 2:
43144732Sdavemq 		switch (total_phy_fd) {
43154732Sdavemq 		case 2:
43164977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43174977Sraghus 			    "Unsupported neptune type 1"));
43184977Sraghus 			goto error_exit;
43194732Sdavemq 		case 1:
43204732Sdavemq 			/* TODO - 2 10G, 1 1G */
43214732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43224732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
43234732Sdavemq 			goto error_exit;
43244732Sdavemq 		case 0:
43254732Sdavemq 			/* 2 10G */
43264782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
43274782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
43284782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
43294782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
43304977Sraghus 
43314977Sraghus 				/*
43324977Sraghus 				 * Check the first phy port address against
43334977Sraghus 				 * the known phy start addresses to determine
43344977Sraghus 				 * the platform type.
43354977Sraghus 				 */
43364977Sraghus 				for (i = NXGE_EXT_PHY_PORT_ST;
43374977Sraghus 				    i < NXGE_MAX_PHY_PORTS; i++) {
43384977Sraghus 					if (port_fd[i] == 1)
43394977Sraghus 						break;
43404977Sraghus 				}
43414977Sraghus 				if (i == BCM8704_NEPTUNE_PORT_ADDR_BASE) {
43424977Sraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
43434977Sraghus 					hw_p->platform_type =
43444977Sraghus 					    P_NEPTUNE_ATLAS_2PORT;
43454977Sraghus 				} else {
43464977Sraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43474977Sraghus 					    "Unsupported neptune type 2 - 1"));
43484977Sraghus 					goto error_exit;
43494977Sraghus 				}
43504732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF;
43514732Sdavemq 			} else {
43524732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43534732Sdavemq 				    "Unsupported neptune type 2"));
43544732Sdavemq 				goto error_exit;
43554732Sdavemq 			}
43564732Sdavemq 			break;
43574732Sdavemq 		case 4:
43584732Sdavemq 			/* Maramba with 2 XAUI */
43594782Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
43604782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
43614782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
43624782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
43634782Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
43644782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
43654782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
43664782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
43674732Sdavemq 
43684732Sdavemq 				/*
43694732Sdavemq 				 * Check the first phy port address against
43704732Sdavemq 				 * the known phy start addresses to determine
43714732Sdavemq 				 * the platform type.
43724732Sdavemq 				 */
43734732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
43744732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
43754732Sdavemq 					if (phy_fd[i] == 1)
43764732Sdavemq 						break;
43774732Sdavemq 				}
43784732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
43794732Sdavemq 					hw_p->platform_type =
43804732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
43814732Sdavemq 				} else if (i ==
43824732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
43834732Sdavemq 					hw_p->platform_type =
43844732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
43854732Sdavemq 				} else {
43864732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43874732Sdavemq 					    "Unknown port %d...Cannot "
43884732Sdavemq 					    "determine platform type", i));
43894977Sraghus 					goto error_exit;
43904732Sdavemq 				}
43914977Sraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
43924977Sraghus 
43934732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43944732Sdavemq 				    "Maramba with 2 XAUI"));
43954732Sdavemq 			} else {
43964732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43974732Sdavemq 				    "Unsupported neptune type 3"));
43984732Sdavemq 				goto error_exit;
43994732Sdavemq 			}
44004732Sdavemq 			break;
44014732Sdavemq 		default:
44024732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44034732Sdavemq 			    "Unsupported neptune type 5"));
44044732Sdavemq 			goto error_exit;
44054732Sdavemq 		}
44064782Ssbehera 		break;
44074732Sdavemq 	case 1:
44084732Sdavemq 		switch (total_phy_fd) {
44094732Sdavemq 		case 3:
44104977Sraghus 			/*
44114977Sraghus 			 * TODO 3 1G, 1 10G mode.
44124977Sraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
44134977Sraghus 			 * 1_10G_3_1G
44144977Sraghus 			 */
44154977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44164977Sraghus 			    "Unsupported neptune type 7"));
44174977Sraghus 			goto error_exit;
44184732Sdavemq 		case 2:
44194732Sdavemq 			/*
44204732Sdavemq 			 * TODO 2 1G, 1 10G mode.
44214732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
44224732Sdavemq 			 * 1_10G_2_1G
44234732Sdavemq 			 */
44244732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44254732Sdavemq 			    "Unsupported neptune type 8"));
44264732Sdavemq 			goto error_exit;
44274732Sdavemq 		case 1:
44284732Sdavemq 			/*
44294732Sdavemq 			 * TODO 1 1G, 1 10G mode.
44304732Sdavemq 			 * Differentiate between 1_1G_1_10G and
44314732Sdavemq 			 * 1_10G_1_1G
44324732Sdavemq 			 */
44334732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44344732Sdavemq 			    "Unsupported neptune type 9"));
44354732Sdavemq 			goto error_exit;
44364732Sdavemq 		case 0:
44374732Sdavemq 			/* TODO 1 10G mode */
44384732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44394732Sdavemq 			    "Unsupported neptune type 10"));
44404732Sdavemq 			goto error_exit;
44414732Sdavemq 		case 4:
44424732Sdavemq 			/* Maramba with 1 XAUI */
44434782Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
44444782Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
44454732Sdavemq 
44464732Sdavemq 				/*
44474732Sdavemq 				 * Check the first phy port address against
44484732Sdavemq 				 * the known phy start addresses to determine
44494732Sdavemq 				 * the platform type.
44504732Sdavemq 				 */
44514732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
44524732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
44534732Sdavemq 					if (phy_fd[i] == 1)
44544732Sdavemq 						break;
44554732Sdavemq 				}
44564732Sdavemq 
44574732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
44584732Sdavemq 					hw_p->platform_type =
44594732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
44604732Sdavemq 				} else if (i ==
44614732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
44624732Sdavemq 					hw_p->platform_type =
44634732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
44644732Sdavemq 				} else {
44654732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
44664732Sdavemq 					    "Unknown port %d...Cannot "
44674732Sdavemq 					    "determine platform type", i));
44684977Sraghus 					goto error_exit;
44694977Sraghus 				}
44704977Sraghus 
44714977Sraghus 				/* The 10G port is BCM8704 */
44724977Sraghus 				for (i = NXGE_EXT_PHY_PORT_ST;
44734977Sraghus 				    i < NXGE_MAX_PHY_PORTS; i++) {
44744977Sraghus 					if (port_fd[i] == 1) {
44754977Sraghus 						prt_id = i;
44764977Sraghus 						break;
44774977Sraghus 					}
44784977Sraghus 				}
44794977Sraghus 
44804977Sraghus 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
44814977Sraghus 				if (prt_id == 0) {
44824977Sraghus 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
44834977Sraghus 				} else if (prt_id == 1) {
44844977Sraghus 					hw_p->niu_type =
44854977Sraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
44864977Sraghus 				} else {
44874977Sraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44884977Sraghus 					    "Unsupported neptune type 11"));
44894977Sraghus 					goto error_exit;
44904732Sdavemq 				}
44914732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44924732Sdavemq 				    "Maramba with 1 XAUI"));
44934732Sdavemq 			} else {
44944732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44954732Sdavemq 				    "Unsupported neptune type 12"));
44964732Sdavemq 				goto error_exit;
44974732Sdavemq 			}
44984732Sdavemq 			break;
44994732Sdavemq 		default:
45004732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45014732Sdavemq 			    "Unsupported neptune type 13"));
45024732Sdavemq 			goto error_exit;
45034732Sdavemq 		}
45044732Sdavemq 		break;
45054732Sdavemq 	case 0:
45064732Sdavemq 		switch (total_phy_fd) {
45074732Sdavemq 		case 4:
45084782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
45094782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
45104782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
45114782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
45124732Sdavemq 
45134732Sdavemq 				/*
45144732Sdavemq 				 * Check the first phy port address against
45154732Sdavemq 				 * the known phy start addresses to determine
45164732Sdavemq 				 * the platform type.
45174732Sdavemq 				 */
45184732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
45194732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
45204732Sdavemq 					if (phy_fd[i] == 1)
45214732Sdavemq 						break;
45224732Sdavemq 				}
45234732Sdavemq 
45244732Sdavemq 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
45254732Sdavemq 					hw_p->platform_type =
45264732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
45274977Sraghus 				} else if (i ==
45284977Sraghus 				    BCM5464_NEPTUNE_PORT_ADDR_BASE) {
45294977Sraghus 					hw_p->platform_type =
45304977Sraghus 					    P_NEPTUNE_ATLAS_4PORT;
45314977Sraghus 				} else {
45324977Sraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
45334977Sraghus 					    "Unknown port %d...Cannot "
45344977Sraghus 					    "determine platform type", i));
45354977Sraghus 					goto error_exit;
45364732Sdavemq 				}
45374977Sraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
45384732Sdavemq 			} else {
45394732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45404732Sdavemq 				    "Unsupported neptune type 14"));
45414732Sdavemq 				goto error_exit;
45424732Sdavemq 			}
45434732Sdavemq 			break;
45444732Sdavemq 		case 3:
45454732Sdavemq 			/* TODO 3 1G mode */
45464732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45474732Sdavemq 			    "Unsupported neptune type 15"));
45484732Sdavemq 			goto error_exit;
45494732Sdavemq 		case 2:
45504732Sdavemq 			/* TODO 2 1G mode */
45514732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45524732Sdavemq 			    "Unsupported neptune type 16"));
45534732Sdavemq 			goto error_exit;
45544732Sdavemq 		case 1:
45554732Sdavemq 			/* TODO 1 1G mode */
45564732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45574732Sdavemq 			    "Unsupported neptune type 17"));
45584732Sdavemq 			goto error_exit;
45594732Sdavemq 		default:
45604732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45614732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
45624732Sdavemq 			    total_phy_fd));
45634732Sdavemq 			goto error_exit;
45644732Sdavemq 		}
45654732Sdavemq 		break;
45664732Sdavemq 	default:
45674732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45684732Sdavemq 		    "Unsupported neptune type 19"));
45694732Sdavemq 		goto error_exit;
45704732Sdavemq 	}
45714732Sdavemq 
45724732Sdavemq scan_exit:
45734732Sdavemq 
45744732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
45754732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
45764732Sdavemq 	return (status);
45774732Sdavemq 
45784732Sdavemq error_exit:
45794732Sdavemq 	return (NXGE_ERROR);
45804732Sdavemq }
45814732Sdavemq 
45824185Sspeer boolean_t
45834185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
45844185Sspeer {
45854185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
45864185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
45874185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
45884185Sspeer 		return (B_FALSE);
45894185Sspeer 	else
45904185Sspeer 		return (B_TRUE);
45914185Sspeer }
45924732Sdavemq 
45934732Sdavemq static void
45944732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
45954732Sdavemq 
45964732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
45974732Sdavemq 	uint8_t xcvr_portn;
45984732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
45994732Sdavemq 
46004732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
46014732Sdavemq 
46024732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
46034732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
46044732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
46054732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
46064732Sdavemq 	}
46074732Sdavemq 	/*
46084732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
46094732Sdavemq 	 * swapped with ethernet port number. This is
46104732Sdavemq 	 * designed for better signal integrity in routing.
46114732Sdavemq 	 */
46124732Sdavemq 	switch (portn) {
46134732Sdavemq 	case 0:
46144732Sdavemq 		xcvr_portn += 3;
46154732Sdavemq 		break;
46164732Sdavemq 	case 1:
46174732Sdavemq 		xcvr_portn += 2;
46184732Sdavemq 		break;
46194732Sdavemq 	case 2:
46204732Sdavemq 		xcvr_portn += 1;
46214732Sdavemq 		break;
46224732Sdavemq 	case 3:
46234732Sdavemq 	default:
46244732Sdavemq 		break;
46254732Sdavemq 	}
46264732Sdavemq 
46274732Sdavemq 	MUTEX_ENTER(&nxge_mii_lock);
46284732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
46294732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
46304732Sdavemq 	if (rs != NPI_SUCCESS) {
46314732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
46324732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
46334732Sdavemq 		    "returned error 0x[%x]", rs));
46344732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
46354732Sdavemq 		return;
46364732Sdavemq 	}
46374732Sdavemq 
46384732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
46394732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
46404732Sdavemq 	if (rs != NPI_SUCCESS) {
46414732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
46424732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
46434732Sdavemq 		    "returned error 0x[%x]", rs));
46444732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
46454732Sdavemq 		return;
46464732Sdavemq 	}
46474732Sdavemq 
46484732Sdavemq 	MUTEX_EXIT(&nxge_mii_lock);
46494732Sdavemq }
4650