xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 4185:f1a68afd98ff)
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 
313859Sml29623 extern uint32_t nxge_no_link_notify;
32*4185Sspeer extern boolean_t nxge_no_msg;
333859Sml29623 extern uint32_t nxge_lb_dbg;
343859Sml29623 extern nxge_os_mutex_t	nxge_mdio_lock;
353859Sml29623 extern nxge_os_mutex_t	nxge_mii_lock;
363859Sml29623 extern boolean_t nxge_jumbo_enable;
373859Sml29623 
383859Sml29623 /*
393859Sml29623  * Ethernet broadcast address definition.
403859Sml29623  */
413859Sml29623 static ether_addr_st etherbroadcastaddr =
423859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
43*4185Sspeer static ether_addr_st etherzeroaddr =
44*4185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
453859Sml29623 
463859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
473859Sml29623 
483859Sml29623 /* Initialize the entire MAC and physical layer */
493859Sml29623 
503859Sml29623 nxge_status_t
513859Sml29623 nxge_mac_init(p_nxge_t nxgep)
523859Sml29623 {
533859Sml29623 	uint8_t			portn;
543859Sml29623 	nxge_status_t		status = NXGE_OK;
553859Sml29623 
563859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
573859Sml29623 
583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
593859Sml29623 
603859Sml29623 	nxgep->mac.portnum = portn;
613859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
623859Sml29623 
633859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
643859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
653859Sml29623 
663859Sml29623 	/* Initialize XIF to configure a network mode */
673859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
683859Sml29623 		goto fail;
693859Sml29623 	}
703859Sml29623 
713859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
723859Sml29623 		goto fail;
733859Sml29623 	}
743859Sml29623 
753859Sml29623 	/* Initialize TX and RX MACs */
763859Sml29623 	/*
773859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
783859Sml29623 	 */
793859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
803859Sml29623 		goto fail;
813859Sml29623 
823859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
833859Sml29623 		goto fail;
843859Sml29623 
853859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
863859Sml29623 		goto fail;
873859Sml29623 
883859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
893859Sml29623 		goto fail;
903859Sml29623 
913859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
923859Sml29623 		goto fail;
933859Sml29623 
943859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
953859Sml29623 		goto fail;
963859Sml29623 
973859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
983859Sml29623 
993859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
1003859Sml29623 
1013859Sml29623 	return (NXGE_OK);
1023859Sml29623 fail:
1033859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1043859Sml29623 			"nxge_mac_init: failed to initialize MAC port<%d>",
1053859Sml29623 			portn));
1063859Sml29623 	return (status);
1073859Sml29623 }
1083859Sml29623 
1093859Sml29623 /* Initialize the Ethernet Link */
1103859Sml29623 
1113859Sml29623 nxge_status_t
1123859Sml29623 nxge_link_init(p_nxge_t nxgep)
1133859Sml29623 {
1143859Sml29623 	nxge_status_t		status = NXGE_OK;
1153859Sml29623 #ifdef	NXGE_DEBUG
1163859Sml29623 	uint8_t			portn;
1173859Sml29623 
1183859Sml29623 	portn = nxgep->mac.portnum;
1193859Sml29623 
1203859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
1213859Sml29623 #endif
1223859Sml29623 
1233859Sml29623 	if (nxgep->niu_type == N2_NIU) {
1243859Sml29623 		/* Workaround to get link up in both NIU ports */
1253859Sml29623 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
1263859Sml29623 			goto fail;
1273859Sml29623 	}
1283859Sml29623 	NXGE_DELAY(200000);
1293859Sml29623 	/* Initialize internal serdes */
1303859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
1313859Sml29623 		goto fail;
1323859Sml29623 	NXGE_DELAY(200000);
1333859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
1343859Sml29623 		goto fail;
1353859Sml29623 
1363859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
1373859Sml29623 
1383859Sml29623 	return (NXGE_OK);
1393859Sml29623 
1403859Sml29623 fail:
1413859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1423859Sml29623 		"nxge_link_init: ",
1433859Sml29623 		"failed to initialize Ethernet link on port<%d>",
1443859Sml29623 		portn));
1453859Sml29623 
1463859Sml29623 	return (status);
1473859Sml29623 }
1483859Sml29623 
1493859Sml29623 
1503859Sml29623 /* Initialize the XIF sub-block within the MAC */
1513859Sml29623 
1523859Sml29623 nxge_status_t
1533859Sml29623 nxge_xif_init(p_nxge_t nxgep)
1543859Sml29623 {
1553859Sml29623 	uint32_t		xif_cfg = 0;
1563859Sml29623 	npi_attr_t		ap;
1573859Sml29623 	uint8_t			portn;
1583859Sml29623 	nxge_port_t		portt;
1593859Sml29623 	nxge_port_mode_t	portmode;
1603859Sml29623 	p_nxge_stats_t		statsp;
1613859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
1623859Sml29623 	npi_handle_t		handle;
1633859Sml29623 
1643859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1653859Sml29623 
1663859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
1673859Sml29623 
1683859Sml29623 	handle = nxgep->npi_handle;
1693859Sml29623 	portmode = nxgep->mac.portmode;
1703859Sml29623 	portt = nxgep->mac.porttype;
1713859Sml29623 	statsp = nxgep->statsp;
1723859Sml29623 
1733859Sml29623 	if (portt == PORT_TYPE_XMAC) {
1743859Sml29623 
1753859Sml29623 		/* Setup XIF Configuration for XMAC */
1763859Sml29623 
1773859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
1783859Sml29623 					(portmode == PORT_10G_COPPER))
1793859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
1803859Sml29623 
1813859Sml29623 		if (portmode == PORT_1G_COPPER) {
1823859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
1833859Sml29623 		}
1843859Sml29623 
1853859Sml29623 		/* Set MAC Internal Loopback if necessary */
1863859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
1873859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
1883859Sml29623 
1893859Sml29623 		if (statsp->mac_stats.link_speed == 100)
1903859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
1913859Sml29623 
1923859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
1933859Sml29623 
1943859Sml29623 		if (portmode == PORT_10G_FIBER) {
1953859Sml29623 			if (statsp->mac_stats.link_up) {
1963859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
1973859Sml29623 			} else {
1983859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
1993859Sml29623 			}
2003859Sml29623 		}
2013859Sml29623 
2023859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
2033859Sml29623 		if (rs != NPI_SUCCESS)
2043859Sml29623 			goto fail;
2053859Sml29623 
2063859Sml29623 		nxgep->mac.xif_config = xif_cfg;
2073859Sml29623 
2083859Sml29623 		/* Set Port Mode */
2093859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
2103859Sml29623 					(portmode == PORT_10G_COPPER)) {
2113859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
2123859Sml29623 						MAC_XGMII_MODE, rs);
2133859Sml29623 			if (rs != NPI_SUCCESS)
2143859Sml29623 				goto fail;
2153859Sml29623 			if (statsp->mac_stats.link_up) {
2163859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
2173859Sml29623 					goto fail;
2183859Sml29623 			} else {
2193859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
2203859Sml29623 					goto fail;
2213859Sml29623 			}
2223859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
2233859Sml29623 						(portmode == PORT_1G_COPPER)) {
2243859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
2253859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
2263859Sml29623 							MAC_GMII_MODE, rs);
2273859Sml29623 			} else {
2283859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
2293859Sml29623 							MAC_MII_MODE, rs);
2303859Sml29623 			}
2313859Sml29623 			if (rs != NPI_SUCCESS)
2323859Sml29623 				goto fail;
2333859Sml29623 		} else {
2343859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2353859Sml29623 					"nxge_xif_init: Unknown port mode (%d)"
2363859Sml29623 					" for port<%d>", portmode, portn));
2373859Sml29623 			goto fail;
2383859Sml29623 		}
2393859Sml29623 
2403859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
2413859Sml29623 
2423859Sml29623 		/* Setup XIF Configuration for BMAC */
2433859Sml29623 
2443859Sml29623 		if (portmode == PORT_1G_COPPER) {
2453859Sml29623 			if (statsp->mac_stats.link_speed == 100)
2463859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
2473859Sml29623 		}
2483859Sml29623 
2493859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
2503859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
2513859Sml29623 
2523859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
2533859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
2543859Sml29623 
2553859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
2563859Sml29623 
2573859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
2583859Sml29623 		if (rs != NPI_SUCCESS)
2593859Sml29623 			goto fail;
2603859Sml29623 		nxgep->mac.xif_config = xif_cfg;
2613859Sml29623 	}
2623859Sml29623 
2633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
2643859Sml29623 	return (NXGE_OK);
2653859Sml29623 fail:
2663859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2673859Sml29623 			"nxge_xif_init: Failed to initialize XIF port<%d>",
2683859Sml29623 			portn));
2693859Sml29623 	return (NXGE_ERROR | rs);
2703859Sml29623 }
2713859Sml29623 
2723859Sml29623 /* Initialize the PCS sub-block in the MAC */
2733859Sml29623 
2743859Sml29623 nxge_status_t
2753859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
2763859Sml29623 {
2773859Sml29623 	pcs_cfg_t		pcs_cfg;
2783859Sml29623 	uint32_t		val;
2793859Sml29623 	uint8_t			portn;
2803859Sml29623 	nxge_port_mode_t	portmode;
2813859Sml29623 	npi_handle_t		handle;
2823859Sml29623 	p_nxge_stats_t		statsp;
2833859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
2843859Sml29623 
2853859Sml29623 	handle = nxgep->npi_handle;
2863859Sml29623 	portmode = nxgep->mac.portmode;
2873859Sml29623 	portn = nxgep->mac.portnum;
2883859Sml29623 	statsp = nxgep->statsp;
2893859Sml29623 
2903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
2913859Sml29623 
2923859Sml29623 	if (portmode == PORT_1G_FIBER) {
2933859Sml29623 		/* Initialize port's PCS */
2943859Sml29623 		pcs_cfg.value = 0;
2953859Sml29623 		pcs_cfg.bits.w0.enable = 1;
2963859Sml29623 		pcs_cfg.bits.w0.mask = 1;
2973859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
2983859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
2993859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
3003859Sml29623 			goto fail;
3013859Sml29623 
3023859Sml29623 	} else if ((portmode == PORT_10G_FIBER) ||
3033859Sml29623 						(portmode == PORT_10G_COPPER)) {
3043859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
3053859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
3063859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
3073859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
3083859Sml29623 
3093859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
3103859Sml29623 			goto fail;
3113859Sml29623 
3123859Sml29623 		/* Set XPCS Internal Loopback if necessary */
3133859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
3143859Sml29623 						XPCS_REG_CONTROL1, &val))
3153859Sml29623 						!= NPI_SUCCESS)
3163859Sml29623 			goto fail;
3173859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
3183859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
3193859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
3203859Sml29623 		else
3213859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
3223859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
3233859Sml29623 						XPCS_REG_CONTROL1, val))
3243859Sml29623 						!= NPI_SUCCESS)
3253859Sml29623 			goto fail;
3263859Sml29623 
3273859Sml29623 		/* Clear descw errors */
3283859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
3293859Sml29623 						XPCS_REG_DESCWERR_COUNTER, 0))
3303859Sml29623 						!= NPI_SUCCESS)
3313859Sml29623 			goto fail;
3323859Sml29623 		/* Clear symbol errors */
3333859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
3343859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
3353859Sml29623 					!= NPI_SUCCESS)
3363859Sml29623 			goto fail;
3373859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
3383859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
3393859Sml29623 					!= NPI_SUCCESS)
3403859Sml29623 			goto fail;
3413859Sml29623 
3423859Sml29623 	} else if (portmode == PORT_1G_COPPER) {
3433859Sml29623 		if (portn < 4) {
3443859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
3453859Sml29623 					PCS_DATAPATH_MODE_MII);
3463859Sml29623 		}
3473859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
3483859Sml29623 			goto fail;
3493859Sml29623 
3503859Sml29623 	} else {
3513859Sml29623 		goto fail;
3523859Sml29623 	}
3533859Sml29623 pass:
3543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
3553859Sml29623 	return (NXGE_OK);
3563859Sml29623 fail:
3573859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3583859Sml29623 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
3593859Sml29623 			portn));
3603859Sml29623 	return (NXGE_ERROR | rs);
3613859Sml29623 }
3623859Sml29623 
3633859Sml29623 /* Initialize the Internal Serdes */
3643859Sml29623 
3653859Sml29623 nxge_status_t
3663859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
3673859Sml29623 {
3683859Sml29623 	p_nxge_stats_t		statsp;
3693859Sml29623 #ifdef	NXGE_DEBUG
3703859Sml29623 	uint8_t			portn;
3713859Sml29623 #endif
3723859Sml29623 	nxge_status_t		status = NXGE_OK;
3733859Sml29623 
3743859Sml29623 #ifdef	NXGE_DEBUG
3753859Sml29623 	portn = nxgep->mac.portnum;
3763859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3773859Sml29623 		"==> nxge_serdes_init port<%d>", portn));
3783859Sml29623 #endif
3793859Sml29623 
3803859Sml29623 	statsp = nxgep->statsp;
3813859Sml29623 
3823859Sml29623 	if (nxgep->niu_type == N2_NIU) {
3833859Sml29623 		if (nxge_n2_serdes_init(nxgep) != NXGE_OK)
3843859Sml29623 			goto fail;
3853859Sml29623 	} else if ((nxgep->niu_type == NEPTUNE) ||
3863859Sml29623 				(nxgep->niu_type == NEPTUNE_2)) {
3873859Sml29623 			if ((status = nxge_neptune_serdes_init(nxgep))
3883859Sml29623 								!= NXGE_OK)
3893859Sml29623 				goto fail;
3903859Sml29623 	} else {
3913859Sml29623 		goto fail;
3923859Sml29623 	}
3933859Sml29623 
3943859Sml29623 	statsp->mac_stats.serdes_inits++;
3953859Sml29623 
3963859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
3973859Sml29623 			portn));
3983859Sml29623 
3993859Sml29623 	return (NXGE_OK);
4003859Sml29623 
4013859Sml29623 fail:
4023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4033859Sml29623 		"nxge_serdes_init: Failed to initialize serdes for port<%d>",
4043859Sml29623 			portn));
4053859Sml29623 
4063859Sml29623 	return (status);
4073859Sml29623 }
4083859Sml29623 
4093859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
4103859Sml29623 
4113859Sml29623 nxge_status_t
4123859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
4133859Sml29623 {
4143859Sml29623 	uint8_t portn;
4153859Sml29623 	int chan;
4163859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
4173859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
4183859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
4193859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
4203859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
4213859Sml29623 	esr_ti_testcfg_t test_cfg;
4223859Sml29623 	nxge_status_t status = NXGE_OK;
4233859Sml29623 
4243859Sml29623 	portn = nxgep->mac.portnum;
4253859Sml29623 
4263859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
4273859Sml29623 			portn));
4283859Sml29623 
4293859Sml29623 	tx_cfg_l.value = 0;
4303859Sml29623 	tx_cfg_h.value = 0;
4313859Sml29623 	rx_cfg_l.value = 0;
4323859Sml29623 	rx_cfg_h.value = 0;
4333859Sml29623 	pll_cfg_l.value = 0;
4343859Sml29623 	test_cfg.value = 0;
4353859Sml29623 
4363859Sml29623 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
4373859Sml29623 		/* 0x0E01 */
4383859Sml29623 		tx_cfg_l.bits.entx = 1;
4393859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
4403859Sml29623 
4413859Sml29623 		/* 0x9101 */
4423859Sml29623 		rx_cfg_l.bits.enrx = 1;
4433859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
4443859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
4453859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
4463859Sml29623 
4473859Sml29623 		/* 0x0008 */
4483859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
4493859Sml29623 
4503859Sml29623 		/* Set loopback mode if necessary */
4513859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
4523859Sml29623 			tx_cfg_l.bits.entest = 1;
4533859Sml29623 			rx_cfg_l.bits.entest = 1;
4543859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
4553859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
4563859Sml29623 				ESR_N2_DEV_ADDR,
4573859Sml29623 				ESR_N2_TEST_CFG_REG, test_cfg.value))
4583859Sml29623 				!= NXGE_OK)
4593859Sml29623 			goto fail;
4603859Sml29623 		}
4613859Sml29623 
4623859Sml29623 		/* Use default PLL value */
4633859Sml29623 
4643859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
4653859Sml29623 
4663859Sml29623 		/* 0x0E21 */
4673859Sml29623 		tx_cfg_l.bits.entx = 1;
4683859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
4693859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
4703859Sml29623 
4713859Sml29623 		/* 0x9121 */
4723859Sml29623 		rx_cfg_l.bits.enrx = 1;
4733859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
4743859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
4753859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
4763859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
4773859Sml29623 
4783859Sml29623 		/* 0x8 */
4793859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
4803859Sml29623 
4813859Sml29623 		/* MPY = 0x100 */
4823859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
4833859Sml29623 
4843859Sml29623 		/* Set PLL */
4853859Sml29623 		pll_cfg_l.bits.enpll = 1;
4863859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
4873859Sml29623 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
4883859Sml29623 				!= NXGE_OK)
4893859Sml29623 			goto fail;
4903859Sml29623 	} else {
4913859Sml29623 		goto fail;
4923859Sml29623 	}
4933859Sml29623 
4943859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
4953859Sml29623 
4963859Sml29623 	NXGE_DELAY(20);
4973859Sml29623 
4983859Sml29623 	/* init TX channels */
4993859Sml29623 	for (chan = 0; chan < 4; chan++) {
5003859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
5013859Sml29623 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
5023859Sml29623 				!= NXGE_OK)
5033859Sml29623 			goto fail;
5043859Sml29623 
5053859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
5063859Sml29623 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
5073859Sml29623 				!= NXGE_OK)
5083859Sml29623 			goto fail;
5093859Sml29623 	}
5103859Sml29623 
5113859Sml29623 	/* init RX channels */
5123859Sml29623 	for (chan = 0; chan < 4; chan++) {
5133859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
5143859Sml29623 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
5153859Sml29623 				!= NXGE_OK)
5163859Sml29623 			goto fail;
5173859Sml29623 
5183859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
5193859Sml29623 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
5203859Sml29623 				!= NXGE_OK)
5213859Sml29623 			goto fail;
5223859Sml29623 	}
5233859Sml29623 
5243859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
5253859Sml29623 			portn));
5263859Sml29623 
5273859Sml29623 	return (NXGE_OK);
5283859Sml29623 fail:
5293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5303859Sml29623 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
5313859Sml29623 				portn));
5323859Sml29623 
5333859Sml29623 	return (status);
5343859Sml29623 }
5353859Sml29623 
5363859Sml29623 /* Initialize Neptune Internal Serdes (Neptune only) */
5373859Sml29623 
5383859Sml29623 nxge_status_t
5393859Sml29623 nxge_neptune_serdes_init(p_nxge_t nxgep)
5403859Sml29623 {
5413859Sml29623 	npi_handle_t		handle;
5423859Sml29623 	uint8_t			portn;
5433859Sml29623 	nxge_port_mode_t	portmode;
5443859Sml29623 	int			chan;
5453859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
5463859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
5473859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
5483859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
5493859Sml29623 	uint64_t		val;
5503859Sml29623 	uint16_t		val16l;
5513859Sml29623 	uint16_t		val16h;
5523859Sml29623 	nxge_status_t		status = NXGE_OK;
5533859Sml29623 
5543859Sml29623 	portn = nxgep->mac.portnum;
5553859Sml29623 
5563859Sml29623 	if ((portn != 0) && (portn != 1))
5573859Sml29623 		return (NXGE_OK);
5583859Sml29623 
5593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>",
5603859Sml29623 			portn));
5613859Sml29623 
5623859Sml29623 	handle = nxgep->npi_handle;
5633859Sml29623 	portmode = nxgep->mac.portmode;
5643859Sml29623 
5653859Sml29623 	if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) {
5663859Sml29623 
5673859Sml29623 		switch (portn) {
5683859Sml29623 		case 0:
5693859Sml29623 			ESR_REG_WR(handle, ESR_0_CONTROL_REG,
5703859Sml29623 				ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
5713859Sml29623 				ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
5723859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
5733859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
5743859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
5753859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
5763859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
5773859Sml29623 				(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
5783859Sml29623 				(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
5793859Sml29623 				(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
5803859Sml29623 				(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
5813859Sml29623 
5823859Sml29623 				/* Set Serdes0 Internal Loopback if necessary */
5833859Sml29623 				if (nxgep->statsp->port_stats.lb_mode ==
5843859Sml29623 							nxge_lb_serdes10g) {
5853859Sml29623 					ESR_REG_WR(handle,
5863859Sml29623 						ESR_0_TEST_CONFIG_REG,
5873859Sml29623 						ESR_PAD_LOOPBACK_CH3 |
5883859Sml29623 						ESR_PAD_LOOPBACK_CH2 |
5893859Sml29623 						ESR_PAD_LOOPBACK_CH1 |
5903859Sml29623 						ESR_PAD_LOOPBACK_CH0);
5913859Sml29623 				} else {
5923859Sml29623 					ESR_REG_WR(handle,
5933859Sml29623 						ESR_0_TEST_CONFIG_REG, 0);
5943859Sml29623 				}
5953859Sml29623 			break;
5963859Sml29623 		case 1:
5973859Sml29623 			ESR_REG_WR(handle, ESR_1_CONTROL_REG,
5983859Sml29623 				ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
5993859Sml29623 				ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
6003859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
6013859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
6023859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
6033859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
6043859Sml29623 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
6053859Sml29623 				(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
6063859Sml29623 				(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
6073859Sml29623 				(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
6083859Sml29623 				(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
6093859Sml29623 
6103859Sml29623 				/* Set Serdes1 Internal Loopback if necessary */
6113859Sml29623 				if (nxgep->statsp->port_stats.lb_mode ==
6123859Sml29623 							nxge_lb_serdes10g) {
6133859Sml29623 					ESR_REG_WR(handle,
6143859Sml29623 						ESR_1_TEST_CONFIG_REG,
6153859Sml29623 						ESR_PAD_LOOPBACK_CH3 |
6163859Sml29623 						ESR_PAD_LOOPBACK_CH2 |
6173859Sml29623 						ESR_PAD_LOOPBACK_CH1 |
6183859Sml29623 						ESR_PAD_LOOPBACK_CH0);
6193859Sml29623 				} else {
6203859Sml29623 					ESR_REG_WR(handle,
6213859Sml29623 						ESR_1_TEST_CONFIG_REG, 0);
6223859Sml29623 				}
6233859Sml29623 			break;
6243859Sml29623 		default:
6253859Sml29623 			/* Nothing to do here */
6263859Sml29623 			goto done;
6273859Sml29623 		}
6283859Sml29623 
6293859Sml29623 		/* init TX RX channels */
6303859Sml29623 		for (chan = 0; chan < 4; chan++) {
6313859Sml29623 			if ((status = nxge_mdio_read(nxgep, portn,
6323859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6333859Sml29623 					ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
6343859Sml29623 					&rx_tx_ctrl_l.value)) != NXGE_OK)
6353859Sml29623 				goto fail;
6363859Sml29623 			if ((status = nxge_mdio_read(nxgep, portn,
6373859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6383859Sml29623 					ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
6393859Sml29623 					&rx_tx_ctrl_h.value)) != NXGE_OK)
6403859Sml29623 				goto fail;
6413859Sml29623 			if ((status = nxge_mdio_read(nxgep, portn,
6423859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6433859Sml29623 					ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
6443859Sml29623 					&glue_ctrl0_l.value)) != NXGE_OK)
6453859Sml29623 				goto fail;
6463859Sml29623 			if ((status = nxge_mdio_read(nxgep, portn,
6473859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6483859Sml29623 					ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
6493859Sml29623 					&glue_ctrl0_h.value)) != NXGE_OK)
6503859Sml29623 				goto fail;
6513859Sml29623 			rx_tx_ctrl_l.bits.enstretch = 1;
6523859Sml29623 			rx_tx_ctrl_h.bits.vmuxlo = 2;
6533859Sml29623 			rx_tx_ctrl_h.bits.vpulselo = 2;
6543859Sml29623 			glue_ctrl0_l.bits.rxlosenable = 1;
6553859Sml29623 			glue_ctrl0_l.bits.samplerate = 0xF;
6563859Sml29623 			glue_ctrl0_l.bits.thresholdcount = 0xFF;
6573859Sml29623 			glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
6583859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
6593859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6603859Sml29623 					ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
6613859Sml29623 					rx_tx_ctrl_l.value)) != NXGE_OK)
6623859Sml29623 				goto fail;
6633859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
6643859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6653859Sml29623 					ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
6663859Sml29623 					rx_tx_ctrl_h.value)) != NXGE_OK)
6673859Sml29623 				goto fail;
6683859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
6693859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6703859Sml29623 					ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
6713859Sml29623 					glue_ctrl0_l.value)) != NXGE_OK)
6723859Sml29623 				goto fail;
6733859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
6743859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6753859Sml29623 					ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
6763859Sml29623 					glue_ctrl0_h.value)) != NXGE_OK)
6773859Sml29623 				goto fail;
6783859Sml29623 		}
6793859Sml29623 
6803859Sml29623 		/* Apply Tx core reset */
6813859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn,
6823859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6833859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
6843859Sml29623 					(uint16_t)0)) != NXGE_OK)
6853859Sml29623 			goto fail;
6863859Sml29623 
6873859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn,
6883859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6893859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
6903859Sml29623 					(uint16_t)0xffff)) != NXGE_OK)
6913859Sml29623 			goto fail;
6923859Sml29623 
6933859Sml29623 		NXGE_DELAY(200);
6943859Sml29623 
6953859Sml29623 		/* Apply Rx core reset */
6963859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn,
6973859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
6983859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
6993859Sml29623 					(uint16_t)0xffff)) != NXGE_OK)
7003859Sml29623 			goto fail;
7013859Sml29623 
7023859Sml29623 		NXGE_DELAY(200);
7033859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn,
7043859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
7053859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
7063859Sml29623 					(uint16_t)0)) != NXGE_OK)
7073859Sml29623 			goto fail;
7083859Sml29623 
7093859Sml29623 		NXGE_DELAY(200);
7103859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
7113859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
7123859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
7133859Sml29623 					&val16l)) != NXGE_OK)
7143859Sml29623 			goto fail;
7153859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
7163859Sml29623 					ESR_NEPTUNE_DEV_ADDR,
7173859Sml29623 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
7183859Sml29623 					&val16h)) != NXGE_OK)
7193859Sml29623 			goto fail;
7203859Sml29623 		if ((val16l != 0) || (val16h != 0)) {
7213859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7223859Sml29623 					"Failed to reset port<%d> XAUI Serdes",
7233859Sml29623 					portn));
7243859Sml29623 		}
7253859Sml29623 
7263859Sml29623 		ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
7273859Sml29623 
7283859Sml29623 		if (portn == 0) {
7293859Sml29623 			if ((val & ESR_SIG_P0_BITS_MASK) !=
7303859Sml29623 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
7313859Sml29623 					ESR_SIG_XSERDES_RDY_P0 |
7323859Sml29623 					ESR_SIG_XDETECT_P0_CH3 |
7333859Sml29623 					ESR_SIG_XDETECT_P0_CH2 |
7343859Sml29623 					ESR_SIG_XDETECT_P0_CH1 |
7353859Sml29623 					ESR_SIG_XDETECT_P0_CH0)) {
7363859Sml29623 				goto fail;
7373859Sml29623 			}
7383859Sml29623 		} else if (portn == 1) {
7393859Sml29623 			if ((val & ESR_SIG_P1_BITS_MASK) !=
7403859Sml29623 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
7413859Sml29623 					ESR_SIG_XSERDES_RDY_P1 |
7423859Sml29623 					ESR_SIG_XDETECT_P1_CH3 |
7433859Sml29623 					ESR_SIG_XDETECT_P1_CH2 |
7443859Sml29623 					ESR_SIG_XDETECT_P1_CH1 |
7453859Sml29623 					ESR_SIG_XDETECT_P1_CH0)) {
7463859Sml29623 				goto fail;
7473859Sml29623 			}
7483859Sml29623 		}
7493859Sml29623 
7503859Sml29623 	} else if (portmode == PORT_1G_FIBER) {
7513859Sml29623 		ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val)
7523859Sml29623 		val &= ~ESR_PLL_CFG_FBDIV_2;
7533859Sml29623 		switch (portn) {
7543859Sml29623 		case 0:
7553859Sml29623 			val |= ESR_PLL_CFG_HALF_RATE_0;
7563859Sml29623 			break;
7573859Sml29623 		case 1:
7583859Sml29623 			val |= ESR_PLL_CFG_HALF_RATE_1;
7593859Sml29623 			break;
7603859Sml29623 		case 2:
7613859Sml29623 			val |= ESR_PLL_CFG_HALF_RATE_2;
7623859Sml29623 			break;
7633859Sml29623 		case 3:
7643859Sml29623 			val |= ESR_PLL_CFG_HALF_RATE_3;
7653859Sml29623 			break;
7663859Sml29623 		default:
7673859Sml29623 			goto fail;
7683859Sml29623 		}
7693859Sml29623 
7703859Sml29623 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
7713859Sml29623 	}
7723859Sml29623 
7733859Sml29623 done:
7743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>",
7753859Sml29623 			portn));
7763859Sml29623 	return (NXGE_OK);
7773859Sml29623 fail:
7783859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
7793859Sml29623 			"nxge_neptune_serdes_init: "
7803859Sml29623 			"Failed to initialize Neptune serdes for port<%d>",
7813859Sml29623 			portn));
7823859Sml29623 
7833859Sml29623 	return (status);
7843859Sml29623 }
7853859Sml29623 
7863859Sml29623 /* Look for transceiver type */
7873859Sml29623 
7883859Sml29623 nxge_status_t
7893859Sml29623 nxge_xcvr_find(p_nxge_t nxgep)
7903859Sml29623 {
7913859Sml29623 	uint8_t		portn;
7923859Sml29623 
7933859Sml29623 	portn = nxgep->mac.portnum;
7943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn));
7953859Sml29623 
7963859Sml29623 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
7973859Sml29623 		return (NXGE_ERROR);
7983859Sml29623 
7993859Sml29623 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
8003859Sml29623 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
8013859Sml29623 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
8023859Sml29623 		if ((nxgep->niu_type == NEPTUNE) ||
8033859Sml29623 			(nxgep->niu_type == NEPTUNE_2)) {
8043859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8053859Sml29623 					BCM8704_NEPTUNE_PORT_ADDR_BASE + portn;
8063859Sml29623 		} else if (nxgep->niu_type == N2_NIU) {
8073859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8083859Sml29623 					BCM8704_N2_PORT_ADDR_BASE + portn;
8093859Sml29623 		} else
8103859Sml29623 			return (NXGE_ERROR);
8113859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_COPPER) {
8123859Sml29623 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
8133859Sml29623 		/*
8143859Sml29623 		 * For Altas, Xcvr port numbers are swapped with ethernet
8153859Sml29623 		 * port number. This is designed for better signal
8163859Sml29623 		 * integrity in routing.
8173859Sml29623 		 */
8183859Sml29623 
8193859Sml29623 		switch (portn) {
8203859Sml29623 		case 0:
8213859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8223859Sml29623 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 3;
8233859Sml29623 			break;
8243859Sml29623 		case 1:
8253859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8263859Sml29623 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 2;
8273859Sml29623 			break;
8283859Sml29623 		case 2:
8293859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8303859Sml29623 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 1;
8313859Sml29623 			break;
8323859Sml29623 		case 3:
8333859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn =
8343859Sml29623 					BCM5464_NEPTUNE_PORT_ADDR_BASE;
8353859Sml29623 			break;
8363859Sml29623 		default:
8373859Sml29623 			return (NXGE_ERROR);
8383859Sml29623 		}
8393859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
8403859Sml29623 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
8413859Sml29623 		nxgep->statsp->mac_stats.xcvr_portn = portn;
8423859Sml29623 	} else {
8433859Sml29623 		return (NXGE_ERROR);
8443859Sml29623 	}
8453859Sml29623 
8463859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
8473859Sml29623 					nxgep->statsp->mac_stats.xcvr_inuse));
8483859Sml29623 	return (NXGE_OK);
8493859Sml29623 }
8503859Sml29623 
8513859Sml29623 /* Initialize transceiver */
8523859Sml29623 
8533859Sml29623 nxge_status_t
8543859Sml29623 nxge_xcvr_init(p_nxge_t nxgep)
8553859Sml29623 {
8563859Sml29623 	p_nxge_param_t		param_arr;
8573859Sml29623 	p_nxge_stats_t		statsp;
8583859Sml29623 	uint16_t		val;
8593859Sml29623 #ifdef	NXGE_DEBUG
8603859Sml29623 	uint8_t			portn;
8613859Sml29623 	uint16_t		val1;
8623859Sml29623 #endif
8633859Sml29623 	uint8_t			phy_port_addr;
8643859Sml29623 	pmd_tx_control_t	tx_ctl;
8653859Sml29623 	control_t		ctl;
8663859Sml29623 	phyxs_control_t		phyxs_ctl;
8673859Sml29623 	pcs_control_t		pcs_ctl;
8683859Sml29623 	uint32_t		delay = 0;
8693859Sml29623 	optics_dcntr_t		op_ctr;
8703859Sml29623 	nxge_status_t		status = NXGE_OK;
8713859Sml29623 #ifdef	NXGE_DEBUG
8723859Sml29623 	portn = nxgep->mac.portnum;
8733859Sml29623 #endif
8743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
8753859Sml29623 
8763859Sml29623 	param_arr = nxgep->param_arr;
8773859Sml29623 	statsp = nxgep->statsp;
8783859Sml29623 
8793859Sml29623 	/*
8803859Sml29623 	 * Initialize the xcvr statistics.
8813859Sml29623 	 */
8823859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
8833859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
8843859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
8853859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
8863859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
8873859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
8883859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
8893859Sml29623 	statsp->mac_stats.cap_pause = 0;
8903859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
8913859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
8923859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
8933859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
8943859Sml29623 
8953859Sml29623 	/*
8963859Sml29623 	 * Initialize the link statistics.
8973859Sml29623 	 */
8983859Sml29623 	statsp->mac_stats.link_T4 = 0;
8993859Sml29623 	statsp->mac_stats.link_asmpause = 0;
9003859Sml29623 	statsp->mac_stats.link_pause = 0;
9013859Sml29623 
9023859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
9033859Sml29623 
9043859Sml29623 	switch (nxgep->mac.portmode) {
9053859Sml29623 	case PORT_10G_FIBER:
9063859Sml29623 		/* Disable Link LEDs */
9073859Sml29623 		if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
9083859Sml29623 			goto fail;
9093859Sml29623 
9103859Sml29623 		/* Set Clause 45 */
9113859Sml29623 		npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
9123859Sml29623 
9133859Sml29623 		/* Reset the transceiver */
9143859Sml29623 		if ((status = nxge_mdio_read(nxgep,
9153859Sml29623 				phy_port_addr,
9163859Sml29623 				BCM8704_PHYXS_ADDR,
9173859Sml29623 				BCM8704_PHYXS_CONTROL_REG,
9183859Sml29623 				&phyxs_ctl.value)) != NXGE_OK)
9193859Sml29623 			goto fail;
9203859Sml29623 
9213859Sml29623 		phyxs_ctl.bits.reset = 1;
9223859Sml29623 		if ((status = nxge_mdio_write(nxgep,
9233859Sml29623 				phy_port_addr,
9243859Sml29623 				BCM8704_PHYXS_ADDR,
9253859Sml29623 				BCM8704_PHYXS_CONTROL_REG,
9263859Sml29623 				phyxs_ctl.value)) != NXGE_OK)
9273859Sml29623 			goto fail;
9283859Sml29623 
9293859Sml29623 		do {
9303859Sml29623 			drv_usecwait(500);
9313859Sml29623 			if ((status = nxge_mdio_read(nxgep,
9323859Sml29623 					phy_port_addr,
9333859Sml29623 					BCM8704_PHYXS_ADDR,
9343859Sml29623 					BCM8704_PHYXS_CONTROL_REG,
9353859Sml29623 					&phyxs_ctl.value)) != NXGE_OK)
9363859Sml29623 				goto fail;
9373859Sml29623 			delay++;
9383859Sml29623 		} while ((phyxs_ctl.bits.reset) && (delay < 100));
9393859Sml29623 		if (delay == 100) {
9403859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9413859Sml29623 				"nxge_xcvr_init: "
9423859Sml29623 				"failed to reset Transceiver on port<%d>",
9433859Sml29623 				portn));
9443859Sml29623 			status = NXGE_ERROR;
9453859Sml29623 			goto fail;
9463859Sml29623 		}
9473859Sml29623 
9483859Sml29623 		/* Set to 0x7FBF */
9493859Sml29623 		ctl.value = 0;
9503859Sml29623 		ctl.bits.res1 = 0x3F;
9513859Sml29623 		ctl.bits.optxon_lvl = 1;
9523859Sml29623 		ctl.bits.oprxflt_lvl = 1;
9533859Sml29623 		ctl.bits.optrxlos_lvl = 1;
9543859Sml29623 		ctl.bits.optxflt_lvl = 1;
9553859Sml29623 		ctl.bits.opprflt_lvl = 1;
9563859Sml29623 		ctl.bits.obtmpflt_lvl = 1;
9573859Sml29623 		ctl.bits.opbiasflt_lvl = 1;
9583859Sml29623 		ctl.bits.optxrst_lvl = 1;
9593859Sml29623 		if ((status = nxge_mdio_write(nxgep,
9603859Sml29623 				phy_port_addr,
9613859Sml29623 				BCM8704_USER_DEV3_ADDR,
9623859Sml29623 				BCM8704_USER_CONTROL_REG, ctl.value))
9633859Sml29623 				!= NXGE_OK)
9643859Sml29623 			goto fail;
9653859Sml29623 
9663859Sml29623 		/* Set to 0x164 */
9673859Sml29623 		tx_ctl.value = 0;
9683859Sml29623 		tx_ctl.bits.tsck_lpwren = 1;
9693859Sml29623 		tx_ctl.bits.tx_dac_txck = 0x2;
9703859Sml29623 		tx_ctl.bits.tx_dac_txd = 0x1;
9713859Sml29623 		tx_ctl.bits.xfp_clken = 1;
9723859Sml29623 		if ((status = nxge_mdio_write(nxgep,
9733859Sml29623 				phy_port_addr,
9743859Sml29623 				BCM8704_USER_DEV3_ADDR,
9753859Sml29623 				BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value))
9763859Sml29623 				!= NXGE_OK)
9773859Sml29623 			goto fail;
9783859Sml29623 		/*
9793859Sml29623 		 * According to Broadcom's instruction, SW needs to read
9803859Sml29623 		 * back these registers twice after written.
9813859Sml29623 		 */
9823859Sml29623 		if ((status = nxge_mdio_read(nxgep,
9833859Sml29623 				phy_port_addr,
9843859Sml29623 				BCM8704_USER_DEV3_ADDR,
9853859Sml29623 				BCM8704_USER_CONTROL_REG, &val))
9863859Sml29623 				!= NXGE_OK)
9873859Sml29623 			goto fail;
9883859Sml29623 
9893859Sml29623 		if ((status = nxge_mdio_read(nxgep,
9903859Sml29623 				phy_port_addr,
9913859Sml29623 				BCM8704_USER_DEV3_ADDR,
9923859Sml29623 				BCM8704_USER_CONTROL_REG, &val))
9933859Sml29623 				!= NXGE_OK)
9943859Sml29623 			goto fail;
9953859Sml29623 
9963859Sml29623 		if ((status = nxge_mdio_read(nxgep,
9973859Sml29623 				phy_port_addr,
9983859Sml29623 				BCM8704_USER_DEV3_ADDR,
9993859Sml29623 				BCM8704_USER_PMD_TX_CONTROL_REG, &val))
10003859Sml29623 				!= NXGE_OK)
10013859Sml29623 			goto fail;
10023859Sml29623 
10033859Sml29623 		if ((status = nxge_mdio_read(nxgep,
10043859Sml29623 				phy_port_addr,
10053859Sml29623 				BCM8704_USER_DEV3_ADDR,
10063859Sml29623 				BCM8704_USER_PMD_TX_CONTROL_REG, &val))
10073859Sml29623 				!= NXGE_OK)
10083859Sml29623 			goto fail;
10093859Sml29623 
10103859Sml29623 
10113859Sml29623 		/* Enable Tx and Rx LEDs to be driven by traffic */
10123859Sml29623 		if ((status = nxge_mdio_read(nxgep,
10133859Sml29623 					phy_port_addr,
10143859Sml29623 					BCM8704_USER_DEV3_ADDR,
10153859Sml29623 					BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
10163859Sml29623 					&op_ctr.value)) != NXGE_OK)
10173859Sml29623 			goto fail;
10183859Sml29623 		op_ctr.bits.gpio_sel = 0x3;
10193859Sml29623 		if ((status = nxge_mdio_write(nxgep,
10203859Sml29623 					phy_port_addr,
10213859Sml29623 					BCM8704_USER_DEV3_ADDR,
10223859Sml29623 					BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
10233859Sml29623 					op_ctr.value)) != NXGE_OK)
10243859Sml29623 			goto fail;
10253859Sml29623 
10263859Sml29623 		NXGE_DELAY(1000000);
10273859Sml29623 
10283859Sml29623 		/* Set BCM8704 Internal Loopback mode if necessary */
10293859Sml29623 		if ((status = nxge_mdio_read(nxgep,
10303859Sml29623 					phy_port_addr,
10313859Sml29623 					BCM8704_PCS_DEV_ADDR,
10323859Sml29623 					BCM8704_PCS_CONTROL_REG,
10333859Sml29623 					&pcs_ctl.value)) != NXGE_OK)
10343859Sml29623 			goto fail;
10353859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
10363859Sml29623 			pcs_ctl.bits.loopback = 1;
10373859Sml29623 		else
10383859Sml29623 			pcs_ctl.bits.loopback = 0;
10393859Sml29623 		if ((status = nxge_mdio_write(nxgep,
10403859Sml29623 					phy_port_addr,
10413859Sml29623 					BCM8704_PCS_DEV_ADDR,
10423859Sml29623 					BCM8704_PCS_CONTROL_REG,
10433859Sml29623 					pcs_ctl.value)) != NXGE_OK)
10443859Sml29623 			goto fail;
10453859Sml29623 
10463859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr,
10473859Sml29623 				0x1, 0xA, &val);
10483859Sml29623 		if (status != NXGE_OK)
10493859Sml29623 			goto fail;
10503859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10513859Sml29623 				"BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n",
10523859Sml29623 				portn, val));
10533859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
10543859Sml29623 		if (status != NXGE_OK)
10553859Sml29623 			goto fail;
10563859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10573859Sml29623 				"BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n",
10583859Sml29623 				portn, val));
10593859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
10603859Sml29623 		if (status != NXGE_OK)
10613859Sml29623 			goto fail;
10623859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10633859Sml29623 				"BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n",
10643859Sml29623 				portn, val));
10653859Sml29623 
10663859Sml29623 #ifdef	NXGE_DEBUG
10673859Sml29623 		/* Diagnose link issue if link is not up */
10683859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr,
10693859Sml29623 					BCM8704_USER_DEV3_ADDR,
10703859Sml29623 					BCM8704_USER_ANALOG_STATUS0_REG,
10713859Sml29623 					&val);
10723859Sml29623 		if (status != NXGE_OK)
10733859Sml29623 			goto fail;
10743859Sml29623 
10753859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr,
10763859Sml29623 					BCM8704_USER_DEV3_ADDR,
10773859Sml29623 					BCM8704_USER_ANALOG_STATUS0_REG,
10783859Sml29623 					&val);
10793859Sml29623 		if (status != NXGE_OK)
10803859Sml29623 			goto fail;
10813859Sml29623 
10823859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr,
10833859Sml29623 					BCM8704_USER_DEV3_ADDR,
10843859Sml29623 					BCM8704_USER_TX_ALARM_STATUS_REG,
10853859Sml29623 					&val1);
10863859Sml29623 		if (status != NXGE_OK)
10873859Sml29623 			goto fail;
10883859Sml29623 
10893859Sml29623 		status = nxge_mdio_read(nxgep, phy_port_addr,
10903859Sml29623 					BCM8704_USER_DEV3_ADDR,
10913859Sml29623 					BCM8704_USER_TX_ALARM_STATUS_REG,
10923859Sml29623 					&val1);
10933859Sml29623 		if (status != NXGE_OK)
10943859Sml29623 			goto fail;
10953859Sml29623 
10963859Sml29623 		if (val != 0x3FC) {
10973859Sml29623 			if ((val == 0x43BC) && (val1 != 0)) {
10983859Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10993859Sml29623 					"Cable not connected to peer or bad"
11003859Sml29623 					" cable on port<%d>\n", portn));
11013859Sml29623 			} else if (val == 0x639C) {
11023859Sml29623 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
11033859Sml29623 					"Optical module (XFP) is bad or absence"
11043859Sml29623 					" on port<%d>\n", portn));
11053859Sml29623 			}
11063859Sml29623 		}
11073859Sml29623 #endif
11083859Sml29623 
11093859Sml29623 		statsp->mac_stats.cap_10gfdx = 1;
11103859Sml29623 		statsp->mac_stats.lp_cap_10gfdx = 1;
11113859Sml29623 		break;
11123859Sml29623 	case PORT_10G_COPPER:
11133859Sml29623 		break;
11143859Sml29623 	case PORT_1G_FIBER:
11153859Sml29623 	case PORT_1G_COPPER:
11163859Sml29623 		/* Set Clause 22 */
11173859Sml29623 		npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
11183859Sml29623 
11193859Sml29623 		/* Set capability flags */
11203859Sml29623 		statsp->mac_stats.cap_1000fdx =
11213859Sml29623 					param_arr[param_anar_1000fdx].value;
11223859Sml29623 		statsp->mac_stats.cap_100fdx =
11233859Sml29623 					param_arr[param_anar_100fdx].value;
11243859Sml29623 		statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
11253859Sml29623 
11263859Sml29623 		if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK)
11273859Sml29623 			goto fail;
11283859Sml29623 		break;
11293859Sml29623 	default:
11303859Sml29623 		goto fail;
11313859Sml29623 	}
11323859Sml29623 
11333859Sml29623 	statsp->mac_stats.xcvr_inits++;
11343859Sml29623 
11353859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
11363859Sml29623 	return (NXGE_OK);
11373859Sml29623 
11383859Sml29623 fail:
11393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11403859Sml29623 		"nxge_xcvr_init: failed to initialize transceiver for port<%d>",
11413859Sml29623 		portn));
11423859Sml29623 	return (status);
11433859Sml29623 }
11443859Sml29623 
11453859Sml29623 
11463859Sml29623 /* Initialize the TxMAC sub-block */
11473859Sml29623 
11483859Sml29623 nxge_status_t
11493859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
11503859Sml29623 {
11513859Sml29623 	npi_attr_t		ap;
11523859Sml29623 	uint8_t			portn;
11533859Sml29623 	nxge_port_mode_t	portmode;
11543859Sml29623 	nxge_port_t		portt;
11553859Sml29623 	npi_handle_t		handle;
11563859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
11573859Sml29623 
11583859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
11593859Sml29623 	portt    = nxgep->mac.porttype;
11603859Sml29623 	handle   = nxgep->npi_handle;
11613859Sml29623 	portmode = nxgep->mac.portmode;
11623859Sml29623 
11633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
11643859Sml29623 			portn));
11653859Sml29623 
11663859Sml29623 	/* Set Max and Min Frame Size */
11673859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
11683859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
11693859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
11703859Sml29623 	} else {
11713859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
11723859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
11733859Sml29623 	}
11743859Sml29623 
11753859Sml29623 	if (rs != NPI_SUCCESS)
11763859Sml29623 		goto fail;
11773859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value ||
11783859Sml29623 		nxgep->mac.is_jumbo == B_TRUE)
11793859Sml29623 		nxgep->mac.maxframesize = 0x2400;
11803859Sml29623 	else
11813859Sml29623 		nxgep->mac.maxframesize = 0x5EE + 4;
11823859Sml29623 	nxgep->mac.minframesize = 64;
11833859Sml29623 
11843859Sml29623 	if (portt == PORT_TYPE_XMAC) {
11853859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
11863859Sml29623 				0)) != NPI_SUCCESS)
11873859Sml29623 			goto fail;
11883859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
11893859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
11903859Sml29623 					(portmode == PORT_10G_COPPER)) {
11913859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
11923859Sml29623 					XGMII_IPG_12_15, rs);
11933859Sml29623 			if (rs != NPI_SUCCESS)
11943859Sml29623 				goto fail;
11953859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
11963859Sml29623 		} else {
11973859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
11983859Sml29623 					MII_GMII_IPG_12, rs);
11993859Sml29623 			if (rs != NPI_SUCCESS)
12003859Sml29623 				goto fail;
12013859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
12023859Sml29623 		}
12033859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
12043859Sml29623 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
12053859Sml29623 			goto fail;
12063859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
12073859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
12083859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
12093859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
12103859Sml29623 
12113859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
12123859Sml29623 							!= NPI_SUCCESS)
12133859Sml29623 			goto fail;
12143859Sml29623 
12153859Sml29623 	} else {
12163859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
12173859Sml29623 				0)) != NPI_SUCCESS)
12183859Sml29623 			goto fail;
12193859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
12203859Sml29623 
12213859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
12223859Sml29623 				rs);
12233859Sml29623 		if (rs != NPI_SUCCESS)
12243859Sml29623 			goto fail;
12253859Sml29623 		nxgep->mac.ctrltype = 0x8808;
12263859Sml29623 
12273859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
12283859Sml29623 		if (rs != NPI_SUCCESS)
12293859Sml29623 			goto fail;
12303859Sml29623 		nxgep->mac.pa_size = 0x7;
12313859Sml29623 
12323859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
12333859Sml29623 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
12343859Sml29623 			goto fail;
12353859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
12363859Sml29623 	}
12373859Sml29623 
12383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
12393859Sml29623 			portn));
12403859Sml29623 
12413859Sml29623 	return (NXGE_OK);
12423859Sml29623 fail:
12433859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12443859Sml29623 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
12453859Sml29623 					portn));
12463859Sml29623 
12473859Sml29623 	return (NXGE_ERROR | rs);
12483859Sml29623 }
12493859Sml29623 
12503859Sml29623 /* Initialize the RxMAC sub-block */
12513859Sml29623 
12523859Sml29623 nxge_status_t
12533859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
12543859Sml29623 {
12553859Sml29623 	npi_attr_t		ap;
12563859Sml29623 	uint32_t		i;
12573859Sml29623 	uint16_t		hashtab_e;
12583859Sml29623 	p_hash_filter_t		hash_filter;
12593859Sml29623 	nxge_port_t		portt;
12603859Sml29623 	uint8_t			portn;
12613859Sml29623 	npi_handle_t		handle;
12623859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
12633859Sml29623 	uint16_t 		*addr16p;
12643859Sml29623 	uint16_t 		addr0, addr1, addr2;
12653859Sml29623 	xmac_rx_config_t	xconfig;
12663859Sml29623 	bmac_rx_config_t	bconfig;
12673859Sml29623 
12683859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
12693859Sml29623 
12703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
12713859Sml29623 			portn));
12723859Sml29623 	handle = nxgep->npi_handle;
12733859Sml29623 	portt = nxgep->mac.porttype;
12743859Sml29623 
12753859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
12763859Sml29623 	addr0 = ntohs(addr16p[2]);
12773859Sml29623 	addr1 = ntohs(addr16p[1]);
12783859Sml29623 	addr2 = ntohs(addr16p[0]);
12793859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
12803859Sml29623 		rs);
12813859Sml29623 
12823859Sml29623 	if (rs != NPI_SUCCESS)
12833859Sml29623 		goto fail;
12843859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
12853859Sml29623 	if (rs != NPI_SUCCESS)
12863859Sml29623 		goto fail;
12873859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
12883859Sml29623 	if (rs != NPI_SUCCESS)
12893859Sml29623 		goto fail;
12903859Sml29623 
12913859Sml29623 	/*
12923859Sml29623 	 * Load the multicast hash filter bits.
12933859Sml29623 	 */
12943859Sml29623 	hash_filter = nxgep->hash_filter;
12953859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
12963859Sml29623 		if (hash_filter != NULL) {
12973859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
12983859Sml29623 				(NMCFILTER_REGS - 1) - i];
12993859Sml29623 		} else {
13003859Sml29623 			hashtab_e = 0;
13013859Sml29623 		}
13023859Sml29623 
13033859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
13043859Sml29623 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
13053859Sml29623 			goto fail;
13063859Sml29623 	}
13073859Sml29623 
13083859Sml29623 	if (portt == PORT_TYPE_XMAC) {
13093859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
13103859Sml29623 				0)) != NPI_SUCCESS)
13113859Sml29623 			goto fail;
13123859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
13133859Sml29623 
13143859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
13153859Sml29623 
13163859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
13173859Sml29623 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
13183859Sml29623 			~CFG_XMAC_RX_STRIP_CRC;
13193859Sml29623 
13203859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
13213859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
13223859Sml29623 
13233859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
13243859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
13253859Sml29623 
13263859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
13273859Sml29623 
13283859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
13293859Sml29623 					xconfig)) != NPI_SUCCESS)
13303859Sml29623 			goto fail;
13313859Sml29623 		nxgep->mac.rx_config = xconfig;
13323859Sml29623 
13333859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
13343859Sml29623 
13353859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
13363859Sml29623 							!= NPI_SUCCESS)
13373859Sml29623 			goto fail;
13383859Sml29623 	} else {
13393859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
13403859Sml29623 
13413859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
13423859Sml29623 					0) != NPI_SUCCESS)
13433859Sml29623 			goto fail;
13443859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
13453859Sml29623 
13463859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
13473859Sml29623 			~CFG_BMAC_RX_STRIP_CRC;
13483859Sml29623 
13493859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
13503859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
13513859Sml29623 
13523859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
13533859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
13543859Sml29623 
13553859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
13563859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
13573859Sml29623 					bconfig)) != NPI_SUCCESS)
13583859Sml29623 			goto fail;
13593859Sml29623 		nxgep->mac.rx_config = bconfig;
13603859Sml29623 
13613859Sml29623 		/* Always enable comparison of mac unique address */
13623859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
13633859Sml29623 					!= NPI_SUCCESS)
13643859Sml29623 			goto fail;
13653859Sml29623 	}
13663859Sml29623 
13673859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
13683859Sml29623 			portn));
13693859Sml29623 
13703859Sml29623 	return (NXGE_OK);
13713859Sml29623 
13723859Sml29623 fail:
13733859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13743859Sml29623 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
13753859Sml29623 				portn));
13763859Sml29623 
13773859Sml29623 	return (NXGE_ERROR | rs);
13783859Sml29623 }
13793859Sml29623 
13803859Sml29623 /* Enable TXMAC */
13813859Sml29623 
13823859Sml29623 nxge_status_t
13833859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
13843859Sml29623 {
13853859Sml29623 	npi_handle_t	handle;
13863859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
13873859Sml29623 	nxge_status_t	status = NXGE_OK;
13883859Sml29623 
13893859Sml29623 	handle = nxgep->npi_handle;
13903859Sml29623 
13913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
13923859Sml29623 			nxgep->mac.portnum));
13933859Sml29623 
13943859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
13953859Sml29623 		goto fail;
13963859Sml29623 
13973859Sml29623 	/* based on speed */
13983859Sml29623 	nxgep->msg_min = ETHERMIN;
13993859Sml29623 
14003859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
14013859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
14023859Sml29623 						CFG_XMAC_TX)) != NPI_SUCCESS)
14033859Sml29623 			goto fail;
14043859Sml29623 	} else {
14053859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
14063859Sml29623 						CFG_BMAC_TX)) != NPI_SUCCESS)
14073859Sml29623 			goto fail;
14083859Sml29623 	}
14093859Sml29623 
14103859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
14113859Sml29623 			nxgep->mac.portnum));
14123859Sml29623 
14133859Sml29623 	return (NXGE_OK);
14143859Sml29623 fail:
14153859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14163859Sml29623 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
14173859Sml29623 			nxgep->mac.portnum));
14183859Sml29623 	if (rs != NPI_SUCCESS)
14193859Sml29623 		return (NXGE_ERROR | rs);
14203859Sml29623 	else
14213859Sml29623 		return (status);
14223859Sml29623 }
14233859Sml29623 
14243859Sml29623 /* Disable TXMAC */
14253859Sml29623 
14263859Sml29623 nxge_status_t
14273859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
14283859Sml29623 {
14293859Sml29623 	npi_handle_t	handle;
14303859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
14313859Sml29623 
14323859Sml29623 	handle = nxgep->npi_handle;
14333859Sml29623 
14343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
14353859Sml29623 			nxgep->mac.portnum));
14363859Sml29623 
14373859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
14383859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
14393859Sml29623 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
14403859Sml29623 			goto fail;
14413859Sml29623 	} else {
14423859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
14433859Sml29623 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
14443859Sml29623 			goto fail;
14453859Sml29623 	}
14463859Sml29623 
14473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
14483859Sml29623 			nxgep->mac.portnum));
14493859Sml29623 	return (NXGE_OK);
14503859Sml29623 fail:
14513859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14523859Sml29623 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
14533859Sml29623 			nxgep->mac.portnum));
14543859Sml29623 	return (NXGE_ERROR | rs);
14553859Sml29623 }
14563859Sml29623 
14573859Sml29623 /* Enable RXMAC */
14583859Sml29623 
14593859Sml29623 nxge_status_t
14603859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
14613859Sml29623 {
14623859Sml29623 	npi_handle_t	handle;
14633859Sml29623 	uint8_t 	portn;
14643859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
14653859Sml29623 	nxge_status_t	status = NXGE_OK;
14663859Sml29623 
14673859Sml29623 	handle = nxgep->npi_handle;
14683859Sml29623 	portn = nxgep->mac.portnum;
14693859Sml29623 
14703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
14713859Sml29623 			portn));
14723859Sml29623 
14733859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
14743859Sml29623 		goto fail;
14753859Sml29623 
14763859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
14773859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
14783859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
14793859Sml29623 			goto fail;
14803859Sml29623 	} else {
14813859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
14823859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
14833859Sml29623 			goto fail;
14843859Sml29623 	}
14853859Sml29623 
14863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
14873859Sml29623 			portn));
14883859Sml29623 
14893859Sml29623 	return (NXGE_OK);
14903859Sml29623 fail:
14913859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14923859Sml29623 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
14933859Sml29623 			portn));
14943859Sml29623 
14953859Sml29623 	if (rs != NPI_SUCCESS)
14963859Sml29623 		return (NXGE_ERROR | rs);
14973859Sml29623 	else
14983859Sml29623 		return (status);
14993859Sml29623 }
15003859Sml29623 
15013859Sml29623 /* Disable RXMAC */
15023859Sml29623 
15033859Sml29623 nxge_status_t
15043859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
15053859Sml29623 {
15063859Sml29623 	npi_handle_t	handle;
15073859Sml29623 	uint8_t		portn;
15083859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15093859Sml29623 
15103859Sml29623 	handle = nxgep->npi_handle;
15113859Sml29623 	portn = nxgep->mac.portnum;
15123859Sml29623 
15133859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
15143859Sml29623 			portn));
15153859Sml29623 
15163859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15173859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
15183859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
15193859Sml29623 			goto fail;
15203859Sml29623 	} else {
15213859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
15223859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
15233859Sml29623 			goto fail;
15243859Sml29623 	}
15253859Sml29623 
15263859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
15273859Sml29623 			portn));
15283859Sml29623 	return (NXGE_OK);
15293859Sml29623 fail:
15303859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15313859Sml29623 			"nxgep_rx_mac_disable: ",
15323859Sml29623 			"Failed to disable port<%d> RxMAC",
15333859Sml29623 			portn));
15343859Sml29623 
15353859Sml29623 	return (NXGE_ERROR | rs);
15363859Sml29623 }
15373859Sml29623 
15383859Sml29623 /* Reset TXMAC */
15393859Sml29623 
15403859Sml29623 nxge_status_t
15413859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
15423859Sml29623 {
15433859Sml29623 	npi_handle_t	handle;
15443859Sml29623 	uint8_t		portn;
15453859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15463859Sml29623 
15473859Sml29623 	handle = nxgep->npi_handle;
15483859Sml29623 	portn = nxgep->mac.portnum;
15493859Sml29623 
15503859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
15513859Sml29623 			portn));
15523859Sml29623 
15533859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15543859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
15553859Sml29623 		    != NPI_SUCCESS)
15563859Sml29623 			goto fail;
15573859Sml29623 	} else {
15583859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
15593859Sml29623 					!= NPI_SUCCESS)
15603859Sml29623 			goto fail;
15613859Sml29623 	}
15623859Sml29623 
15633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
15643859Sml29623 			portn));
15653859Sml29623 
15663859Sml29623 	return (NXGE_OK);
15673859Sml29623 fail:
15683859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15693859Sml29623 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
15703859Sml29623 			portn));
15713859Sml29623 
15723859Sml29623 	return (NXGE_ERROR | rs);
15733859Sml29623 }
15743859Sml29623 
15753859Sml29623 /* Reset RXMAC */
15763859Sml29623 
15773859Sml29623 nxge_status_t
15783859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
15793859Sml29623 {
15803859Sml29623 	npi_handle_t	handle;
15813859Sml29623 	uint8_t		portn;
15823859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15833859Sml29623 
15843859Sml29623 	handle = nxgep->npi_handle;
15853859Sml29623 	portn = nxgep->mac.portnum;
15863859Sml29623 
15873859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
15883859Sml29623 			portn));
15893859Sml29623 
15903859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15913859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
15923859Sml29623 		    != NPI_SUCCESS)
15933859Sml29623 		goto fail;
15943859Sml29623 	} else {
15953859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
15963859Sml29623 					!= NPI_SUCCESS)
15973859Sml29623 		goto fail;
15983859Sml29623 	}
15993859Sml29623 
16003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
16013859Sml29623 			portn));
16023859Sml29623 
16033859Sml29623 	return (NXGE_OK);
16043859Sml29623 fail:
16053859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16063859Sml29623 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
16073859Sml29623 			portn));
16083859Sml29623 	return (NXGE_ERROR | rs);
16093859Sml29623 }
16103859Sml29623 
16113859Sml29623 
16123859Sml29623 /* Enable/Disable MII Link Status change interrupt */
16133859Sml29623 
16143859Sml29623 nxge_status_t
16153859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
16163859Sml29623 {
16173859Sml29623 	uint8_t			portn;
16183859Sml29623 	nxge_port_mode_t	portmode;
16193859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
16203859Sml29623 
16213859Sml29623 	portn = nxgep->mac.portnum;
16223859Sml29623 	portmode = nxgep->mac.portmode;
16233859Sml29623 
16243859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
16253859Sml29623 
16263859Sml29623 	if (enable == LINK_INTR_START) {
16273859Sml29623 		if (portmode == PORT_10G_FIBER) {
16283859Sml29623 			if ((rs = npi_xmac_xpcs_link_intr_enable(
16293859Sml29623 						nxgep->npi_handle,
16303859Sml29623 						portn)) != NPI_SUCCESS)
16313859Sml29623 				goto fail;
16323859Sml29623 		} else if (portmode == PORT_1G_FIBER) {
16333859Sml29623 			if ((rs = npi_mac_pcs_link_intr_enable(
16343859Sml29623 						nxgep->npi_handle,
16353859Sml29623 						portn)) != NPI_SUCCESS)
16363859Sml29623 				goto fail;
16373859Sml29623 		} else if (portmode == PORT_1G_COPPER) {
16383859Sml29623 			if ((rs = npi_mac_mif_link_intr_enable(
16393859Sml29623 				nxgep->npi_handle,
16403859Sml29623 				portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS)
16413859Sml29623 				goto fail;
16423859Sml29623 		} else
16433859Sml29623 			goto fail;
16443859Sml29623 	} else if (enable == LINK_INTR_STOP) {
16453859Sml29623 		if (portmode == PORT_10G_FIBER) {
16463859Sml29623 			if ((rs = npi_xmac_xpcs_link_intr_disable(
16473859Sml29623 						nxgep->npi_handle,
16483859Sml29623 						portn)) != NPI_SUCCESS)
16493859Sml29623 				goto fail;
16503859Sml29623 		} else  if (portmode == PORT_1G_FIBER) {
16513859Sml29623 			if ((rs = npi_mac_pcs_link_intr_disable(
16523859Sml29623 						nxgep->npi_handle,
16533859Sml29623 						portn)) != NPI_SUCCESS)
16543859Sml29623 				goto fail;
16553859Sml29623 		} else if (portmode == PORT_1G_COPPER) {
16563859Sml29623 			if ((rs = npi_mac_mif_link_intr_disable(
16573859Sml29623 						nxgep->npi_handle,
16583859Sml29623 						portn)) != NPI_SUCCESS)
16593859Sml29623 				goto fail;
16603859Sml29623 		} else
16613859Sml29623 			goto fail;
16623859Sml29623 	}
16633859Sml29623 
16643859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
16653859Sml29623 
16663859Sml29623 	return (NXGE_OK);
16673859Sml29623 fail:
16683859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16693859Sml29623 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
16703859Sml29623 			portn));
16713859Sml29623 
16723859Sml29623 	return (NXGE_ERROR | rs);
16733859Sml29623 }
16743859Sml29623 
16753859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
16763859Sml29623 
16773859Sml29623 nxge_status_t
16783859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
16793859Sml29623 {
16803859Sml29623 	p_nxge_param_t	param_arr;
16813859Sml29623 	p_nxge_stats_t	statsp;
16823859Sml29623 	uint8_t		xcvr_portn;
16833859Sml29623 	p_mii_regs_t	mii_regs;
16843859Sml29623 	mii_bmcr_t	bmcr;
16853859Sml29623 	mii_bmsr_t	bmsr;
16863859Sml29623 	mii_anar_t	anar;
16873859Sml29623 	mii_gcr_t	gcr;
16883859Sml29623 	mii_esr_t	esr;
16893859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
16903859Sml29623 	int		status = NXGE_OK;
16913859Sml29623 
16923859Sml29623 	uint_t delay;
16933859Sml29623 
16943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
16953859Sml29623 
16963859Sml29623 	param_arr = nxgep->param_arr;
16973859Sml29623 	statsp = nxgep->statsp;
16983859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
16993859Sml29623 
17003859Sml29623 	mii_regs = NULL;
17013859Sml29623 
17023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17033859Sml29623 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
17043859Sml29623 
17053859Sml29623 	/*
17063859Sml29623 	 * Reset the transceiver.
17073859Sml29623 	 */
17083859Sml29623 	delay = 0;
17093859Sml29623 	bmcr.value = 0;
17103859Sml29623 	bmcr.bits.reset = 1;
17113859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
17123859Sml29623 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
17133859Sml29623 		goto fail;
17143859Sml29623 	do {
17153859Sml29623 		drv_usecwait(500);
17163859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
17173859Sml29623 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
17183859Sml29623 				!= NXGE_OK)
17193859Sml29623 			goto fail;
17203859Sml29623 		delay++;
17213859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
17223859Sml29623 	if (delay == 1000) {
17233859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
17243859Sml29623 		goto fail;
17253859Sml29623 	}
17263859Sml29623 
17273859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
17283859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
17293859Sml29623 			&bmsr.value)) != NXGE_OK)
17303859Sml29623 		goto fail;
17313859Sml29623 
17323859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
17333859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
17343859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
17353859Sml29623 	param_arr[param_anar_100hdx].value = 0;
17363859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
17373859Sml29623 	param_arr[param_anar_10hdx].value = 0;
17383859Sml29623 
17393859Sml29623 	/*
17403859Sml29623 	 * Initialize the xcvr statistics.
17413859Sml29623 	 */
17423859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
17433859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
17443859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
17453859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
17463859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
17473859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
17483859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
17493859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
17503859Sml29623 
17513859Sml29623 	/*
17523859Sml29623 	 * Initialise the xcvr advertised capability statistics.
17533859Sml29623 	 */
17543859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
17553859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
17563859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
17573859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
17583859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
17593859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
17603859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
17613859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
17623859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
17633859Sml29623 					param_arr[param_anar_asmpause].value;
17643859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
17653859Sml29623 
17663859Sml29623 
17673859Sml29623 	/*
17683859Sml29623 	 * Check for extended status just in case we're
17693859Sml29623 	 * running a Gigibit phy.
17703859Sml29623 	 */
17713859Sml29623 	if (bmsr.bits.extend_status) {
17723859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
17733859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
17743859Sml29623 				!= NXGE_OK)
17753859Sml29623 			goto fail;
17763859Sml29623 		param_arr[param_anar_1000fdx].value &=
17773859Sml29623 					esr.bits.link_1000fdx;
17783859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
17793859Sml29623 
17803859Sml29623 		statsp->mac_stats.cap_1000fdx =
17813859Sml29623 			(esr.bits.link_1000Xfdx ||
17823859Sml29623 				esr.bits.link_1000fdx);
17833859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
17843859Sml29623 	} else {
17853859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
17863859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
17873859Sml29623 	}
17883859Sml29623 
17893859Sml29623 	/*
17903859Sml29623 	 * Initialize 1G Statistics once the capability is established.
17913859Sml29623 	 */
17923859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
17933859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
17943859Sml29623 
17953859Sml29623 	/*
17963859Sml29623 	 * Initialise the link statistics.
17973859Sml29623 	 */
17983859Sml29623 	statsp->mac_stats.link_T4 = 0;
17993859Sml29623 	statsp->mac_stats.link_asmpause = 0;
18003859Sml29623 	statsp->mac_stats.link_pause = 0;
18013859Sml29623 	statsp->mac_stats.link_speed = 0;
18023859Sml29623 	statsp->mac_stats.link_duplex = 0;
18033859Sml29623 	statsp->mac_stats.link_up = 0;
18043859Sml29623 
18053859Sml29623 	/*
18063859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
18073859Sml29623 	 */
18083859Sml29623 	bmcr.value = 0;
18093859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
18103859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
18113859Sml29623 		goto fail;
18123859Sml29623 
18133859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
18143859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
18153859Sml29623 		bmcr.bits.loopback = 1;
18163859Sml29623 		bmcr.bits.enable_autoneg = 0;
18173859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
18183859Sml29623 			bmcr.bits.speed_1000_sel = 1;
18193859Sml29623 		bmcr.bits.duplex_mode = 1;
18203859Sml29623 		param_arr[param_autoneg].value = 0;
18213859Sml29623 	} else {
18223859Sml29623 		bmcr.bits.loopback = 0;
18233859Sml29623 	}
18243859Sml29623 
18253859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
18263859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
18273859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
18283859Sml29623 		param_arr[param_autoneg].value = 0;
18293859Sml29623 		bcm5464r_aux.value = 0;
18303859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
18313859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
18323859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
18333859Sml29623 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
18343859Sml29623 				!= NXGE_OK)
18353859Sml29623 			goto fail;
18363859Sml29623 	}
18373859Sml29623 
18383859Sml29623 	if (param_arr[param_autoneg].value) {
18393859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18403859Sml29623 				"Restarting Auto-negotiation."));
18413859Sml29623 		/*
18423859Sml29623 		 * Setup our Auto-negotiation advertisement register.
18433859Sml29623 		 */
18443859Sml29623 		anar.value = 0;
18453859Sml29623 		anar.bits.selector = 1;
18463859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
18473859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
18483859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
18493859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
18503859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
18513859Sml29623 		anar.bits.cap_asmpause = 0;
18523859Sml29623 		anar.bits.cap_pause = 0;
18533859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
18543859Sml29623 			param_arr[param_anar_100fdx].value ||
18553859Sml29623 			param_arr[param_anar_10fdx].value) {
18563859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
18573859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
18583859Sml29623 		}
18593859Sml29623 
18603859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
18613859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
18623859Sml29623 				!= NXGE_OK)
18633859Sml29623 			goto fail;
18643859Sml29623 		if (bmsr.bits.extend_status) {
18653859Sml29623 			gcr.value = 0;
18663859Sml29623 			gcr.bits.ms_mode_en =
18673859Sml29623 				param_arr[param_master_cfg_enable].value;
18683859Sml29623 			gcr.bits.master =
18693859Sml29623 				param_arr[param_master_cfg_value].value;
18703859Sml29623 			gcr.bits.link_1000fdx =
18713859Sml29623 				param_arr[param_anar_1000fdx].value;
18723859Sml29623 			gcr.bits.link_1000hdx =
18733859Sml29623 				param_arr[param_anar_1000hdx].value;
18743859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
18753859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
18763859Sml29623 				!= NXGE_OK)
18773859Sml29623 				goto fail;
18783859Sml29623 		}
18793859Sml29623 
18803859Sml29623 		bmcr.bits.enable_autoneg = 1;
18813859Sml29623 		bmcr.bits.restart_autoneg = 1;
18823859Sml29623 
18833859Sml29623 	} else {
18843859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
18853859Sml29623 		bmcr.bits.speed_1000_sel =
18863859Sml29623 			param_arr[param_anar_1000fdx].value |
18873859Sml29623 				param_arr[param_anar_1000hdx].value;
18883859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
18893859Sml29623 			(param_arr[param_anar_100fdx].value |
18903859Sml29623 				param_arr[param_anar_100hdx].value);
18913859Sml29623 		if (bmcr.bits.speed_1000_sel) {
18923859Sml29623 			statsp->mac_stats.link_speed = 1000;
18933859Sml29623 			gcr.value = 0;
18943859Sml29623 			gcr.bits.ms_mode_en =
18953859Sml29623 				param_arr[param_master_cfg_enable].value;
18963859Sml29623 			gcr.bits.master =
18973859Sml29623 				param_arr[param_master_cfg_value].value;
18983859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
18993859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr),
19003859Sml29623 				gcr.value))
19013859Sml29623 				!= NXGE_OK)
19023859Sml29623 				goto fail;
19033859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
19043859Sml29623 				bmcr.bits.duplex_mode = 1;
19053859Sml29623 				statsp->mac_stats.link_duplex = 2;
19063859Sml29623 			} else
19073859Sml29623 				statsp->mac_stats.link_duplex = 1;
19083859Sml29623 		} else if (bmcr.bits.speed_sel) {
19093859Sml29623 			statsp->mac_stats.link_speed = 100;
19103859Sml29623 			if (param_arr[param_anar_100fdx].value) {
19113859Sml29623 				bmcr.bits.duplex_mode = 1;
19123859Sml29623 				statsp->mac_stats.link_duplex = 2;
19133859Sml29623 			} else
19143859Sml29623 				statsp->mac_stats.link_duplex = 1;
19153859Sml29623 		} else {
19163859Sml29623 			statsp->mac_stats.link_speed = 10;
19173859Sml29623 			if (param_arr[param_anar_10fdx].value) {
19183859Sml29623 				bmcr.bits.duplex_mode = 1;
19193859Sml29623 				statsp->mac_stats.link_duplex = 2;
19203859Sml29623 			} else
19213859Sml29623 				statsp->mac_stats.link_duplex = 1;
19223859Sml29623 		}
19233859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
19243859Sml29623 			statsp->mac_stats.link_asmpause =
19253859Sml29623 						statsp->mac_stats.cap_asmpause;
19263859Sml29623 			statsp->mac_stats.link_pause =
19273859Sml29623 						statsp->mac_stats.cap_pause;
19283859Sml29623 		}
19293859Sml29623 
19303859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
19313859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
19323859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
19333859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
19343859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
19353859Sml29623 				gcr.value = 0;
19363859Sml29623 				gcr.bits.ms_mode_en = 1;
19373859Sml29623 				gcr.bits.master = 1;
19383859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
19393859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gcr),
19403859Sml29623 					gcr.value))
19413859Sml29623 					!= NXGE_OK)
19423859Sml29623 					goto fail;
19433859Sml29623 				bmcr.value = 0;
19443859Sml29623 				bmcr.bits.speed_1000_sel = 1;
19453859Sml29623 				statsp->mac_stats.link_speed = 1000;
19463859Sml29623 			} else if (statsp->port_stats.lb_mode
19473859Sml29623 			    == nxge_lb_ext100) {
19483859Sml29623 				/* BCM5464R 100mbps external loopback mode */
19493859Sml29623 				bmcr.value = 0;
19503859Sml29623 				bmcr.bits.speed_sel = 1;
19513859Sml29623 				bmcr.bits.duplex_mode = 1;
19523859Sml29623 				statsp->mac_stats.link_speed = 100;
19533859Sml29623 			} else if (statsp->port_stats.lb_mode
19543859Sml29623 			    == nxge_lb_ext10) {
19553859Sml29623 				/* BCM5464R 10mbps external loopback mode */
19563859Sml29623 				bmcr.value = 0;
19573859Sml29623 				bmcr.bits.duplex_mode = 1;
19583859Sml29623 				statsp->mac_stats.link_speed = 10;
19593859Sml29623 			}
19603859Sml29623 		}
19613859Sml29623 	}
19623859Sml29623 
19633859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
19643859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
19653859Sml29623 			bmcr.value)) != NXGE_OK)
19663859Sml29623 		goto fail;
19673859Sml29623 
19683859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
19693859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
19703859Sml29623 		goto fail;
19713859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
19723859Sml29623 
19733859Sml29623 	/*
19743859Sml29623 	 * Initialize the xcvr status kept in the context structure.
19753859Sml29623 	 */
19763859Sml29623 	nxgep->soft_bmsr.value = 0;
19773859Sml29623 
19783859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
19793859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
19803859Sml29623 			&nxgep->bmsr.value)) != NXGE_OK)
19813859Sml29623 		goto fail;
19823859Sml29623 
19833859Sml29623 	statsp->mac_stats.xcvr_inits++;
19843859Sml29623 	nxgep->bmsr.value = 0;
19853859Sml29623 
19863859Sml29623 fail:
19873859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19883859Sml29623 			"<== nxge_mii_xcvr_init status 0x%x", status));
19893859Sml29623 	return (status);
19903859Sml29623 }
19913859Sml29623 
19923859Sml29623 /* Read from a MII compliant register */
19933859Sml29623 
19943859Sml29623 nxge_status_t
19953859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
19963859Sml29623 		uint16_t *value)
19973859Sml29623 {
19983859Sml29623 	npi_status_t rs = NPI_SUCCESS;
19993859Sml29623 
20003859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
20013859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
20023859Sml29623 
20033859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
20043859Sml29623 
20053859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
20063859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
20073859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
20083859Sml29623 			goto fail;
20093859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
20103859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
20113859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
20123859Sml29623 			goto fail;
20133859Sml29623 	} else
20143859Sml29623 		goto fail;
20153859Sml29623 
20163859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
20173859Sml29623 
20183859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
20193859Sml29623 			"xcvr_reg<%d> value=0x%x",
20203859Sml29623 			xcvr_portn, xcvr_reg, *value));
20213859Sml29623 	return (NXGE_OK);
20223859Sml29623 fail:
20233859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
20243859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20253859Sml29623 			"nxge_mii_read: Failed to read mii on xcvr %d",
20263859Sml29623 			xcvr_portn));
20273859Sml29623 
20283859Sml29623 	return (NXGE_ERROR | rs);
20293859Sml29623 }
20303859Sml29623 
20313859Sml29623 /* Write to a MII compliant Register */
20323859Sml29623 
20333859Sml29623 nxge_status_t
20343859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
20353859Sml29623 		uint16_t value)
20363859Sml29623 {
20373859Sml29623 	npi_status_t rs = NPI_SUCCESS;
20383859Sml29623 
20393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
20403859Sml29623 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
20413859Sml29623 			value));
20423859Sml29623 
20433859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
20443859Sml29623 
20453859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
20463859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
20473859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
20483859Sml29623 			goto fail;
20493859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
20503859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
20513859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
20523859Sml29623 			goto fail;
20533859Sml29623 	} else
20543859Sml29623 		goto fail;
20553859Sml29623 
20563859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
20573859Sml29623 
20583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
20593859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
20603859Sml29623 	return (NXGE_OK);
20613859Sml29623 fail:
20623859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
20633859Sml29623 
20643859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20653859Sml29623 			"nxge_mii_write: Failed to write mii on xcvr %d",
20663859Sml29623 			xcvr_portn));
20673859Sml29623 
20683859Sml29623 	return (NXGE_ERROR | rs);
20693859Sml29623 }
20703859Sml29623 
20713859Sml29623 /* Perform read from Clause45 serdes / transceiver device */
20723859Sml29623 
20733859Sml29623 nxge_status_t
20743859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
20753859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
20763859Sml29623 {
20773859Sml29623 	npi_status_t rs = NPI_SUCCESS;
20783859Sml29623 
20793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
20803859Sml29623 			xcvr_portn));
20813859Sml29623 
20823859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
20833859Sml29623 
20843859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
20853859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
20863859Sml29623 		goto fail;
20873859Sml29623 
20883859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
20893859Sml29623 
20903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
20913859Sml29623 			xcvr_portn));
20923859Sml29623 	return (NXGE_OK);
20933859Sml29623 fail:
20943859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
20953859Sml29623 
20963859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20973859Sml29623 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
20983859Sml29623 			xcvr_portn));
20993859Sml29623 
21003859Sml29623 	return (NXGE_ERROR | rs);
21013859Sml29623 }
21023859Sml29623 
21033859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
21043859Sml29623 
21053859Sml29623 nxge_status_t
21063859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
21073859Sml29623 		uint16_t xcvr_reg, uint16_t value)
21083859Sml29623 {
21093859Sml29623 	npi_status_t rs = NPI_SUCCESS;
21103859Sml29623 
21113859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
21123859Sml29623 			xcvr_portn));
21133859Sml29623 
21143859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
21153859Sml29623 
21163859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
21173859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
21183859Sml29623 		goto fail;
21193859Sml29623 
21203859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
21213859Sml29623 
21223859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
21233859Sml29623 			xcvr_portn));
21243859Sml29623 	return (NXGE_OK);
21253859Sml29623 fail:
21263859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
21273859Sml29623 
21283859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21293859Sml29623 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
21303859Sml29623 			xcvr_portn));
21313859Sml29623 
21323859Sml29623 	return (NXGE_ERROR | rs);
21333859Sml29623 }
21343859Sml29623 
21353859Sml29623 
21363859Sml29623 /* Check MII to see if there is any link status change */
21373859Sml29623 
21383859Sml29623 nxge_status_t
21393859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
21403859Sml29623 		nxge_link_state_t *link_up)
21413859Sml29623 {
21423859Sml29623 	p_nxge_param_t	param_arr;
21433859Sml29623 	p_nxge_stats_t	statsp;
21443859Sml29623 	p_mii_regs_t	mii_regs;
21453859Sml29623 	p_mii_bmsr_t	soft_bmsr;
21463859Sml29623 	mii_anar_t	anar;
21473859Sml29623 	mii_anlpar_t	anlpar;
21483859Sml29623 	mii_anar_t	an_common;
21493859Sml29623 	mii_aner_t	aner;
21503859Sml29623 	mii_gsr_t	gsr;
21513859Sml29623 	nxge_status_t	status = NXGE_OK;
21523859Sml29623 
21533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
21543859Sml29623 
21553859Sml29623 	mii_regs = NULL;
21563859Sml29623 	param_arr = nxgep->param_arr;
21573859Sml29623 	statsp = nxgep->statsp;
21583859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
21593859Sml29623 	*link_up = LINK_NO_CHANGE;
21603859Sml29623 
21613859Sml29623 	if (bmsr_ints.bits.link_status) {
21623859Sml29623 		if (bmsr.bits.link_status) {
21633859Sml29623 			soft_bmsr->bits.link_status = 1;
21643859Sml29623 		} else {
21653859Sml29623 			statsp->mac_stats.link_up = 0;
21663859Sml29623 			soft_bmsr->bits.link_status = 0;
21673859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21683859Sml29623 					"Link down cable problem"));
21693859Sml29623 			*link_up = LINK_IS_DOWN;
21703859Sml29623 		}
21713859Sml29623 	}
21723859Sml29623 
21733859Sml29623 	if (param_arr[param_autoneg].value) {
21743859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
21753859Sml29623 			if (bmsr.bits.auto_neg_complete)
21763859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
21773859Sml29623 			else
21783859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
21793859Sml29623 		}
21803859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
21813859Sml29623 			statsp->mac_stats.link_T4 = 0;
21823859Sml29623 			statsp->mac_stats.link_speed = 0;
21833859Sml29623 			statsp->mac_stats.link_duplex = 0;
21843859Sml29623 			statsp->mac_stats.link_asmpause = 0;
21853859Sml29623 			statsp->mac_stats.link_pause = 0;
21863859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
21873859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
21883859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
21893859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
21903859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
21913859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
21923859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
21933859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
21943859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
21953859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
21963859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
21973859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
21983859Sml29623 		}
21993859Sml29623 	} else
22003859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
22013859Sml29623 
22023859Sml29623 	if ((bmsr_ints.bits.link_status ||
22033859Sml29623 		bmsr_ints.bits.auto_neg_complete) &&
22043859Sml29623 		soft_bmsr->bits.link_status &&
22053859Sml29623 		soft_bmsr->bits.auto_neg_complete) {
22063859Sml29623 		statsp->mac_stats.link_up = 1;
22073859Sml29623 		if (param_arr[param_autoneg].value) {
22083859Sml29623 			if ((status = nxge_mii_read(nxgep,
22093859Sml29623 				statsp->mac_stats.xcvr_portn,
22103859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anar),
22113859Sml29623 					&anar.value)) != NXGE_OK)
22123859Sml29623 				goto fail;
22133859Sml29623 			if ((status = nxge_mii_read(nxgep,
22143859Sml29623 				statsp->mac_stats.xcvr_portn,
22153859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
22163859Sml29623 					&anlpar.value)) != NXGE_OK)
22173859Sml29623 				goto fail;
22183859Sml29623 			if ((status = nxge_mii_read(nxgep,
22193859Sml29623 				statsp->mac_stats.xcvr_portn,
22203859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->aner),
22213859Sml29623 					&aner.value)) != NXGE_OK)
22223859Sml29623 				goto fail;
22233859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
22243859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
22253859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
22263859Sml29623 							anlpar.bits.cap_100fdx;
22273859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
22283859Sml29623 							anlpar.bits.cap_100hdx;
22293859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
22303859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
22313859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
22323859Sml29623 						anlpar.bits.cap_asmpause;
22333859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
22343859Sml29623 			an_common.value = anar.value & anlpar.value;
22353859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
22363859Sml29623 				param_arr[param_anar_1000hdx].value) {
22373859Sml29623 				if ((status = nxge_mii_read(nxgep,
22383859Sml29623 					statsp->mac_stats.xcvr_portn,
22393859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gsr),
22403859Sml29623 						&gsr.value))
22413859Sml29623 						!= NXGE_OK)
22423859Sml29623 					goto fail;
22433859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
22443859Sml29623 					gsr.bits.link_1000fdx;
22453859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
22463859Sml29623 					gsr.bits.link_1000hdx;
22473859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
22483859Sml29623 					gsr.bits.link_1000fdx) {
22493859Sml29623 					statsp->mac_stats.link_speed = 1000;
22503859Sml29623 					statsp->mac_stats.link_duplex = 2;
22513859Sml29623 				} else if (
22523859Sml29623 					param_arr[param_anar_1000hdx].value &&
22533859Sml29623 						gsr.bits.link_1000hdx) {
22543859Sml29623 					statsp->mac_stats.link_speed = 1000;
22553859Sml29623 					statsp->mac_stats.link_duplex = 1;
22563859Sml29623 				}
22573859Sml29623 			}
22583859Sml29623 			if ((an_common.value != 0) &&
22593859Sml29623 					!(statsp->mac_stats.link_speed)) {
22603859Sml29623 				if (an_common.bits.cap_100T4) {
22613859Sml29623 					statsp->mac_stats.link_T4 = 1;
22623859Sml29623 					statsp->mac_stats.link_speed = 100;
22633859Sml29623 					statsp->mac_stats.link_duplex = 1;
22643859Sml29623 				} else if (an_common.bits.cap_100fdx) {
22653859Sml29623 					statsp->mac_stats.link_speed = 100;
22663859Sml29623 					statsp->mac_stats.link_duplex = 2;
22673859Sml29623 				} else if (an_common.bits.cap_100hdx) {
22683859Sml29623 					statsp->mac_stats.link_speed = 100;
22693859Sml29623 					statsp->mac_stats.link_duplex = 1;
22703859Sml29623 				} else if (an_common.bits.cap_10fdx) {
22713859Sml29623 					statsp->mac_stats.link_speed = 10;
22723859Sml29623 					statsp->mac_stats.link_duplex = 2;
22733859Sml29623 				} else if (an_common.bits.cap_10hdx) {
22743859Sml29623 					statsp->mac_stats.link_speed = 10;
22753859Sml29623 					statsp->mac_stats.link_duplex = 1;
22763859Sml29623 				} else {
22773859Sml29623 					goto fail;
22783859Sml29623 				}
22793859Sml29623 			}
22803859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
22813859Sml29623 				statsp->mac_stats.link_asmpause =
22823859Sml29623 					an_common.bits.cap_asmpause;
22833859Sml29623 				if (statsp->mac_stats.link_asmpause)
22843859Sml29623 				if ((statsp->mac_stats.cap_pause == 0) &&
22853859Sml29623 						(statsp->mac_stats.lp_cap_pause
22863859Sml29623 						== 1))
22873859Sml29623 						statsp->mac_stats.link_pause
22883859Sml29623 						= 0;
22893859Sml29623 					else
22903859Sml29623 						statsp->mac_stats.link_pause
22913859Sml29623 						= 1;
22923859Sml29623 				else
22933859Sml29623 					statsp->mac_stats.link_pause =
22943859Sml29623 						an_common.bits.cap_pause;
22953859Sml29623 			}
22963859Sml29623 		}
22973859Sml29623 		*link_up = LINK_IS_UP;
22983859Sml29623 	}
22993859Sml29623 
23003859Sml29623 	if (nxgep->link_notify) {
23013859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
23023859Sml29623 				LINK_IS_DOWN);
23033859Sml29623 		nxgep->link_notify = B_FALSE;
23043859Sml29623 	}
23053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
23063859Sml29623 	return (NXGE_OK);
23073859Sml29623 fail:
23083859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23093859Sml29623 			"nxge_mii_check: Unable to check MII"));
23103859Sml29623 	return (status);
23113859Sml29623 }
23123859Sml29623 
23133859Sml29623 /* Add a multicast address entry into the HW hash table */
23143859Sml29623 
23153859Sml29623 nxge_status_t
23163859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
23173859Sml29623 {
23183859Sml29623 	uint32_t mchash;
23193859Sml29623 	p_hash_filter_t hash_filter;
23203859Sml29623 	uint16_t hash_bit;
23213859Sml29623 	boolean_t rx_init = B_FALSE;
23223859Sml29623 	uint_t j;
23233859Sml29623 	nxge_status_t status = NXGE_OK;
23243859Sml29623 
23253859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
23263859Sml29623 
23273859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
23283859Sml29623 	mchash = crc32_mchash(addrp);
23293859Sml29623 	if (nxgep->hash_filter == NULL) {
23303859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
23313859Sml29623 			"Allocating hash filter storage."));
23323859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
23333859Sml29623 					KM_SLEEP);
23343859Sml29623 	}
23353859Sml29623 	hash_filter = nxgep->hash_filter;
23363859Sml29623 	j = mchash / HASH_REG_WIDTH;
23373859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
23383859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
23393859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
23403859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
23413859Sml29623 		hash_filter->hash_ref_cnt++;
23423859Sml29623 		rx_init = B_TRUE;
23433859Sml29623 	}
23443859Sml29623 	if (rx_init) {
23453859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
23463859Sml29623 			goto fail;
23473859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
23483859Sml29623 			goto fail;
23493859Sml29623 	}
23503859Sml29623 
23513859Sml29623 	RW_EXIT(&nxgep->filter_lock);
23523859Sml29623 
23533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
23543859Sml29623 
23553859Sml29623 	return (NXGE_OK);
23563859Sml29623 fail:
23573859Sml29623 	RW_EXIT(&nxgep->filter_lock);
23583859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
23593859Sml29623 					"Unable to add multicast address"));
23603859Sml29623 	return (status);
23613859Sml29623 }
23623859Sml29623 
23633859Sml29623 /* Remove a multicast address entry from the HW hash table */
23643859Sml29623 
23653859Sml29623 nxge_status_t
23663859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
23673859Sml29623 {
23683859Sml29623 	uint32_t mchash;
23693859Sml29623 	p_hash_filter_t hash_filter;
23703859Sml29623 	uint16_t hash_bit;
23713859Sml29623 	boolean_t rx_init = B_FALSE;
23723859Sml29623 	uint_t j;
23733859Sml29623 	nxge_status_t status = NXGE_OK;
23743859Sml29623 
23753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
23763859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
23773859Sml29623 	mchash = crc32_mchash(addrp);
23783859Sml29623 	if (nxgep->hash_filter == NULL) {
23793859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
23803859Sml29623 			"Hash filter already de_allocated."));
23813859Sml29623 		RW_EXIT(&nxgep->filter_lock);
23823859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
23833859Sml29623 		return (NXGE_OK);
23843859Sml29623 	}
23853859Sml29623 	hash_filter = nxgep->hash_filter;
23863859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
23873859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
23883859Sml29623 		j = mchash / HASH_REG_WIDTH;
23893859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
23903859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
23913859Sml29623 		hash_filter->hash_ref_cnt--;
23923859Sml29623 		rx_init = B_TRUE;
23933859Sml29623 	}
23943859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
23953859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
23963859Sml29623 			"De-allocating hash filter storage."));
23973859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
23983859Sml29623 		nxgep->hash_filter = NULL;
23993859Sml29623 	}
24003859Sml29623 
24013859Sml29623 	if (rx_init) {
24023859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
24033859Sml29623 			goto fail;
24043859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
24053859Sml29623 			goto fail;
24063859Sml29623 	}
24073859Sml29623 	RW_EXIT(&nxgep->filter_lock);
24083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
24093859Sml29623 
24103859Sml29623 	return (NXGE_OK);
24113859Sml29623 fail:
24123859Sml29623 	RW_EXIT(&nxgep->filter_lock);
24133859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
24143859Sml29623 			"Unable to remove multicast address"));
24153859Sml29623 
24163859Sml29623 	return (status);
24173859Sml29623 }
24183859Sml29623 
24193859Sml29623 /* Set MAC address into MAC address HW registers */
24203859Sml29623 
24213859Sml29623 nxge_status_t
24223859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
24233859Sml29623 {
24243859Sml29623 	nxge_status_t status = NXGE_OK;
24253859Sml29623 
24263859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
24273859Sml29623 
24283859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
24293859Sml29623 	/*
24303859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
24313859Sml29623 	 */
24323859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
24333859Sml29623 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
24343859Sml29623 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
24353859Sml29623 		goto nxge_set_mac_addr_exit;
24363859Sml29623 	}
24373859Sml29623 	nxgep->ouraddr = *addrp;
24383859Sml29623 	/*
24393859Sml29623 	 * Set new interface local address and re-init device.
24403859Sml29623 	 * This is destructive to any other streams attached
24413859Sml29623 	 * to this device.
24423859Sml29623 	 */
24433859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
24443859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
24453859Sml29623 		goto fail;
24463859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
24473859Sml29623 		goto fail;
24483859Sml29623 
24493859Sml29623 	RW_EXIT(&nxgep->filter_lock);
24503859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
24513859Sml29623 	goto nxge_set_mac_addr_end;
24523859Sml29623 nxge_set_mac_addr_exit:
24533859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
24543859Sml29623 nxge_set_mac_addr_end:
24553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
24563859Sml29623 
24573859Sml29623 	return (NXGE_OK);
24583859Sml29623 fail:
24593859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
24603859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
24613859Sml29623 			"Unable to set mac address"));
24623859Sml29623 	return (status);
24633859Sml29623 }
24643859Sml29623 
24653859Sml29623 /* Check status of MII (MIF or PCS) link */
24663859Sml29623 
24673859Sml29623 nxge_status_t
24683859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
24693859Sml29623 {
24703859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
24713859Sml29623 	mii_anlpar_t anlpar;
24723859Sml29623 	mii_gsr_t gsr;
24733859Sml29623 	p_mii_regs_t mii_regs;
24743859Sml29623 	nxge_status_t status = NXGE_OK;
24753859Sml29623 	uint8_t portn;
24763859Sml29623 	nxge_link_state_t link_up;
24773859Sml29623 
24783859Sml29623 	portn = nxgep->mac.portnum;
24793859Sml29623 
24803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
24813859Sml29623 				portn));
24823859Sml29623 
24833859Sml29623 	mii_regs = NULL;
24843859Sml29623 
24853859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
24863859Sml29623 
24873859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
24883859Sml29623 		goto nxge_check_mii_link_exit;
24893859Sml29623 
24903859Sml29623 	if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
24913859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
24923859Sml29623 		&bmsr_data.value)) != NXGE_OK)
24933859Sml29623 		goto fail;
24943859Sml29623 
24953859Sml29623 	if (nxgep->param_arr[param_autoneg].value) {
24963859Sml29623 		if ((status = nxge_mii_read(nxgep,
24973859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn,
24983859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->gsr),
24993859Sml29623 			&gsr.value)) != NXGE_OK)
25003859Sml29623 			goto fail;
25013859Sml29623 		if ((status = nxge_mii_read(nxgep,
25023859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn,
25033859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anlpar),
25043859Sml29623 			&anlpar.value)) != NXGE_OK)
25053859Sml29623 			goto fail;
25063859Sml29623 		if (nxgep->statsp->mac_stats.link_up &&
25073859Sml29623 			((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
25083859Sml29623 				gsr.bits.link_1000fdx) ||
25093859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
25103859Sml29623 				gsr.bits.link_1000hdx) ||
25113859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100T4 ^
25123859Sml29623 				anlpar.bits.cap_100T4) ||
25133859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100fdx ^
25143859Sml29623 				anlpar.bits.cap_100fdx) ||
25153859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100hdx ^
25163859Sml29623 				anlpar.bits.cap_100hdx) ||
25173859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_10fdx ^
25183859Sml29623 				anlpar.bits.cap_10fdx) ||
25193859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_10hdx ^
25203859Sml29623 				anlpar.bits.cap_10hdx))) {
25213859Sml29623 			bmsr_data.bits.link_status = 0;
25223859Sml29623 		}
25233859Sml29623 	}
25243859Sml29623 
25253859Sml29623 	/* Workaround for link down issue */
25263859Sml29623 	if (bmsr_data.value == 0) {
25273859Sml29623 		cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
25283859Sml29623 		goto nxge_check_mii_link_exit;
25293859Sml29623 	}
25303859Sml29623 
25313859Sml29623 	bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
25323859Sml29623 	nxgep->bmsr.value = bmsr_data.value;
25333859Sml29623 	if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up))
25343859Sml29623 			!= NXGE_OK)
25353859Sml29623 		goto fail;
25363859Sml29623 
25373859Sml29623 nxge_check_mii_link_exit:
25383859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25393859Sml29623 	if (link_up == LINK_IS_UP) {
25403859Sml29623 		nxge_link_is_up(nxgep);
25413859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
25423859Sml29623 		nxge_link_is_down(nxgep);
25433859Sml29623 	}
25443859Sml29623 
25453859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
25463859Sml29623 
25473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
25483859Sml29623 				portn));
25493859Sml29623 	return (NXGE_OK);
25503859Sml29623 
25513859Sml29623 fail:
25523859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25533859Sml29623 
25543859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
25553859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
25563859Sml29623 			"nxge_check_mii_link: Failed to check link port<%d>",
25573859Sml29623 			portn));
25583859Sml29623 	return (status);
25593859Sml29623 }
25603859Sml29623 
25613859Sml29623 
25623859Sml29623 /*ARGSUSED*/
25633859Sml29623 nxge_status_t
25643859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
25653859Sml29623 {
25663859Sml29623 	uint8_t		portn;
25673859Sml29623 
25683859Sml29623 	nxge_status_t	status = NXGE_OK;
25693859Sml29623 	boolean_t	link_up;
25703859Sml29623 
25713859Sml29623 	portn = nxgep->mac.portnum;
25723859Sml29623 
25733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
25743859Sml29623 				portn));
25753859Sml29623 
25763859Sml29623 	status = nxge_check_bcm8704_link(nxgep, &link_up);
25773859Sml29623 
25783859Sml29623 	if (status != NXGE_OK)
25793859Sml29623 		goto fail;
25803859Sml29623 
25813859Sml29623 	if (link_up) {
25823859Sml29623 		if (nxgep->link_notify ||
25833859Sml29623 			nxgep->statsp->mac_stats.link_up == 0) {
25843859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
25853859Sml29623 				goto fail;
25863859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
25873859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
25883859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
25893859Sml29623 
25903859Sml29623 			nxge_link_is_up(nxgep);
25913859Sml29623 			nxgep->link_notify = B_FALSE;
25923859Sml29623 		}
25933859Sml29623 	} else {
25943859Sml29623 		if (nxgep->link_notify ||
25953859Sml29623 			nxgep->statsp->mac_stats.link_up == 1) {
25963859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
25973859Sml29623 				goto fail;
25983859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
25993859Sml29623 					"Link down cable problem"));
26003859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
26013859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
26023859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
26033859Sml29623 
26043859Sml29623 			nxge_link_is_down(nxgep);
26053859Sml29623 			nxgep->link_notify = B_FALSE;
26063859Sml29623 		}
26073859Sml29623 	}
26083859Sml29623 
26093859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
26103859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
26113859Sml29623 				portn));
26123859Sml29623 	return (NXGE_OK);
26133859Sml29623 
26143859Sml29623 fail:
26153859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26163859Sml29623 			"nxge_check_10g_link: Failed to check link port<%d>",
26173859Sml29623 			portn));
26183859Sml29623 	return (status);
26193859Sml29623 }
26203859Sml29623 
26213859Sml29623 
26223859Sml29623 /* Declare link down */
26233859Sml29623 
26243859Sml29623 void
26253859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
26263859Sml29623 {
26273859Sml29623 	p_nxge_stats_t statsp;
26283859Sml29623 	char link_stat_msg[64];
26293859Sml29623 
26303859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
26313859Sml29623 
26323859Sml29623 	statsp = nxgep->statsp;
2633*4185Sspeer 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
26343859Sml29623 			statsp->mac_stats.xcvr_portn);
26353859Sml29623 
2636*4185Sspeer 	if (nxge_no_msg == B_FALSE) {
2637*4185Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2638*4185Sspeer 	}
2639*4185Sspeer 
26403859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
26413859Sml29623 
26423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
26433859Sml29623 }
26443859Sml29623 
26453859Sml29623 /* Declare link up */
26463859Sml29623 
26473859Sml29623 void
26483859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
26493859Sml29623 {
26503859Sml29623 	p_nxge_stats_t statsp;
26513859Sml29623 	char link_stat_msg[64];
26523859Sml29623 	uint32_t val;
26533859Sml29623 
26543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
26553859Sml29623 
26563859Sml29623 	statsp = nxgep->statsp;
2657*4185Sspeer 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
26583859Sml29623 				statsp->mac_stats.xcvr_portn,
26593859Sml29623 				statsp->mac_stats.link_speed);
26603859Sml29623 
26613859Sml29623 	if (statsp->mac_stats.link_T4)
26623859Sml29623 		(void) strcat(link_stat_msg, "T4");
26633859Sml29623 	else if (statsp->mac_stats.link_duplex == 2)
26643859Sml29623 		(void) strcat(link_stat_msg, "full duplex");
26653859Sml29623 	else
26663859Sml29623 		(void) strcat(link_stat_msg, "half duplex");
26673859Sml29623 
26683859Sml29623 	(void) nxge_xif_init(nxgep);
26693859Sml29623 
26703859Sml29623 	/* Clean up symbol errors incurred during link transition */
26713859Sml29623 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
26723859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
26733859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
26743859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
26753859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
26763859Sml29623 	}
26773859Sml29623 
2678*4185Sspeer 	if (nxge_no_msg == B_FALSE) {
2679*4185Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2680*4185Sspeer 	}
2681*4185Sspeer 
26823859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
26833859Sml29623 
26843859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
26853859Sml29623 }
26863859Sml29623 
26873859Sml29623 /*
26883859Sml29623  * Calculate the bit in the multicast address filter
26893859Sml29623  * that selects the given * address.
26903859Sml29623  * Note: For GEM, the last 8-bits are used.
26913859Sml29623  */
26923859Sml29623 uint32_t
26933859Sml29623 crc32_mchash(p_ether_addr_t addr)
26943859Sml29623 {
26953859Sml29623 	uint8_t *cp;
26963859Sml29623 	uint32_t crc;
26973859Sml29623 	uint32_t c;
26983859Sml29623 	int byte;
26993859Sml29623 	int bit;
27003859Sml29623 
27013859Sml29623 	cp = (uint8_t *)addr;
27023859Sml29623 	crc = (uint32_t)0xffffffff;
27033859Sml29623 	for (byte = 0; byte < 6; byte++) {
27043859Sml29623 		c = (uint32_t)cp[byte];
27053859Sml29623 		for (bit = 0; bit < 8; bit++) {
27063859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
27073859Sml29623 				crc = (crc >> 1)^0xedb88320;
27083859Sml29623 			else
27093859Sml29623 				crc = (crc >> 1);
27103859Sml29623 			c >>= 1;
27113859Sml29623 		}
27123859Sml29623 	}
27133859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
27143859Sml29623 }
27153859Sml29623 
27163859Sml29623 /* Reset serdes */
27173859Sml29623 
27183859Sml29623 nxge_status_t
27193859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
27203859Sml29623 {
27213859Sml29623 	npi_handle_t		handle;
27223859Sml29623 
27233859Sml29623 	handle = nxgep->npi_handle;
27243859Sml29623 
27253859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
27263859Sml29623 	drv_usecwait(500);
27273859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
27283859Sml29623 
27293859Sml29623 	return (NXGE_OK);
27303859Sml29623 }
27313859Sml29623 
27323859Sml29623 /* Monitor link status using interrupt or polling */
27333859Sml29623 
27343859Sml29623 nxge_status_t
27353859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
27363859Sml29623 {
27373859Sml29623 	nxge_status_t status = NXGE_OK;
27383859Sml29623 
27393859Sml29623 	/*
27403859Sml29623 	 * Make sure that we don't check the link if this happen to
27413859Sml29623 	 * be not port0 or 1 and it is not BMAC port.
27423859Sml29623 	 */
27433859Sml29623 	if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
27443859Sml29623 		return (NXGE_OK);
27453859Sml29623 
27463859Sml29623 	if (nxgep->statsp == NULL) {
27473859Sml29623 		/* stats has not been allocated. */
27483859Sml29623 		return (NXGE_OK);
27493859Sml29623 	}
27503859Sml29623 	/* Don't check link if we're not in internal loopback mode */
27513859Sml29623 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
27523859Sml29623 		return (NXGE_OK);
27533859Sml29623 
27543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
27553859Sml29623 			"==> nxge_link_monitor port<%d> enable=%d",
27563859Sml29623 			nxgep->mac.portnum, enable));
27573859Sml29623 	if (enable == LINK_MONITOR_START) {
27583859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
27593859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
27603859Sml29623 							!= NXGE_OK)
27613859Sml29623 				goto fail;
27623859Sml29623 		} else {
27633859Sml29623 			switch (nxgep->mac.portmode) {
27643859Sml29623 			case PORT_10G_FIBER:
27653859Sml29623 				nxgep->nxge_link_poll_timerid = timeout(
27663859Sml29623 						(fptrv_t)nxge_check_10g_link,
27673859Sml29623 						nxgep,
27683859Sml29623 						drv_usectohz(1000 * 1000));
27693859Sml29623 			break;
27703859Sml29623 
27713859Sml29623 			case PORT_1G_COPPER:
27723859Sml29623 			case PORT_1G_FIBER:
27733859Sml29623 				nxgep->nxge_link_poll_timerid = timeout(
27743859Sml29623 						(fptrv_t)nxge_check_mii_link,
27753859Sml29623 						nxgep,
27763859Sml29623 						drv_usectohz(1000 * 1000));
27773859Sml29623 			break;
27783859Sml29623 			default:
27793859Sml29623 				;
27803859Sml29623 			}
27813859Sml29623 		}
27823859Sml29623 	} else {
27833859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
27843859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
27853859Sml29623 							!= NXGE_OK)
27863859Sml29623 				goto fail;
27873859Sml29623 		} else {
27883859Sml29623 			if (nxgep->nxge_link_poll_timerid != 0) {
27893859Sml29623 				(void) untimeout(nxgep->nxge_link_poll_timerid);
27903859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
27913859Sml29623 			}
27923859Sml29623 		}
27933859Sml29623 	}
27943859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
27953859Sml29623 			"<== nxge_link_monitor port<%d> enable=%d",
27963859Sml29623 			nxgep->mac.portnum, enable));
27973859Sml29623 	return (NXGE_OK);
27983859Sml29623 fail:
27993859Sml29623 	return (status);
28003859Sml29623 }
28013859Sml29623 
28023859Sml29623 /* Set promiscous mode */
28033859Sml29623 
28043859Sml29623 nxge_status_t
28053859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
28063859Sml29623 {
28073859Sml29623 	nxge_status_t status = NXGE_OK;
28083859Sml29623 
28093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
28103859Sml29623 		"==> nxge_set_promisc: on %d", on));
28113859Sml29623 
28123859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
28133859Sml29623 
28143859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
28153859Sml29623 
28163859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
28173859Sml29623 		goto fail;
28183859Sml29623 	}
28193859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
28203859Sml29623 		goto fail;
28213859Sml29623 	}
28223859Sml29623 
28233859Sml29623 	RW_EXIT(&nxgep->filter_lock);
28243859Sml29623 
28253859Sml29623 	if (on)
28263859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
28273859Sml29623 	else
28283859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
28293859Sml29623 
28303859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
28313859Sml29623 
28323859Sml29623 	return (NXGE_OK);
28333859Sml29623 fail:
28343859Sml29623 	RW_EXIT(&nxgep->filter_lock);
28353859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
28363859Sml29623 			"Unable to set promisc (%d)", on));
28373859Sml29623 
28383859Sml29623 	return (status);
28393859Sml29623 }
28403859Sml29623 
28413859Sml29623 /*ARGSUSED*/
28423859Sml29623 uint_t
28433859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
28443859Sml29623 {
28453859Sml29623 #ifdef	NXGE_DEBUG
28463859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
28473859Sml29623 #endif
28483859Sml29623 #if NXGE_MIF
28493859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
28503859Sml29623 	uint32_t		status;
28513859Sml29623 	npi_handle_t		handle;
28523859Sml29623 	uint8_t			portn;
28533859Sml29623 	p_nxge_stats_t		statsp;
28543859Sml29623 #endif
28553859Sml29623 
28563859Sml29623 #ifdef	NXGE_MIF
28573859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
28583859Sml29623 		nxgep = ldvp->nxgep;
28593859Sml29623 	}
28603859Sml29623 	nxgep = ldvp->nxgep;
28613859Sml29623 #endif
28623859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
28633859Sml29623 
28643859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
28653859Sml29623 	return (DDI_INTR_CLAIMED);
28663859Sml29623 
28673859Sml29623 mif_intr_fail:
28683859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
28693859Sml29623 	return (DDI_INTR_UNCLAIMED);
28703859Sml29623 }
28713859Sml29623 
28723859Sml29623 /*ARGSUSED*/
28733859Sml29623 uint_t
28743859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
28753859Sml29623 {
28763859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
28773859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
28783859Sml29623 	p_nxge_ldg_t		ldgp;
28793859Sml29623 	uint32_t		status;
28803859Sml29623 	npi_handle_t		handle;
28813859Sml29623 	uint8_t			portn;
28823859Sml29623 	p_nxge_stats_t		statsp;
28833859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
28843859Sml29623 
28853859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
28863859Sml29623 		nxgep = ldvp->nxgep;
28873859Sml29623 	}
28883859Sml29623 
28893859Sml29623 	ldgp = ldvp->ldgp;
28903859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
28913859Sml29623 		"group %d", ldgp->ldg));
28923859Sml29623 
28933859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
28943859Sml29623 	/*
28953859Sml29623 	 * This interrupt handler is for a specific
28963859Sml29623 	 * mac port.
28973859Sml29623 	 */
28983859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
28993859Sml29623 	portn = nxgep->mac.portnum;
29003859Sml29623 
29013859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
29023859Sml29623 		"==> nxge_mac_intr: reading mac stats: port<%d>", portn));
29033859Sml29623 
29043859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
29053859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
29063859Sml29623 					(xmac_tx_iconfig_t *)&status);
29073859Sml29623 		if (rs != NPI_SUCCESS)
29083859Sml29623 			goto npi_fail;
29093859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
29103859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
29113859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
29123859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29133859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
29143859Sml29623 			}
29153859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
29163859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
29173859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29183859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
29193859Sml29623 			}
29203859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
29213859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
29223859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29233859Sml29623 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
29243859Sml29623 			}
29253859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
29263859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
29273859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29283859Sml29623 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
29293859Sml29623 			}
29303859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
29313859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
29323859Sml29623 							XTXMAC_BYTE_CNT_MASK;
29333859Sml29623 			}
29343859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
29353859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
29363859Sml29623 							XTXMAC_FRM_CNT_MASK;
29373859Sml29623 			}
29383859Sml29623 		}
29393859Sml29623 
29403859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
29413859Sml29623 					(xmac_rx_iconfig_t *)&status);
29423859Sml29623 		if (rs != NPI_SUCCESS)
29433859Sml29623 			goto npi_fail;
29443859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
29453859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
29463859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
29473859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
29483859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
29493859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29503859Sml29623 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
29513859Sml29623 			}
29523859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
29533859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
29543859Sml29623 							XRXMAC_CRC_ER_CNT_MASK;
29553859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29563859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
29573859Sml29623 			}
29583859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
29593859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
29603859Sml29623 							MAC_LEN_ER_CNT_MASK;
29613859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29623859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
29633859Sml29623 			}
29643859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
29653859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
29663859Sml29623 							XRXMAC_CD_VIO_CNT_MASK;
29673859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
29683859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
29693859Sml29623 			}
29703859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
29713859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
29723859Sml29623 							XRXMAC_BT_CNT_MASK;
29733859Sml29623 			}
29743859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
29753859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
29763859Sml29623 							XRXMAC_HIST_CNT1_MASK;
29773859Sml29623 			}
29783859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
29793859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
29803859Sml29623 							XRXMAC_HIST_CNT2_MASK;
29813859Sml29623 			}
29823859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
29833859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
29843859Sml29623 							XRXMAC_HIST_CNT3_MASK;
29853859Sml29623 			}
29863859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
29873859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
29883859Sml29623 							XRXMAC_HIST_CNT4_MASK;
29893859Sml29623 			}
29903859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
29913859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
29923859Sml29623 							XRXMAC_HIST_CNT5_MASK;
29933859Sml29623 			}
29943859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
29953859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
29963859Sml29623 							XRXMAC_HIST_CNT6_MASK;
29973859Sml29623 			}
29983859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
29993859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
30003859Sml29623 							XRXMAC_BC_FRM_CNT_MASK;
30013859Sml29623 			}
30023859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
30033859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
30043859Sml29623 							XRXMAC_MC_FRM_CNT_MASK;
30053859Sml29623 			}
30063859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
30073859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
30083859Sml29623 							XRXMAC_FRAG_CNT_MASK;
30093859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30103859Sml29623 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
30113859Sml29623 			}
30123859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
30133859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
30143859Sml29623 							XRXMAC_AL_ER_CNT_MASK;
30153859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30163859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
30173859Sml29623 			}
30183859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
30193859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
30203859Sml29623 							XMAC_LINK_FLT_CNT_MASK;
30213859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30223859Sml29623 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
30233859Sml29623 			}
30243859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
30253859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
30263859Sml29623 			}
30273859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
30283859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
30293859Sml29623 			}
30303859Sml29623 		}
30313859Sml29623 
30323859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
30333859Sml29623 						(xmac_ctl_iconfig_t *)&status);
30343859Sml29623 		if (rs != NPI_SUCCESS)
30353859Sml29623 			goto npi_fail;
30363859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
30373859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
30383859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
30393859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
30403859Sml29623 				statsp->xmac_stats.tx_pause_state++;
30413859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
30423859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
30433859Sml29623 		}
30443859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
30453859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
30463859Sml29623 						(bmac_tx_iconfig_t *)&status);
30473859Sml29623 		if (rs != NPI_SUCCESS)
30483859Sml29623 			goto npi_fail;
30493859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
30503859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
30513859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
30523859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30533859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
30543859Sml29623 			}
30553859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
30563859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
30573859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30583859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
30593859Sml29623 			}
30603859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
30613859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
30623859Sml29623 							BTXMAC_BYTE_CNT_MASK;
30633859Sml29623 			}
30643859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
30653859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
30663859Sml29623 							BTXMAC_FRM_CNT_MASK;
30673859Sml29623 			}
30683859Sml29623 		}
30693859Sml29623 
30703859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
30713859Sml29623 						(bmac_rx_iconfig_t *)&status);
30723859Sml29623 		if (rs != NPI_SUCCESS)
30733859Sml29623 			goto npi_fail;
30743859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
30753859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
30763859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
30773859Sml29623 			}
30783859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
30793859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
30803859Sml29623 							RXMAC_FRM_CNT_MASK;
30813859Sml29623 			}
30823859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
30833859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
30843859Sml29623 							BMAC_CRC_ER_CNT_MASK;
30853859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30863859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
30873859Sml29623 			}
30883859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
30893859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
30903859Sml29623 							MAC_LEN_ER_CNT_MASK;
30913859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30923859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
30933859Sml29623 			}
30943859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
30953859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
30963859Sml29623 							BMAC_CD_VIO_CNT_MASK;
30973859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
30983859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
30993859Sml29623 			}
31003859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
31013859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
31023859Sml29623 							BRXMAC_BYTE_CNT_MASK;
31033859Sml29623 			}
31043859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
31053859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
31063859Sml29623 							BMAC_AL_ER_CNT_MASK;
31073859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31083859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
31093859Sml29623 			}
31103859Sml29623 
31113859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
31123859Sml29623 						(bmac_ctl_iconfig_t *)&status);
31133859Sml29623 			if (rs != NPI_SUCCESS)
31143859Sml29623 				goto npi_fail;
31153859Sml29623 
31163859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
31173859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
31183859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
31193859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
31203859Sml29623 					statsp->bmac_stats.tx_pause_state++;
31213859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
31223859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
31233859Sml29623 			}
31243859Sml29623 		}
31253859Sml29623 
31263859Sml29623 	if (ldgp->nldvs == 1) {
31273859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
31283859Sml29623 			B_TRUE, ldgp->ldg_timer);
31293859Sml29623 	}
31303859Sml29623 
31313859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
31323859Sml29623 	return (DDI_INTR_CLAIMED);
31333859Sml29623 
31343859Sml29623 npi_fail:
31353859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
31363859Sml29623 	return (DDI_INTR_UNCLAIMED);
31373859Sml29623 }
31383859Sml29623 
31393859Sml29623 nxge_status_t
31403859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
31413859Sml29623 {
31423859Sml29623 	uint8_t		phy_port_addr;
31433859Sml29623 	nxge_status_t	status = NXGE_OK;
31443859Sml29623 	boolean_t	rx_sig_ok;
31453859Sml29623 	boolean_t	pcs_blk_lock;
31463859Sml29623 	boolean_t	link_align;
31473859Sml29623 	uint16_t	val1, val2, val3;
31483859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
31493859Sml29623 	uint16_t	val_debug;
31503859Sml29623 	uint16_t	val;
31513859Sml29623 #endif
31523859Sml29623 
31533859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
31543859Sml29623 
31553859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
31563859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
31573859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
31583859Sml29623 	if ((val_debug & ~0x200) != 0) {
31593859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
31603859Sml29623 				nxgep->mac.portnum, val_debug);
31613859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
31623859Sml29623 				&val_debug);
31633859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
31643859Sml29623 				nxgep->mac.portnum, val_debug);
31653859Sml29623 	}
31663859Sml29623 
31673859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
31683859Sml29623 					XPCS_REG_DESCWERR_COUNTER, &val);
31693859Sml29623 	if (val != 0)
31703859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
31713859Sml29623 
31723859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
31733859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
31743859Sml29623 	if (val != 0)
31753859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
31763859Sml29623 
31773859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
31783859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
31793859Sml29623 	if (val != 0)
31803859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
31813859Sml29623 #endif
31823859Sml29623 
31833859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
31843859Sml29623 
31853859Sml29623 	/* Check Device 1 Register 0xA bit0 */
31863859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
31873859Sml29623 			BCM8704_PMA_PMD_DEV_ADDR,
31883859Sml29623 			BCM8704_PMD_RECEIVE_SIG_DETECT,
31893859Sml29623 			&val1);
31903859Sml29623 	if (status != NXGE_OK)
31913859Sml29623 		goto fail;
31923859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
31933859Sml29623 
31943859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
31953859Sml29623 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
31963859Sml29623 			BCM8704_PCS_DEV_ADDR,
31973859Sml29623 			BCM8704_10GBASE_R_PCS_STATUS_REG,
31983859Sml29623 			&val2)) != NPI_SUCCESS)
31993859Sml29623 		goto fail;
32003859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
32013859Sml29623 
32023859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
32033859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
32043859Sml29623 			BCM8704_PHYXS_ADDR,
32053859Sml29623 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
32063859Sml29623 			&val3);
32073859Sml29623 	if (status != NXGE_OK)
32083859Sml29623 		goto fail;
32093859Sml29623 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
32103859Sml29623 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
32113859Sml29623 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
32123859Sml29623 
32133859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
32143859Sml29623 	/* Temp workaround for link down issue */
32153859Sml29623 	if (pcs_blk_lock == B_FALSE) {
32163859Sml29623 		if (val2 != 0x4) {
32173859Sml29623 			pcs_blk_lock = B_TRUE;
32183859Sml29623 			cmn_err(CE_NOTE,
32193859Sml29623 				"!LINK DEBUG: port%d PHY Dev3 "
32203859Sml29623 				"Reg 0x20 = 0x%x\n",
32213859Sml29623 				nxgep->mac.portnum, val2);
32223859Sml29623 		}
32233859Sml29623 	}
32243859Sml29623 
32253859Sml29623 	if (link_align == B_FALSE) {
32263859Sml29623 		if (val3 != 0x140f) {
32273859Sml29623 			link_align = B_TRUE;
32283859Sml29623 			cmn_err(CE_NOTE,
32293859Sml29623 				"!LINK DEBUG: port%d PHY Dev4 "
32303859Sml29623 				"Reg 0x18 = 0x%x\n",
32313859Sml29623 				nxgep->mac.portnum, val3);
32323859Sml29623 		}
32333859Sml29623 	}
32343859Sml29623 
32353859Sml29623 	if (rx_sig_ok == B_FALSE) {
32363859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
32373859Sml29623 			rx_sig_ok = B_TRUE;
32383859Sml29623 			cmn_err(CE_NOTE,
32393859Sml29623 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
32403859Sml29623 				nxgep->mac.portnum);
32413859Sml29623 		}
32423859Sml29623 	}
32433859Sml29623 #endif
32443859Sml29623 
32453859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
32463859Sml29623 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
32473859Sml29623 
32483859Sml29623 	return (NXGE_OK);
32493859Sml29623 fail:
32503859Sml29623 	return (status);
32513859Sml29623 }
32523859Sml29623 
32533859Sml29623 
32543859Sml29623 nxge_status_t
32553859Sml29623 nxge_get_xcvr_type(p_nxge_t nxgep)
32563859Sml29623 {
32573859Sml29623 	nxge_status_t status = NXGE_OK;
3258*4185Sspeer 	char *phy_type;
32593859Sml29623 	char *prop_val;
32603859Sml29623 
3261*4185Sspeer 	if (nxgep->niu_type == N2_NIU) {
3262*4185Sspeer 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
3263*4185Sspeer 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
3264*4185Sspeer 			if (strcmp("xgf", prop_val) == 0) {
3265*4185Sspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
3266*4185Sspeer 				    XPCS_XCVR;
3267*4185Sspeer 				nxgep->mac.portmode = PORT_10G_FIBER;
3268*4185Sspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3269*4185Sspeer 				    "10G Fiber Xcvr"));
3270*4185Sspeer 			} else if (strcmp("mif", prop_val) == 0) {
3271*4185Sspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
3272*4185Sspeer 				    INT_MII_XCVR;
3273*4185Sspeer 				nxgep->mac.portmode = PORT_1G_COPPER;
3274*4185Sspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3275*4185Sspeer 				    "1G Copper Xcvr"));
3276*4185Sspeer 			} else if (strcmp("pcs", prop_val) == 0) {
3277*4185Sspeer 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3278*4185Sspeer 				nxgep->mac.portmode = PORT_1G_FIBER;
3279*4185Sspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3280*4185Sspeer 				    "1G Fiber Xcvr"));
3281*4185Sspeer 			} else if (strcmp("xgc", prop_val) == 0) {
3282*4185Sspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
3283*4185Sspeer 				    XPCS_XCVR;
3284*4185Sspeer 				nxgep->mac.portmode = PORT_10G_COPPER;
3285*4185Sspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3286*4185Sspeer 				    "10G Copper Xcvr"));
3287*4185Sspeer 			} else {
3288*4185Sspeer 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3289*4185Sspeer 				    "Unknown phy-type: %s", prop_val));
3290*4185Sspeer 				ddi_prop_free(prop_val);
3291*4185Sspeer 				return (NXGE_ERROR);
3292*4185Sspeer 			}
3293*4185Sspeer 			status = NXGE_OK;
3294*4185Sspeer 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
3295*4185Sspeer 			    nxgep->dip, "phy-type", prop_val);
3296*4185Sspeer 			ddi_prop_free(prop_val);
3297*4185Sspeer 			return (status);
32983859Sml29623 		} else {
32993859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3300*4185Sspeer 			    "Exiting...phy-type property not found"));
33013859Sml29623 			return (NXGE_ERROR);
33023859Sml29623 		}
33033859Sml29623 	}
3304*4185Sspeer 
3305*4185Sspeer 	if (!nxgep->vpd_info.ver_valid) {
3306*4185Sspeer 		/*
3307*4185Sspeer 		 * read the phy type from the SEEPROM - NCR registers
3308*4185Sspeer 		 */
3309*4185Sspeer 		status = nxge_espc_phy_type_get(nxgep);
3310*4185Sspeer 		if (status != NXGE_OK)
3311*4185Sspeer 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3312*4185Sspeer 			    "[%s] invalid...please update",
3313*4185Sspeer 			    nxgep->vpd_info.ver));
3314*4185Sspeer 		return (status);
3315*4185Sspeer 	}
3316*4185Sspeer 
3317*4185Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3318*4185Sspeer 	    "Reading phy type from expansion ROM"));
3319*4185Sspeer 	/*
3320*4185Sspeer 	 * Try to read the phy type from the vpd data read off the
3321*4185Sspeer 	 * expansion ROM.
3322*4185Sspeer 	 */
3323*4185Sspeer 	phy_type = nxgep->vpd_info.phy_type;
3324*4185Sspeer 	if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') {
3325*4185Sspeer 		nxgep->mac.portmode = PORT_1G_COPPER;
3326*4185Sspeer 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3327*4185Sspeer 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
3328*4185Sspeer 	    phy_type[2] == 'f') {
3329*4185Sspeer 		nxgep->mac.portmode = PORT_10G_FIBER;
3330*4185Sspeer 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3331*4185Sspeer 	} else if (phy_type[0] == 'p' && phy_type[1] == 'c' &&
3332*4185Sspeer 	    phy_type[2] == 's') {
3333*4185Sspeer 		nxgep->mac.portmode = PORT_1G_FIBER;
3334*4185Sspeer 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3335*4185Sspeer 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
3336*4185Sspeer 	    phy_type[2] == 'c') {
3337*4185Sspeer 		nxgep->mac.portmode = PORT_10G_COPPER;
3338*4185Sspeer 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3339*4185Sspeer 	} else {
3340*4185Sspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3341*4185Sspeer 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
3342*4185Sspeer 		    phy_type[0], phy_type[1], phy_type[2]));
3343*4185Sspeer 		/*
3344*4185Sspeer 		 * read the phy type from the SEEPROM - NCR registers
3345*4185Sspeer 		 */
3346*4185Sspeer 		status = nxge_espc_phy_type_get(nxgep);
3347*4185Sspeer 		if (status != NXGE_OK)
3348*4185Sspeer 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
3349*4185Sspeer 			    "[%s] invalid...please update",
3350*4185Sspeer 			    nxgep->vpd_info.ver));
3351*4185Sspeer 	}
33523859Sml29623 
33533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
33543859Sml29623 	return (status);
33553859Sml29623 }
33563859Sml29623 
33573859Sml29623 nxge_status_t
33583859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
33593859Sml29623 {
33603859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
33613859Sml29623 							!= NPI_SUCCESS)
33623859Sml29623 		return (NXGE_ERROR);
33633859Sml29623 	else
33643859Sml29623 		return (NXGE_OK);
33653859Sml29623 }
33663859Sml29623 
33673859Sml29623 nxge_status_t
33683859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
33693859Sml29623 {
33703859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
33713859Sml29623 							!= NPI_SUCCESS)
33723859Sml29623 		return (NXGE_ERROR);
33733859Sml29623 	else
33743859Sml29623 		return (NXGE_OK);
33753859Sml29623 }
3376*4185Sspeer 
3377*4185Sspeer boolean_t
3378*4185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
3379*4185Sspeer {
3380*4185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
3381*4185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
3382*4185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
3383*4185Sspeer 		return (B_FALSE);
3384*4185Sspeer 	else
3385*4185Sspeer 		return (B_TRUE);
3386*4185Sspeer }
3387