xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 98ecde52)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
22a3c5bd6dSspeer  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish #include <sys/nxge/nxge_impl.h>
2944961713Sgirish #include <sys/nxge/nxge_mac.h>
3044961713Sgirish 
31*98ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
32*98ecde52Stm #define	LM_WAIT_MULTIPLIER	8
33*98ecde52Stm 
3444961713Sgirish extern uint32_t nxge_no_link_notify;
3544961713Sgirish extern uint32_t nxge_lb_dbg;
3644961713Sgirish extern nxge_os_mutex_t	nxge_mdio_lock;
3744961713Sgirish extern nxge_os_mutex_t	nxge_mii_lock;
3844961713Sgirish extern boolean_t nxge_jumbo_enable;
3944961713Sgirish 
40*98ecde52Stm typedef enum {
41*98ecde52Stm 	CHECK_LINK_RESCHEDULE,
42*98ecde52Stm 	CHECK_LINK_STOP
43*98ecde52Stm } check_link_state_t;
44*98ecde52Stm 
45*98ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
46*98ecde52Stm 
4744961713Sgirish /*
4844961713Sgirish  * Ethernet broadcast address definition.
4944961713Sgirish  */
5044961713Sgirish static ether_addr_st etherbroadcastaddr =
5144961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
5256d930aeSspeer static ether_addr_st etherzeroaddr =
5356d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
5444961713Sgirish 
5544961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t);
5644961713Sgirish 
5744961713Sgirish /* Initialize the entire MAC and physical layer */
5844961713Sgirish 
5944961713Sgirish nxge_status_t
6044961713Sgirish nxge_mac_init(p_nxge_t nxgep)
6144961713Sgirish {
6244961713Sgirish 	uint8_t			portn;
6344961713Sgirish 	nxge_status_t		status = NXGE_OK;
6444961713Sgirish 
6544961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6644961713Sgirish 
6744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
6844961713Sgirish 
6944961713Sgirish 	nxgep->mac.portnum = portn;
7044961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
7144961713Sgirish 
7244961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
7344961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
7444961713Sgirish 
7544961713Sgirish 	/* Initialize XIF to configure a network mode */
7644961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
7744961713Sgirish 		goto fail;
7844961713Sgirish 	}
7944961713Sgirish 
8044961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
8144961713Sgirish 		goto fail;
8244961713Sgirish 	}
8344961713Sgirish 
8444961713Sgirish 	/* Initialize TX and RX MACs */
8544961713Sgirish 	/*
8644961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
8744961713Sgirish 	 */
8844961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
8944961713Sgirish 		goto fail;
9044961713Sgirish 
9144961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
9244961713Sgirish 		goto fail;
9344961713Sgirish 
9444961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
9544961713Sgirish 		goto fail;
9644961713Sgirish 
9744961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
9844961713Sgirish 		goto fail;
9944961713Sgirish 
10044961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
10144961713Sgirish 		goto fail;
10244961713Sgirish 
10344961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
10444961713Sgirish 		goto fail;
10544961713Sgirish 
10644961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
10744961713Sgirish 
10844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
10944961713Sgirish 
11044961713Sgirish 	return (NXGE_OK);
11144961713Sgirish fail:
11244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11344961713Sgirish 			"nxge_mac_init: failed to initialize MAC port<%d>",
11444961713Sgirish 			portn));
11544961713Sgirish 	return (status);
11644961713Sgirish }
11744961713Sgirish 
11844961713Sgirish /* Initialize the Ethernet Link */
11944961713Sgirish 
12044961713Sgirish nxge_status_t
12144961713Sgirish nxge_link_init(p_nxge_t nxgep)
12244961713Sgirish {
12344961713Sgirish 	nxge_status_t		status = NXGE_OK;
12444961713Sgirish #ifdef	NXGE_DEBUG
12544961713Sgirish 	uint8_t			portn;
12644961713Sgirish 
12744961713Sgirish 	portn = nxgep->mac.portnum;
12844961713Sgirish 
12944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
13044961713Sgirish #endif
13144961713Sgirish 
13244961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
13344961713Sgirish 		/* Workaround to get link up in both NIU ports */
13444961713Sgirish 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
13544961713Sgirish 			goto fail;
13644961713Sgirish 	}
13744961713Sgirish 	NXGE_DELAY(200000);
13844961713Sgirish 	/* Initialize internal serdes */
13944961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
14044961713Sgirish 		goto fail;
14144961713Sgirish 	NXGE_DELAY(200000);
14244961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
14344961713Sgirish 		goto fail;
14444961713Sgirish 
14544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
14644961713Sgirish 
14744961713Sgirish 	return (NXGE_OK);
14844961713Sgirish 
14944961713Sgirish fail:
15044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15144961713Sgirish 		"nxge_link_init: ",
15244961713Sgirish 		"failed to initialize Ethernet link on port<%d>",
15344961713Sgirish 		portn));
15444961713Sgirish 
15544961713Sgirish 	return (status);
15644961713Sgirish }
15744961713Sgirish 
15844961713Sgirish 
15944961713Sgirish /* Initialize the XIF sub-block within the MAC */
16044961713Sgirish 
16144961713Sgirish nxge_status_t
16244961713Sgirish nxge_xif_init(p_nxge_t nxgep)
16344961713Sgirish {
16444961713Sgirish 	uint32_t		xif_cfg = 0;
16544961713Sgirish 	npi_attr_t		ap;
16644961713Sgirish 	uint8_t			portn;
16744961713Sgirish 	nxge_port_t		portt;
16844961713Sgirish 	nxge_port_mode_t	portmode;
16944961713Sgirish 	p_nxge_stats_t		statsp;
17044961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
17144961713Sgirish 	npi_handle_t		handle;
17244961713Sgirish 
17344961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
17444961713Sgirish 
17544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
17644961713Sgirish 
17744961713Sgirish 	handle = nxgep->npi_handle;
17844961713Sgirish 	portmode = nxgep->mac.portmode;
17944961713Sgirish 	portt = nxgep->mac.porttype;
18044961713Sgirish 	statsp = nxgep->statsp;
18144961713Sgirish 
18244961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
18344961713Sgirish 
18444961713Sgirish 		/* Setup XIF Configuration for XMAC */
18544961713Sgirish 
18644961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
18744961713Sgirish 					(portmode == PORT_10G_COPPER))
18844961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
18944961713Sgirish 
19044961713Sgirish 		if (portmode == PORT_1G_COPPER) {
19144961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
19244961713Sgirish 		}
19344961713Sgirish 
19444961713Sgirish 		/* Set MAC Internal Loopback if necessary */
19544961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
19644961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
19744961713Sgirish 
19844961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
19944961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
20044961713Sgirish 
20144961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
20244961713Sgirish 
20344961713Sgirish 		if (portmode == PORT_10G_FIBER) {
20444961713Sgirish 			if (statsp->mac_stats.link_up) {
20544961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
20644961713Sgirish 			} else {
20744961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
20844961713Sgirish 			}
20944961713Sgirish 		}
21044961713Sgirish 
21144961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
21244961713Sgirish 		if (rs != NPI_SUCCESS)
21344961713Sgirish 			goto fail;
21444961713Sgirish 
21544961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
21644961713Sgirish 
21744961713Sgirish 		/* Set Port Mode */
21844961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
21944961713Sgirish 					(portmode == PORT_10G_COPPER)) {
22044961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
22144961713Sgirish 						MAC_XGMII_MODE, rs);
22244961713Sgirish 			if (rs != NPI_SUCCESS)
22344961713Sgirish 				goto fail;
22444961713Sgirish 			if (statsp->mac_stats.link_up) {
22544961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
22644961713Sgirish 					goto fail;
22744961713Sgirish 			} else {
22844961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
22944961713Sgirish 					goto fail;
23044961713Sgirish 			}
23144961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
23244961713Sgirish 						(portmode == PORT_1G_COPPER)) {
23344961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
23444961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
23544961713Sgirish 							MAC_GMII_MODE, rs);
23644961713Sgirish 			} else {
23744961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
23844961713Sgirish 							MAC_MII_MODE, rs);
23944961713Sgirish 			}
24044961713Sgirish 			if (rs != NPI_SUCCESS)
24144961713Sgirish 				goto fail;
24244961713Sgirish 		} else {
24344961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
24444961713Sgirish 					"nxge_xif_init: Unknown port mode (%d)"
24544961713Sgirish 					" for port<%d>", portmode, portn));
24644961713Sgirish 			goto fail;
24744961713Sgirish 		}
24844961713Sgirish 
24944961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
25044961713Sgirish 
25144961713Sgirish 		/* Setup XIF Configuration for BMAC */
25244961713Sgirish 
25344961713Sgirish 		if (portmode == PORT_1G_COPPER) {
25444961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
25544961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
25644961713Sgirish 		}
25744961713Sgirish 
25844961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
25944961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
26044961713Sgirish 
26144961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
26244961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
26344961713Sgirish 
26444961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
26544961713Sgirish 
26644961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
26744961713Sgirish 		if (rs != NPI_SUCCESS)
26844961713Sgirish 			goto fail;
26944961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
27044961713Sgirish 	}
27144961713Sgirish 
27244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
27344961713Sgirish 	return (NXGE_OK);
27444961713Sgirish fail:
27544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
27644961713Sgirish 			"nxge_xif_init: Failed to initialize XIF port<%d>",
27744961713Sgirish 			portn));
27844961713Sgirish 	return (NXGE_ERROR | rs);
27944961713Sgirish }
28044961713Sgirish 
28144961713Sgirish /* Initialize the PCS sub-block in the MAC */
28244961713Sgirish 
28344961713Sgirish nxge_status_t
28444961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
28544961713Sgirish {
28644961713Sgirish 	pcs_cfg_t		pcs_cfg;
28744961713Sgirish 	uint32_t		val;
28844961713Sgirish 	uint8_t			portn;
28944961713Sgirish 	nxge_port_mode_t	portmode;
29044961713Sgirish 	npi_handle_t		handle;
29144961713Sgirish 	p_nxge_stats_t		statsp;
29244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
29344961713Sgirish 
29444961713Sgirish 	handle = nxgep->npi_handle;
29544961713Sgirish 	portmode = nxgep->mac.portmode;
29644961713Sgirish 	portn = nxgep->mac.portnum;
29744961713Sgirish 	statsp = nxgep->statsp;
29844961713Sgirish 
29944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
30044961713Sgirish 
30144961713Sgirish 	if (portmode == PORT_1G_FIBER) {
30244961713Sgirish 		/* Initialize port's PCS */
30344961713Sgirish 		pcs_cfg.value = 0;
30444961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
30544961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
30644961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
30744961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
30844961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
30944961713Sgirish 			goto fail;
31044961713Sgirish 
31144961713Sgirish 	} else if ((portmode == PORT_10G_FIBER) ||
31244961713Sgirish 						(portmode == PORT_10G_COPPER)) {
31344961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
31444961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
31544961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
31644961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
31744961713Sgirish 
31844961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
31944961713Sgirish 			goto fail;
32044961713Sgirish 
32144961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
32244961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
32344961713Sgirish 						XPCS_REG_CONTROL1, &val))
32444961713Sgirish 						!= NPI_SUCCESS)
32544961713Sgirish 			goto fail;
32644961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
32744961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
32844961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
32944961713Sgirish 		else
33044961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
33144961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
33244961713Sgirish 						XPCS_REG_CONTROL1, val))
33344961713Sgirish 						!= NPI_SUCCESS)
33444961713Sgirish 			goto fail;
33544961713Sgirish 
33644961713Sgirish 		/* Clear descw errors */
33744961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
33844961713Sgirish 						XPCS_REG_DESCWERR_COUNTER, 0))
33944961713Sgirish 						!= NPI_SUCCESS)
34044961713Sgirish 			goto fail;
34144961713Sgirish 		/* Clear symbol errors */
34244961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
34344961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
34444961713Sgirish 					!= NPI_SUCCESS)
34544961713Sgirish 			goto fail;
34644961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
34744961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
34844961713Sgirish 					!= NPI_SUCCESS)
34944961713Sgirish 			goto fail;
35044961713Sgirish 
35144961713Sgirish 	} else if (portmode == PORT_1G_COPPER) {
35244961713Sgirish 		if (portn < 4) {
35344961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
35444961713Sgirish 					PCS_DATAPATH_MODE_MII);
35544961713Sgirish 		}
35644961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
35744961713Sgirish 			goto fail;
35844961713Sgirish 
35944961713Sgirish 	} else {
36044961713Sgirish 		goto fail;
36144961713Sgirish 	}
36244961713Sgirish pass:
36344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
36444961713Sgirish 	return (NXGE_OK);
36544961713Sgirish fail:
36644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36744961713Sgirish 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
36844961713Sgirish 			portn));
36944961713Sgirish 	return (NXGE_ERROR | rs);
37044961713Sgirish }
37144961713Sgirish 
37244961713Sgirish /* Initialize the Internal Serdes */
37344961713Sgirish 
37444961713Sgirish nxge_status_t
37544961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
37644961713Sgirish {
37744961713Sgirish 	p_nxge_stats_t		statsp;
37844961713Sgirish #ifdef	NXGE_DEBUG
37944961713Sgirish 	uint8_t			portn;
38044961713Sgirish #endif
38144961713Sgirish 	nxge_status_t		status = NXGE_OK;
38244961713Sgirish 
38344961713Sgirish #ifdef	NXGE_DEBUG
38444961713Sgirish 	portn = nxgep->mac.portnum;
38544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38644961713Sgirish 		"==> nxge_serdes_init port<%d>", portn));
38744961713Sgirish #endif
38844961713Sgirish 
38944961713Sgirish 	statsp = nxgep->statsp;
39044961713Sgirish 
39144961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
39244961713Sgirish 		if (nxge_n2_serdes_init(nxgep) != NXGE_OK)
39344961713Sgirish 			goto fail;
39444961713Sgirish 	} else if ((nxgep->niu_type == NEPTUNE) ||
39544961713Sgirish 				(nxgep->niu_type == NEPTUNE_2)) {
39644961713Sgirish 			if ((status = nxge_neptune_serdes_init(nxgep))
39744961713Sgirish 								!= NXGE_OK)
39844961713Sgirish 				goto fail;
39944961713Sgirish 	} else {
40044961713Sgirish 		goto fail;
40144961713Sgirish 	}
40244961713Sgirish 
40344961713Sgirish 	statsp->mac_stats.serdes_inits++;
40444961713Sgirish 
40544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
40644961713Sgirish 			portn));
40744961713Sgirish 
40844961713Sgirish 	return (NXGE_OK);
40944961713Sgirish 
41044961713Sgirish fail:
41144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41244961713Sgirish 		"nxge_serdes_init: Failed to initialize serdes for port<%d>",
41344961713Sgirish 			portn));
41444961713Sgirish 
41544961713Sgirish 	return (status);
41644961713Sgirish }
41744961713Sgirish 
41844961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
41944961713Sgirish 
42044961713Sgirish nxge_status_t
42144961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
42244961713Sgirish {
42344961713Sgirish 	uint8_t portn;
42444961713Sgirish 	int chan;
42544961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
42644961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
42744961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
42844961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
42944961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
43044961713Sgirish 	esr_ti_testcfg_t test_cfg;
43144961713Sgirish 	nxge_status_t status = NXGE_OK;
43244961713Sgirish 
43344961713Sgirish 	portn = nxgep->mac.portnum;
43444961713Sgirish 
43544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
43644961713Sgirish 			portn));
43744961713Sgirish 
43844961713Sgirish 	tx_cfg_l.value = 0;
43944961713Sgirish 	tx_cfg_h.value = 0;
44044961713Sgirish 	rx_cfg_l.value = 0;
44144961713Sgirish 	rx_cfg_h.value = 0;
44244961713Sgirish 	pll_cfg_l.value = 0;
44344961713Sgirish 	test_cfg.value = 0;
44444961713Sgirish 
44544961713Sgirish 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
44644961713Sgirish 		/* 0x0E01 */
44744961713Sgirish 		tx_cfg_l.bits.entx = 1;
44844961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
44944961713Sgirish 
45044961713Sgirish 		/* 0x9101 */
45144961713Sgirish 		rx_cfg_l.bits.enrx = 1;
45244961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
45344961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
45444961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
45544961713Sgirish 
45644961713Sgirish 		/* 0x0008 */
45744961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
45844961713Sgirish 
45944961713Sgirish 		/* Set loopback mode if necessary */
46044961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
46144961713Sgirish 			tx_cfg_l.bits.entest = 1;
46244961713Sgirish 			rx_cfg_l.bits.entest = 1;
46344961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
46444961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
46544961713Sgirish 				ESR_N2_DEV_ADDR,
46644961713Sgirish 				ESR_N2_TEST_CFG_REG, test_cfg.value))
46744961713Sgirish 				!= NXGE_OK)
46844961713Sgirish 			goto fail;
46944961713Sgirish 		}
47044961713Sgirish 
47144961713Sgirish 		/* Use default PLL value */
47244961713Sgirish 
47344961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
47444961713Sgirish 
47544961713Sgirish 		/* 0x0E21 */
47644961713Sgirish 		tx_cfg_l.bits.entx = 1;
47744961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
47844961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
47944961713Sgirish 
48044961713Sgirish 		/* 0x9121 */
48144961713Sgirish 		rx_cfg_l.bits.enrx = 1;
48244961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
48344961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
48444961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
48544961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
48644961713Sgirish 
48744961713Sgirish 		/* 0x8 */
48844961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
48944961713Sgirish 
49044961713Sgirish 		/* MPY = 0x100 */
49144961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
49244961713Sgirish 
49344961713Sgirish 		/* Set PLL */
49444961713Sgirish 		pll_cfg_l.bits.enpll = 1;
49544961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
49644961713Sgirish 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
49744961713Sgirish 				!= NXGE_OK)
49844961713Sgirish 			goto fail;
49944961713Sgirish 	} else {
50044961713Sgirish 		goto fail;
50144961713Sgirish 	}
50244961713Sgirish 
50344961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
50444961713Sgirish 
50544961713Sgirish 	NXGE_DELAY(20);
50644961713Sgirish 
50744961713Sgirish 	/* init TX channels */
50844961713Sgirish 	for (chan = 0; chan < 4; chan++) {
50944961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
51044961713Sgirish 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
51144961713Sgirish 				!= NXGE_OK)
51244961713Sgirish 			goto fail;
51344961713Sgirish 
51444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
51544961713Sgirish 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
51644961713Sgirish 				!= NXGE_OK)
51744961713Sgirish 			goto fail;
51844961713Sgirish 	}
51944961713Sgirish 
52044961713Sgirish 	/* init RX channels */
52144961713Sgirish 	for (chan = 0; chan < 4; chan++) {
52244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
52344961713Sgirish 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
52444961713Sgirish 				!= NXGE_OK)
52544961713Sgirish 			goto fail;
52644961713Sgirish 
52744961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
52844961713Sgirish 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
52944961713Sgirish 				!= NXGE_OK)
53044961713Sgirish 			goto fail;
53144961713Sgirish 	}
53244961713Sgirish 
53344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
53444961713Sgirish 			portn));
53544961713Sgirish 
53644961713Sgirish 	return (NXGE_OK);
53744961713Sgirish fail:
53844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53944961713Sgirish 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
54044961713Sgirish 				portn));
54144961713Sgirish 
54244961713Sgirish 	return (status);
54344961713Sgirish }
54444961713Sgirish 
54544961713Sgirish /* Initialize Neptune Internal Serdes (Neptune only) */
54644961713Sgirish 
54744961713Sgirish nxge_status_t
54844961713Sgirish nxge_neptune_serdes_init(p_nxge_t nxgep)
54944961713Sgirish {
55044961713Sgirish 	npi_handle_t		handle;
55144961713Sgirish 	uint8_t			portn;
55244961713Sgirish 	nxge_port_mode_t	portmode;
55344961713Sgirish 	int			chan;
55444961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
55544961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
55644961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
55744961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
55844961713Sgirish 	uint64_t		val;
55944961713Sgirish 	uint16_t		val16l;
56044961713Sgirish 	uint16_t		val16h;
56144961713Sgirish 	nxge_status_t		status = NXGE_OK;
56244961713Sgirish 
56344961713Sgirish 	portn = nxgep->mac.portnum;
56444961713Sgirish 
56544961713Sgirish 	if ((portn != 0) && (portn != 1))
56644961713Sgirish 		return (NXGE_OK);
56744961713Sgirish 
56844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>",
56944961713Sgirish 			portn));
57044961713Sgirish 
57144961713Sgirish 	handle = nxgep->npi_handle;
57244961713Sgirish 	portmode = nxgep->mac.portmode;
57344961713Sgirish 
57444961713Sgirish 	if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) {
57544961713Sgirish 
57644961713Sgirish 		switch (portn) {
57744961713Sgirish 		case 0:
57844961713Sgirish 			ESR_REG_WR(handle, ESR_0_CONTROL_REG,
57944961713Sgirish 				ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
58044961713Sgirish 				ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
58144961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
58244961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
58344961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
58444961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
58544961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
58644961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
58744961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
58844961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
58944961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
59044961713Sgirish 
59144961713Sgirish 				/* Set Serdes0 Internal Loopback if necessary */
59244961713Sgirish 				if (nxgep->statsp->port_stats.lb_mode ==
59344961713Sgirish 							nxge_lb_serdes10g) {
59444961713Sgirish 					ESR_REG_WR(handle,
59544961713Sgirish 						ESR_0_TEST_CONFIG_REG,
59644961713Sgirish 						ESR_PAD_LOOPBACK_CH3 |
59744961713Sgirish 						ESR_PAD_LOOPBACK_CH2 |
59844961713Sgirish 						ESR_PAD_LOOPBACK_CH1 |
59944961713Sgirish 						ESR_PAD_LOOPBACK_CH0);
60044961713Sgirish 				} else {
60144961713Sgirish 					ESR_REG_WR(handle,
60244961713Sgirish 						ESR_0_TEST_CONFIG_REG, 0);
60344961713Sgirish 				}
60444961713Sgirish 			break;
60544961713Sgirish 		case 1:
60644961713Sgirish 			ESR_REG_WR(handle, ESR_1_CONTROL_REG,
60744961713Sgirish 				ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
60844961713Sgirish 				ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
60944961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
61044961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
61144961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
61244961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
61344961713Sgirish 				(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
61444961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
61544961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
61644961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
61744961713Sgirish 				(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
61844961713Sgirish 
61944961713Sgirish 				/* Set Serdes1 Internal Loopback if necessary */
62044961713Sgirish 				if (nxgep->statsp->port_stats.lb_mode ==
62144961713Sgirish 							nxge_lb_serdes10g) {
62244961713Sgirish 					ESR_REG_WR(handle,
62344961713Sgirish 						ESR_1_TEST_CONFIG_REG,
62444961713Sgirish 						ESR_PAD_LOOPBACK_CH3 |
62544961713Sgirish 						ESR_PAD_LOOPBACK_CH2 |
62644961713Sgirish 						ESR_PAD_LOOPBACK_CH1 |
62744961713Sgirish 						ESR_PAD_LOOPBACK_CH0);
62844961713Sgirish 				} else {
62944961713Sgirish 					ESR_REG_WR(handle,
63044961713Sgirish 						ESR_1_TEST_CONFIG_REG, 0);
63144961713Sgirish 				}
63244961713Sgirish 			break;
63344961713Sgirish 		default:
63444961713Sgirish 			/* Nothing to do here */
63544961713Sgirish 			goto done;
63644961713Sgirish 		}
63744961713Sgirish 
63844961713Sgirish 		/* init TX RX channels */
63944961713Sgirish 		for (chan = 0; chan < 4; chan++) {
64044961713Sgirish 			if ((status = nxge_mdio_read(nxgep, portn,
64144961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
64244961713Sgirish 					ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
64344961713Sgirish 					&rx_tx_ctrl_l.value)) != NXGE_OK)
64444961713Sgirish 				goto fail;
64544961713Sgirish 			if ((status = nxge_mdio_read(nxgep, portn,
64644961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
64744961713Sgirish 					ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
64844961713Sgirish 					&rx_tx_ctrl_h.value)) != NXGE_OK)
64944961713Sgirish 				goto fail;
65044961713Sgirish 			if ((status = nxge_mdio_read(nxgep, portn,
65144961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
65244961713Sgirish 					ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
65344961713Sgirish 					&glue_ctrl0_l.value)) != NXGE_OK)
65444961713Sgirish 				goto fail;
65544961713Sgirish 			if ((status = nxge_mdio_read(nxgep, portn,
65644961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
65744961713Sgirish 					ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
65844961713Sgirish 					&glue_ctrl0_h.value)) != NXGE_OK)
65944961713Sgirish 				goto fail;
66044961713Sgirish 			rx_tx_ctrl_l.bits.enstretch = 1;
66144961713Sgirish 			rx_tx_ctrl_h.bits.vmuxlo = 2;
66244961713Sgirish 			rx_tx_ctrl_h.bits.vpulselo = 2;
66344961713Sgirish 			glue_ctrl0_l.bits.rxlosenable = 1;
66444961713Sgirish 			glue_ctrl0_l.bits.samplerate = 0xF;
66544961713Sgirish 			glue_ctrl0_l.bits.thresholdcount = 0xFF;
66644961713Sgirish 			glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
66744961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
66844961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
66944961713Sgirish 					ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
67044961713Sgirish 					rx_tx_ctrl_l.value)) != NXGE_OK)
67144961713Sgirish 				goto fail;
67244961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
67344961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
67444961713Sgirish 					ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
67544961713Sgirish 					rx_tx_ctrl_h.value)) != NXGE_OK)
67644961713Sgirish 				goto fail;
67744961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
67844961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
67944961713Sgirish 					ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
68044961713Sgirish 					glue_ctrl0_l.value)) != NXGE_OK)
68144961713Sgirish 				goto fail;
68244961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
68344961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
68444961713Sgirish 					ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
68544961713Sgirish 					glue_ctrl0_h.value)) != NXGE_OK)
68644961713Sgirish 				goto fail;
68744961713Sgirish 		}
68844961713Sgirish 
68944961713Sgirish 		/* Apply Tx core reset */
69044961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
69144961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
69244961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
69344961713Sgirish 					(uint16_t)0)) != NXGE_OK)
69444961713Sgirish 			goto fail;
69544961713Sgirish 
69644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
69744961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
69844961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
69944961713Sgirish 					(uint16_t)0xffff)) != NXGE_OK)
70044961713Sgirish 			goto fail;
70144961713Sgirish 
70244961713Sgirish 		NXGE_DELAY(200);
70344961713Sgirish 
70444961713Sgirish 		/* Apply Rx core reset */
70544961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
70644961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
70744961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
70844961713Sgirish 					(uint16_t)0xffff)) != NXGE_OK)
70944961713Sgirish 			goto fail;
71044961713Sgirish 
71144961713Sgirish 		NXGE_DELAY(200);
71244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
71344961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
71444961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
71544961713Sgirish 					(uint16_t)0)) != NXGE_OK)
71644961713Sgirish 			goto fail;
71744961713Sgirish 
71844961713Sgirish 		NXGE_DELAY(200);
71944961713Sgirish 		if ((status = nxge_mdio_read(nxgep, portn,
72044961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
72144961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
72244961713Sgirish 					&val16l)) != NXGE_OK)
72344961713Sgirish 			goto fail;
72444961713Sgirish 		if ((status = nxge_mdio_read(nxgep, portn,
72544961713Sgirish 					ESR_NEPTUNE_DEV_ADDR,
72644961713Sgirish 					ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(),
72744961713Sgirish 					&val16h)) != NXGE_OK)
72844961713Sgirish 			goto fail;
72944961713Sgirish 		if ((val16l != 0) || (val16h != 0)) {
73044961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
73144961713Sgirish 					"Failed to reset port<%d> XAUI Serdes",
73244961713Sgirish 					portn));
73344961713Sgirish 		}
73444961713Sgirish 
73544961713Sgirish 		ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
73644961713Sgirish 
73744961713Sgirish 		if (portn == 0) {
73844961713Sgirish 			if ((val & ESR_SIG_P0_BITS_MASK) !=
73944961713Sgirish 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
74044961713Sgirish 					ESR_SIG_XSERDES_RDY_P0 |
74144961713Sgirish 					ESR_SIG_XDETECT_P0_CH3 |
74244961713Sgirish 					ESR_SIG_XDETECT_P0_CH2 |
74344961713Sgirish 					ESR_SIG_XDETECT_P0_CH1 |
74444961713Sgirish 					ESR_SIG_XDETECT_P0_CH0)) {
74544961713Sgirish 				goto fail;
74644961713Sgirish 			}
74744961713Sgirish 		} else if (portn == 1) {
74844961713Sgirish 			if ((val & ESR_SIG_P1_BITS_MASK) !=
74944961713Sgirish 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
75044961713Sgirish 					ESR_SIG_XSERDES_RDY_P1 |
75144961713Sgirish 					ESR_SIG_XDETECT_P1_CH3 |
75244961713Sgirish 					ESR_SIG_XDETECT_P1_CH2 |
75344961713Sgirish 					ESR_SIG_XDETECT_P1_CH1 |
75444961713Sgirish 					ESR_SIG_XDETECT_P1_CH0)) {
75544961713Sgirish 				goto fail;
75644961713Sgirish 			}
75744961713Sgirish 		}
75844961713Sgirish 
75944961713Sgirish 	} else if (portmode == PORT_1G_FIBER) {
76044961713Sgirish 		ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val)
76144961713Sgirish 		val &= ~ESR_PLL_CFG_FBDIV_2;
76244961713Sgirish 		switch (portn) {
76344961713Sgirish 		case 0:
76444961713Sgirish 			val |= ESR_PLL_CFG_HALF_RATE_0;
76544961713Sgirish 			break;
76644961713Sgirish 		case 1:
76744961713Sgirish 			val |= ESR_PLL_CFG_HALF_RATE_1;
76844961713Sgirish 			break;
76944961713Sgirish 		case 2:
77044961713Sgirish 			val |= ESR_PLL_CFG_HALF_RATE_2;
77144961713Sgirish 			break;
77244961713Sgirish 		case 3:
77344961713Sgirish 			val |= ESR_PLL_CFG_HALF_RATE_3;
77444961713Sgirish 			break;
77544961713Sgirish 		default:
77644961713Sgirish 			goto fail;
77744961713Sgirish 		}
77844961713Sgirish 
77944961713Sgirish 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
78044961713Sgirish 	}
78144961713Sgirish 
78244961713Sgirish done:
78344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>",
78444961713Sgirish 			portn));
78544961713Sgirish 	return (NXGE_OK);
78644961713Sgirish fail:
78744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
78844961713Sgirish 			"nxge_neptune_serdes_init: "
78944961713Sgirish 			"Failed to initialize Neptune serdes for port<%d>",
79044961713Sgirish 			portn));
79144961713Sgirish 
79244961713Sgirish 	return (status);
79344961713Sgirish }
79444961713Sgirish 
79544961713Sgirish /* Look for transceiver type */
79644961713Sgirish 
79744961713Sgirish nxge_status_t
79844961713Sgirish nxge_xcvr_find(p_nxge_t nxgep)
79944961713Sgirish {
80044961713Sgirish 	uint8_t		portn;
80144961713Sgirish 
80244961713Sgirish 	portn = nxgep->mac.portnum;
80344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn));
80444961713Sgirish 
80544961713Sgirish 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
80644961713Sgirish 		return (NXGE_ERROR);
80744961713Sgirish 
80844961713Sgirish 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
80944961713Sgirish 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
81044961713Sgirish 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
81144961713Sgirish 		if ((nxgep->niu_type == NEPTUNE) ||
81244961713Sgirish 			(nxgep->niu_type == NEPTUNE_2)) {
81344961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
81444961713Sgirish 					BCM8704_NEPTUNE_PORT_ADDR_BASE + portn;
81544961713Sgirish 		} else if (nxgep->niu_type == N2_NIU) {
81644961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
81744961713Sgirish 					BCM8704_N2_PORT_ADDR_BASE + portn;
81844961713Sgirish 		} else
81944961713Sgirish 			return (NXGE_ERROR);
82044961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_COPPER) {
82144961713Sgirish 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
82244961713Sgirish 		/*
82344961713Sgirish 		 * For Altas, Xcvr port numbers are swapped with ethernet
82444961713Sgirish 		 * port number. This is designed for better signal
82544961713Sgirish 		 * integrity in routing.
82644961713Sgirish 		 */
82744961713Sgirish 
82844961713Sgirish 		switch (portn) {
82944961713Sgirish 		case 0:
83044961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
83144961713Sgirish 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 3;
83244961713Sgirish 			break;
83344961713Sgirish 		case 1:
83444961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
83544961713Sgirish 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 2;
83644961713Sgirish 			break;
83744961713Sgirish 		case 2:
83844961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
83944961713Sgirish 					BCM5464_NEPTUNE_PORT_ADDR_BASE + 1;
84044961713Sgirish 			break;
84144961713Sgirish 		case 3:
84244961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn =
84344961713Sgirish 					BCM5464_NEPTUNE_PORT_ADDR_BASE;
84444961713Sgirish 			break;
84544961713Sgirish 		default:
84644961713Sgirish 			return (NXGE_ERROR);
84744961713Sgirish 		}
84844961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
84944961713Sgirish 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
85044961713Sgirish 		nxgep->statsp->mac_stats.xcvr_portn = portn;
85144961713Sgirish 	} else {
85244961713Sgirish 		return (NXGE_ERROR);
85344961713Sgirish 	}
85444961713Sgirish 
85544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
85644961713Sgirish 					nxgep->statsp->mac_stats.xcvr_inuse));
85744961713Sgirish 	return (NXGE_OK);
85844961713Sgirish }
85944961713Sgirish 
86044961713Sgirish /* Initialize transceiver */
86144961713Sgirish 
86244961713Sgirish nxge_status_t
86344961713Sgirish nxge_xcvr_init(p_nxge_t nxgep)
86444961713Sgirish {
86544961713Sgirish 	p_nxge_param_t		param_arr;
86644961713Sgirish 	p_nxge_stats_t		statsp;
86744961713Sgirish 	uint16_t		val;
86844961713Sgirish #ifdef	NXGE_DEBUG
86914ea4bb7Ssd 	uint8_t			portn;
87044961713Sgirish 	uint16_t		val1;
87144961713Sgirish #endif
87244961713Sgirish 	uint8_t			phy_port_addr;
87344961713Sgirish 	pmd_tx_control_t	tx_ctl;
87444961713Sgirish 	control_t		ctl;
87544961713Sgirish 	phyxs_control_t		phyxs_ctl;
87644961713Sgirish 	pcs_control_t		pcs_ctl;
87744961713Sgirish 	uint32_t		delay = 0;
87844961713Sgirish 	optics_dcntr_t		op_ctr;
87944961713Sgirish 	nxge_status_t		status = NXGE_OK;
88014ea4bb7Ssd #ifdef	NXGE_DEBUG
88144961713Sgirish 	portn = nxgep->mac.portnum;
88214ea4bb7Ssd #endif
88344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
88444961713Sgirish 
88544961713Sgirish 	param_arr = nxgep->param_arr;
88644961713Sgirish 	statsp = nxgep->statsp;
88744961713Sgirish 
88844961713Sgirish 	/*
88958324dfcSspeer 	 * Initialize the xcvr statistics.
89044961713Sgirish 	 */
89144961713Sgirish 	statsp->mac_stats.cap_autoneg = 0;
89244961713Sgirish 	statsp->mac_stats.cap_100T4 = 0;
89344961713Sgirish 	statsp->mac_stats.cap_100fdx = 0;
89444961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
89544961713Sgirish 	statsp->mac_stats.cap_10fdx = 0;
89644961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
89744961713Sgirish 	statsp->mac_stats.cap_asmpause = 0;
89844961713Sgirish 	statsp->mac_stats.cap_pause = 0;
89944961713Sgirish 	statsp->mac_stats.cap_1000fdx = 0;
90044961713Sgirish 	statsp->mac_stats.cap_1000hdx = 0;
90144961713Sgirish 	statsp->mac_stats.cap_10gfdx = 0;
90244961713Sgirish 	statsp->mac_stats.cap_10ghdx = 0;
90344961713Sgirish 
90444961713Sgirish 	/*
90544961713Sgirish 	 * Initialize the link statistics.
90644961713Sgirish 	 */
90744961713Sgirish 	statsp->mac_stats.link_T4 = 0;
90844961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
90944961713Sgirish 	statsp->mac_stats.link_pause = 0;
91044961713Sgirish 
91144961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
91244961713Sgirish 
91344961713Sgirish 	switch (nxgep->mac.portmode) {
91444961713Sgirish 	case PORT_10G_FIBER:
91544961713Sgirish 		/* Disable Link LEDs */
91644961713Sgirish 		if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
91744961713Sgirish 			goto fail;
91844961713Sgirish 
91944961713Sgirish 		/* Set Clause 45 */
92044961713Sgirish 		npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
92144961713Sgirish 
92244961713Sgirish 		/* Reset the transceiver */
92344961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
92444961713Sgirish 				phy_port_addr,
92544961713Sgirish 				BCM8704_PHYXS_ADDR,
92644961713Sgirish 				BCM8704_PHYXS_CONTROL_REG,
92744961713Sgirish 				&phyxs_ctl.value)) != NXGE_OK)
92844961713Sgirish 			goto fail;
92944961713Sgirish 
93044961713Sgirish 		phyxs_ctl.bits.reset = 1;
93144961713Sgirish 		if ((status = nxge_mdio_write(nxgep,
93244961713Sgirish 				phy_port_addr,
93344961713Sgirish 				BCM8704_PHYXS_ADDR,
93444961713Sgirish 				BCM8704_PHYXS_CONTROL_REG,
93544961713Sgirish 				phyxs_ctl.value)) != NXGE_OK)
93644961713Sgirish 			goto fail;
93744961713Sgirish 
93844961713Sgirish 		do {
93944961713Sgirish 			drv_usecwait(500);
94044961713Sgirish 			if ((status = nxge_mdio_read(nxgep,
94144961713Sgirish 					phy_port_addr,
94244961713Sgirish 					BCM8704_PHYXS_ADDR,
94344961713Sgirish 					BCM8704_PHYXS_CONTROL_REG,
94444961713Sgirish 					&phyxs_ctl.value)) != NXGE_OK)
94544961713Sgirish 				goto fail;
94644961713Sgirish 			delay++;
94744961713Sgirish 		} while ((phyxs_ctl.bits.reset) && (delay < 100));
94844961713Sgirish 		if (delay == 100) {
94944961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
95044961713Sgirish 				"nxge_xcvr_init: "
95144961713Sgirish 				"failed to reset Transceiver on port<%d>",
95244961713Sgirish 				portn));
95344961713Sgirish 			status = NXGE_ERROR;
95444961713Sgirish 			goto fail;
95544961713Sgirish 		}
95644961713Sgirish 
95744961713Sgirish 		/* Set to 0x7FBF */
95844961713Sgirish 		ctl.value = 0;
95944961713Sgirish 		ctl.bits.res1 = 0x3F;
96044961713Sgirish 		ctl.bits.optxon_lvl = 1;
96144961713Sgirish 		ctl.bits.oprxflt_lvl = 1;
96244961713Sgirish 		ctl.bits.optrxlos_lvl = 1;
96344961713Sgirish 		ctl.bits.optxflt_lvl = 1;
96444961713Sgirish 		ctl.bits.opprflt_lvl = 1;
96544961713Sgirish 		ctl.bits.obtmpflt_lvl = 1;
96644961713Sgirish 		ctl.bits.opbiasflt_lvl = 1;
96744961713Sgirish 		ctl.bits.optxrst_lvl = 1;
96844961713Sgirish 		if ((status = nxge_mdio_write(nxgep,
96944961713Sgirish 				phy_port_addr,
97044961713Sgirish 				BCM8704_USER_DEV3_ADDR,
97144961713Sgirish 				BCM8704_USER_CONTROL_REG, ctl.value))
97244961713Sgirish 				!= NXGE_OK)
97344961713Sgirish 			goto fail;
97444961713Sgirish 
97544961713Sgirish 		/* Set to 0x164 */
97644961713Sgirish 		tx_ctl.value = 0;
97744961713Sgirish 		tx_ctl.bits.tsck_lpwren = 1;
97844961713Sgirish 		tx_ctl.bits.tx_dac_txck = 0x2;
97944961713Sgirish 		tx_ctl.bits.tx_dac_txd = 0x1;
98044961713Sgirish 		tx_ctl.bits.xfp_clken = 1;
98144961713Sgirish 		if ((status = nxge_mdio_write(nxgep,
98244961713Sgirish 				phy_port_addr,
98344961713Sgirish 				BCM8704_USER_DEV3_ADDR,
98444961713Sgirish 				BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value))
98544961713Sgirish 				!= NXGE_OK)
98644961713Sgirish 			goto fail;
98744961713Sgirish 		/*
98844961713Sgirish 		 * According to Broadcom's instruction, SW needs to read
98944961713Sgirish 		 * back these registers twice after written.
99044961713Sgirish 		 */
99144961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
99244961713Sgirish 				phy_port_addr,
99344961713Sgirish 				BCM8704_USER_DEV3_ADDR,
99444961713Sgirish 				BCM8704_USER_CONTROL_REG, &val))
99544961713Sgirish 				!= NXGE_OK)
99644961713Sgirish 			goto fail;
99744961713Sgirish 
99844961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
99944961713Sgirish 				phy_port_addr,
100044961713Sgirish 				BCM8704_USER_DEV3_ADDR,
100144961713Sgirish 				BCM8704_USER_CONTROL_REG, &val))
100244961713Sgirish 				!= NXGE_OK)
100344961713Sgirish 			goto fail;
100444961713Sgirish 
100544961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
100644961713Sgirish 				phy_port_addr,
100744961713Sgirish 				BCM8704_USER_DEV3_ADDR,
100844961713Sgirish 				BCM8704_USER_PMD_TX_CONTROL_REG, &val))
100944961713Sgirish 				!= NXGE_OK)
101044961713Sgirish 			goto fail;
101144961713Sgirish 
101244961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
101344961713Sgirish 				phy_port_addr,
101444961713Sgirish 				BCM8704_USER_DEV3_ADDR,
101544961713Sgirish 				BCM8704_USER_PMD_TX_CONTROL_REG, &val))
101644961713Sgirish 				!= NXGE_OK)
101744961713Sgirish 			goto fail;
101844961713Sgirish 
101944961713Sgirish 
102044961713Sgirish 		/* Enable Tx and Rx LEDs to be driven by traffic */
102144961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
102244961713Sgirish 					phy_port_addr,
102344961713Sgirish 					BCM8704_USER_DEV3_ADDR,
102444961713Sgirish 					BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
102544961713Sgirish 					&op_ctr.value)) != NXGE_OK)
102644961713Sgirish 			goto fail;
102744961713Sgirish 		op_ctr.bits.gpio_sel = 0x3;
102844961713Sgirish 		if ((status = nxge_mdio_write(nxgep,
102944961713Sgirish 					phy_port_addr,
103044961713Sgirish 					BCM8704_USER_DEV3_ADDR,
103144961713Sgirish 					BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
103244961713Sgirish 					op_ctr.value)) != NXGE_OK)
103344961713Sgirish 			goto fail;
103444961713Sgirish 
103544961713Sgirish 		NXGE_DELAY(1000000);
103644961713Sgirish 
103744961713Sgirish 		/* Set BCM8704 Internal Loopback mode if necessary */
103844961713Sgirish 		if ((status = nxge_mdio_read(nxgep,
103944961713Sgirish 					phy_port_addr,
104044961713Sgirish 					BCM8704_PCS_DEV_ADDR,
104144961713Sgirish 					BCM8704_PCS_CONTROL_REG,
104244961713Sgirish 					&pcs_ctl.value)) != NXGE_OK)
104344961713Sgirish 			goto fail;
104444961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
104544961713Sgirish 			pcs_ctl.bits.loopback = 1;
104644961713Sgirish 		else
104744961713Sgirish 			pcs_ctl.bits.loopback = 0;
104844961713Sgirish 		if ((status = nxge_mdio_write(nxgep,
104944961713Sgirish 					phy_port_addr,
105044961713Sgirish 					BCM8704_PCS_DEV_ADDR,
105144961713Sgirish 					BCM8704_PCS_CONTROL_REG,
105244961713Sgirish 					pcs_ctl.value)) != NXGE_OK)
105344961713Sgirish 			goto fail;
105444961713Sgirish 
105544961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr,
105644961713Sgirish 				0x1, 0xA, &val);
105744961713Sgirish 		if (status != NXGE_OK)
105844961713Sgirish 			goto fail;
105944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
106044961713Sgirish 				"BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n",
106144961713Sgirish 				portn, val));
106244961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
106344961713Sgirish 		if (status != NXGE_OK)
106444961713Sgirish 			goto fail;
106544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
106644961713Sgirish 				"BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n",
106744961713Sgirish 				portn, val));
106844961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
106944961713Sgirish 		if (status != NXGE_OK)
107044961713Sgirish 			goto fail;
107144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
107244961713Sgirish 				"BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n",
107344961713Sgirish 				portn, val));
107444961713Sgirish 
107544961713Sgirish #ifdef	NXGE_DEBUG
107644961713Sgirish 		/* Diagnose link issue if link is not up */
107744961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr,
107844961713Sgirish 					BCM8704_USER_DEV3_ADDR,
107944961713Sgirish 					BCM8704_USER_ANALOG_STATUS0_REG,
108044961713Sgirish 					&val);
108144961713Sgirish 		if (status != NXGE_OK)
108244961713Sgirish 			goto fail;
108344961713Sgirish 
108444961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr,
108544961713Sgirish 					BCM8704_USER_DEV3_ADDR,
108644961713Sgirish 					BCM8704_USER_ANALOG_STATUS0_REG,
108744961713Sgirish 					&val);
108844961713Sgirish 		if (status != NXGE_OK)
108944961713Sgirish 			goto fail;
109044961713Sgirish 
109144961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr,
109244961713Sgirish 					BCM8704_USER_DEV3_ADDR,
109344961713Sgirish 					BCM8704_USER_TX_ALARM_STATUS_REG,
109444961713Sgirish 					&val1);
109544961713Sgirish 		if (status != NXGE_OK)
109644961713Sgirish 			goto fail;
109744961713Sgirish 
109844961713Sgirish 		status = nxge_mdio_read(nxgep, phy_port_addr,
109944961713Sgirish 					BCM8704_USER_DEV3_ADDR,
110044961713Sgirish 					BCM8704_USER_TX_ALARM_STATUS_REG,
110144961713Sgirish 					&val1);
110244961713Sgirish 		if (status != NXGE_OK)
110344961713Sgirish 			goto fail;
110444961713Sgirish 
110544961713Sgirish 		if (val != 0x3FC) {
110644961713Sgirish 			if ((val == 0x43BC) && (val1 != 0)) {
110744961713Sgirish 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
110844961713Sgirish 					"Cable not connected to peer or bad"
110944961713Sgirish 					" cable on port<%d>\n", portn));
111044961713Sgirish 			} else if (val == 0x639C) {
111144961713Sgirish 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
111244961713Sgirish 					"Optical module (XFP) is bad or absence"
111344961713Sgirish 					" on port<%d>\n", portn));
111444961713Sgirish 			}
111544961713Sgirish 		}
111644961713Sgirish #endif
111744961713Sgirish 
111844961713Sgirish 		statsp->mac_stats.cap_10gfdx = 1;
111944961713Sgirish 		statsp->mac_stats.lp_cap_10gfdx = 1;
112044961713Sgirish 		break;
112144961713Sgirish 	case PORT_10G_COPPER:
112244961713Sgirish 		break;
112344961713Sgirish 	case PORT_1G_FIBER:
112444961713Sgirish 	case PORT_1G_COPPER:
112544961713Sgirish 		/* Set Clause 22 */
112644961713Sgirish 		npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
112744961713Sgirish 
112844961713Sgirish 		/* Set capability flags */
112944961713Sgirish 		statsp->mac_stats.cap_1000fdx =
113044961713Sgirish 					param_arr[param_anar_1000fdx].value;
113144961713Sgirish 		statsp->mac_stats.cap_100fdx =
113244961713Sgirish 					param_arr[param_anar_100fdx].value;
113344961713Sgirish 		statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
113444961713Sgirish 
113544961713Sgirish 		if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK)
113644961713Sgirish 			goto fail;
113744961713Sgirish 		break;
113844961713Sgirish 	default:
113944961713Sgirish 		goto fail;
114044961713Sgirish 	}
114144961713Sgirish 
114244961713Sgirish 	statsp->mac_stats.xcvr_inits++;
114344961713Sgirish 
114444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
114544961713Sgirish 	return (NXGE_OK);
114644961713Sgirish 
114744961713Sgirish fail:
114844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
114944961713Sgirish 		"nxge_xcvr_init: failed to initialize transceiver for port<%d>",
115044961713Sgirish 		portn));
115144961713Sgirish 	return (status);
115244961713Sgirish }
115344961713Sgirish 
115444961713Sgirish 
115544961713Sgirish /* Initialize the TxMAC sub-block */
115644961713Sgirish 
115744961713Sgirish nxge_status_t
115844961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
115944961713Sgirish {
116044961713Sgirish 	npi_attr_t		ap;
116144961713Sgirish 	uint8_t			portn;
116244961713Sgirish 	nxge_port_mode_t	portmode;
116344961713Sgirish 	nxge_port_t		portt;
116444961713Sgirish 	npi_handle_t		handle;
116544961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
116644961713Sgirish 
116744961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
116844961713Sgirish 	portt    = nxgep->mac.porttype;
116944961713Sgirish 	handle   = nxgep->npi_handle;
117044961713Sgirish 	portmode = nxgep->mac.portmode;
117144961713Sgirish 
117244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
117344961713Sgirish 			portn));
117444961713Sgirish 
117544961713Sgirish 	/* Set Max and Min Frame Size */
117614ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
117744961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
117844961713Sgirish 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
117944961713Sgirish 	} else {
118044961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
118144961713Sgirish 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
118244961713Sgirish 	}
118344961713Sgirish 
118444961713Sgirish 	if (rs != NPI_SUCCESS)
118544961713Sgirish 		goto fail;
118614ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value ||
118714ea4bb7Ssd 		nxgep->mac.is_jumbo == B_TRUE)
118844961713Sgirish 		nxgep->mac.maxframesize = 0x2400;
118944961713Sgirish 	else
119044961713Sgirish 		nxgep->mac.maxframesize = 0x5EE + 4;
119144961713Sgirish 	nxgep->mac.minframesize = 64;
119244961713Sgirish 
119344961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
119444961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
119544961713Sgirish 				0)) != NPI_SUCCESS)
119644961713Sgirish 			goto fail;
119744961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
119844961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
119944961713Sgirish 					(portmode == PORT_10G_COPPER)) {
120044961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
120144961713Sgirish 					XGMII_IPG_12_15, rs);
120244961713Sgirish 			if (rs != NPI_SUCCESS)
120344961713Sgirish 				goto fail;
120444961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
120544961713Sgirish 		} else {
120644961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
120744961713Sgirish 					MII_GMII_IPG_12, rs);
120844961713Sgirish 			if (rs != NPI_SUCCESS)
120944961713Sgirish 				goto fail;
121044961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
121144961713Sgirish 		}
121244961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
121344961713Sgirish 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
121444961713Sgirish 			goto fail;
121544961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
121644961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
121744961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
121844961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
121944961713Sgirish 
122044961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
122144961713Sgirish 							!= NPI_SUCCESS)
122244961713Sgirish 			goto fail;
122344961713Sgirish 
122444961713Sgirish 	} else {
122544961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
122644961713Sgirish 				0)) != NPI_SUCCESS)
122744961713Sgirish 			goto fail;
122844961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
122944961713Sgirish 
123044961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
123144961713Sgirish 				rs);
123244961713Sgirish 		if (rs != NPI_SUCCESS)
123344961713Sgirish 			goto fail;
123444961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
123544961713Sgirish 
123644961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
123744961713Sgirish 		if (rs != NPI_SUCCESS)
123844961713Sgirish 			goto fail;
123944961713Sgirish 		nxgep->mac.pa_size = 0x7;
124044961713Sgirish 
124144961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
124244961713Sgirish 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
124344961713Sgirish 			goto fail;
124444961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
124544961713Sgirish 	}
124644961713Sgirish 
124744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
124844961713Sgirish 			portn));
124944961713Sgirish 
125044961713Sgirish 	return (NXGE_OK);
125144961713Sgirish fail:
125244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
125344961713Sgirish 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
125444961713Sgirish 					portn));
125544961713Sgirish 
125644961713Sgirish 	return (NXGE_ERROR | rs);
125744961713Sgirish }
125844961713Sgirish 
125944961713Sgirish /* Initialize the RxMAC sub-block */
126044961713Sgirish 
126144961713Sgirish nxge_status_t
126244961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
126344961713Sgirish {
126444961713Sgirish 	npi_attr_t		ap;
126544961713Sgirish 	uint32_t		i;
126644961713Sgirish 	uint16_t		hashtab_e;
126744961713Sgirish 	p_hash_filter_t		hash_filter;
126844961713Sgirish 	nxge_port_t		portt;
126944961713Sgirish 	uint8_t			portn;
127044961713Sgirish 	npi_handle_t		handle;
127144961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
127244961713Sgirish 	uint16_t 		*addr16p;
127344961713Sgirish 	uint16_t 		addr0, addr1, addr2;
127444961713Sgirish 	xmac_rx_config_t	xconfig;
127544961713Sgirish 	bmac_rx_config_t	bconfig;
127644961713Sgirish 
127744961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
127844961713Sgirish 
127944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
128044961713Sgirish 			portn));
128144961713Sgirish 	handle = nxgep->npi_handle;
128244961713Sgirish 	portt = nxgep->mac.porttype;
128344961713Sgirish 
128444961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
128544961713Sgirish 	addr0 = ntohs(addr16p[2]);
128644961713Sgirish 	addr1 = ntohs(addr16p[1]);
128744961713Sgirish 	addr2 = ntohs(addr16p[0]);
128844961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
128944961713Sgirish 		rs);
129044961713Sgirish 
129144961713Sgirish 	if (rs != NPI_SUCCESS)
129244961713Sgirish 		goto fail;
129344961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
129444961713Sgirish 	if (rs != NPI_SUCCESS)
129544961713Sgirish 		goto fail;
129644961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
129744961713Sgirish 	if (rs != NPI_SUCCESS)
129844961713Sgirish 		goto fail;
129944961713Sgirish 
130044961713Sgirish 	/*
130144961713Sgirish 	 * Load the multicast hash filter bits.
130244961713Sgirish 	 */
130344961713Sgirish 	hash_filter = nxgep->hash_filter;
130444961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
130544961713Sgirish 		if (hash_filter != NULL) {
130644961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
130744961713Sgirish 				(NMCFILTER_REGS - 1) - i];
130844961713Sgirish 		} else {
130944961713Sgirish 			hashtab_e = 0;
131044961713Sgirish 		}
131144961713Sgirish 
131244961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
131344961713Sgirish 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
131444961713Sgirish 			goto fail;
131544961713Sgirish 	}
131644961713Sgirish 
131744961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
131844961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
131944961713Sgirish 				0)) != NPI_SUCCESS)
132044961713Sgirish 			goto fail;
132144961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
132244961713Sgirish 
132344961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
132444961713Sgirish 
132544961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
1326a3c5bd6dSspeer 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
1327a3c5bd6dSspeer 			~CFG_XMAC_RX_STRIP_CRC;
132844961713Sgirish 
132944961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
133044961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
133144961713Sgirish 
133244961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
133344961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
133444961713Sgirish 
133544961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
133644961713Sgirish 
133744961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
133844961713Sgirish 					xconfig)) != NPI_SUCCESS)
133944961713Sgirish 			goto fail;
134044961713Sgirish 		nxgep->mac.rx_config = xconfig;
134144961713Sgirish 
134244961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
134344961713Sgirish 
134444961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
134544961713Sgirish 							!= NPI_SUCCESS)
134644961713Sgirish 			goto fail;
134744961713Sgirish 	} else {
134844961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
134944961713Sgirish 
135044961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
135144961713Sgirish 					0) != NPI_SUCCESS)
135244961713Sgirish 			goto fail;
135344961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
135444961713Sgirish 
1355a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
1356a3c5bd6dSspeer 			~CFG_BMAC_RX_STRIP_CRC;
135744961713Sgirish 
135844961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
135944961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
136044961713Sgirish 
136144961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
136244961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
136344961713Sgirish 
136444961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
136544961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
136644961713Sgirish 					bconfig)) != NPI_SUCCESS)
136744961713Sgirish 			goto fail;
136844961713Sgirish 		nxgep->mac.rx_config = bconfig;
136944961713Sgirish 
137044961713Sgirish 		/* Always enable comparison of mac unique address */
137144961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
137244961713Sgirish 					!= NPI_SUCCESS)
137344961713Sgirish 			goto fail;
137444961713Sgirish 	}
137544961713Sgirish 
137644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
137744961713Sgirish 			portn));
137844961713Sgirish 
137944961713Sgirish 	return (NXGE_OK);
138044961713Sgirish 
138144961713Sgirish fail:
138244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
138344961713Sgirish 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
138444961713Sgirish 				portn));
138544961713Sgirish 
138644961713Sgirish 	return (NXGE_ERROR | rs);
138744961713Sgirish }
138844961713Sgirish 
138944961713Sgirish /* Enable TXMAC */
139044961713Sgirish 
139144961713Sgirish nxge_status_t
139244961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
139344961713Sgirish {
139444961713Sgirish 	npi_handle_t	handle;
139544961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
139644961713Sgirish 	nxge_status_t	status = NXGE_OK;
139744961713Sgirish 
139844961713Sgirish 	handle = nxgep->npi_handle;
139944961713Sgirish 
140044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
140144961713Sgirish 			nxgep->mac.portnum));
140244961713Sgirish 
140344961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
140444961713Sgirish 		goto fail;
140544961713Sgirish 
140644961713Sgirish 	/* based on speed */
140744961713Sgirish 	nxgep->msg_min = ETHERMIN;
140844961713Sgirish 
140944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
141044961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
141144961713Sgirish 						CFG_XMAC_TX)) != NPI_SUCCESS)
141244961713Sgirish 			goto fail;
141344961713Sgirish 	} else {
141444961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
141544961713Sgirish 						CFG_BMAC_TX)) != NPI_SUCCESS)
141644961713Sgirish 			goto fail;
141744961713Sgirish 	}
141844961713Sgirish 
141944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
142044961713Sgirish 			nxgep->mac.portnum));
142144961713Sgirish 
142244961713Sgirish 	return (NXGE_OK);
142344961713Sgirish fail:
142444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
142544961713Sgirish 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
142644961713Sgirish 			nxgep->mac.portnum));
142744961713Sgirish 	if (rs != NPI_SUCCESS)
142844961713Sgirish 		return (NXGE_ERROR | rs);
142944961713Sgirish 	else
143044961713Sgirish 		return (status);
143144961713Sgirish }
143244961713Sgirish 
143344961713Sgirish /* Disable TXMAC */
143444961713Sgirish 
143544961713Sgirish nxge_status_t
143644961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
143744961713Sgirish {
143844961713Sgirish 	npi_handle_t	handle;
143944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
144044961713Sgirish 
144144961713Sgirish 	handle = nxgep->npi_handle;
144244961713Sgirish 
144344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
144444961713Sgirish 			nxgep->mac.portnum));
144544961713Sgirish 
144644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
144744961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
144844961713Sgirish 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
144944961713Sgirish 			goto fail;
145044961713Sgirish 	} else {
145144961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
145244961713Sgirish 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
145344961713Sgirish 			goto fail;
145444961713Sgirish 	}
145544961713Sgirish 
145644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
145744961713Sgirish 			nxgep->mac.portnum));
145844961713Sgirish 	return (NXGE_OK);
145944961713Sgirish fail:
146044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
146144961713Sgirish 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
146244961713Sgirish 			nxgep->mac.portnum));
146344961713Sgirish 	return (NXGE_ERROR | rs);
146444961713Sgirish }
146544961713Sgirish 
146644961713Sgirish /* Enable RXMAC */
146744961713Sgirish 
146844961713Sgirish nxge_status_t
146944961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
147044961713Sgirish {
147144961713Sgirish 	npi_handle_t	handle;
147244961713Sgirish 	uint8_t 	portn;
147344961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
147444961713Sgirish 	nxge_status_t	status = NXGE_OK;
147544961713Sgirish 
147644961713Sgirish 	handle = nxgep->npi_handle;
147744961713Sgirish 	portn = nxgep->mac.portnum;
147844961713Sgirish 
147944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
148044961713Sgirish 			portn));
148144961713Sgirish 
148244961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
148344961713Sgirish 		goto fail;
148444961713Sgirish 
148544961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
148644961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
148744961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
148844961713Sgirish 			goto fail;
148944961713Sgirish 	} else {
149044961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
149144961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
149244961713Sgirish 			goto fail;
149344961713Sgirish 	}
149444961713Sgirish 
149544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
149644961713Sgirish 			portn));
149744961713Sgirish 
149844961713Sgirish 	return (NXGE_OK);
149944961713Sgirish fail:
150044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
150144961713Sgirish 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
150244961713Sgirish 			portn));
150344961713Sgirish 
150444961713Sgirish 	if (rs != NPI_SUCCESS)
150544961713Sgirish 		return (NXGE_ERROR | rs);
150644961713Sgirish 	else
150744961713Sgirish 		return (status);
150844961713Sgirish }
150944961713Sgirish 
151044961713Sgirish /* Disable RXMAC */
151144961713Sgirish 
151244961713Sgirish nxge_status_t
151344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
151444961713Sgirish {
151544961713Sgirish 	npi_handle_t	handle;
151644961713Sgirish 	uint8_t		portn;
151744961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
151844961713Sgirish 
151944961713Sgirish 	handle = nxgep->npi_handle;
152044961713Sgirish 	portn = nxgep->mac.portnum;
152144961713Sgirish 
152244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
152344961713Sgirish 			portn));
152444961713Sgirish 
152544961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
152644961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
152744961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
152844961713Sgirish 			goto fail;
152944961713Sgirish 	} else {
153044961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
153144961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
153244961713Sgirish 			goto fail;
153344961713Sgirish 	}
153444961713Sgirish 
153544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
153644961713Sgirish 			portn));
153744961713Sgirish 	return (NXGE_OK);
153844961713Sgirish fail:
153944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
154044961713Sgirish 			"nxgep_rx_mac_disable: ",
154144961713Sgirish 			"Failed to disable port<%d> RxMAC",
154244961713Sgirish 			portn));
154344961713Sgirish 
154444961713Sgirish 	return (NXGE_ERROR | rs);
154544961713Sgirish }
154644961713Sgirish 
154744961713Sgirish /* Reset TXMAC */
154844961713Sgirish 
154944961713Sgirish nxge_status_t
155044961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
155144961713Sgirish {
155244961713Sgirish 	npi_handle_t	handle;
155344961713Sgirish 	uint8_t		portn;
155444961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
155544961713Sgirish 
155644961713Sgirish 	handle = nxgep->npi_handle;
155744961713Sgirish 	portn = nxgep->mac.portnum;
155844961713Sgirish 
155944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
156044961713Sgirish 			portn));
156144961713Sgirish 
156244961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
156344961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
156444961713Sgirish 		    != NPI_SUCCESS)
156544961713Sgirish 			goto fail;
156644961713Sgirish 	} else {
156744961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
156844961713Sgirish 					!= NPI_SUCCESS)
156944961713Sgirish 			goto fail;
157044961713Sgirish 	}
157144961713Sgirish 
157244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
157344961713Sgirish 			portn));
157444961713Sgirish 
157544961713Sgirish 	return (NXGE_OK);
157644961713Sgirish fail:
157744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
157844961713Sgirish 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
157944961713Sgirish 			portn));
158044961713Sgirish 
158144961713Sgirish 	return (NXGE_ERROR | rs);
158244961713Sgirish }
158344961713Sgirish 
158444961713Sgirish /* Reset RXMAC */
158544961713Sgirish 
158644961713Sgirish nxge_status_t
158744961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
158844961713Sgirish {
158944961713Sgirish 	npi_handle_t	handle;
159044961713Sgirish 	uint8_t		portn;
159144961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
159244961713Sgirish 
159344961713Sgirish 	handle = nxgep->npi_handle;
159444961713Sgirish 	portn = nxgep->mac.portnum;
159544961713Sgirish 
159644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
159744961713Sgirish 			portn));
159844961713Sgirish 
159944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
160044961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
160144961713Sgirish 		    != NPI_SUCCESS)
160244961713Sgirish 		goto fail;
160344961713Sgirish 	} else {
160444961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
160544961713Sgirish 					!= NPI_SUCCESS)
160644961713Sgirish 		goto fail;
160744961713Sgirish 	}
160844961713Sgirish 
160944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
161044961713Sgirish 			portn));
161144961713Sgirish 
161244961713Sgirish 	return (NXGE_OK);
161344961713Sgirish fail:
161444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
161544961713Sgirish 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
161644961713Sgirish 			portn));
161744961713Sgirish 	return (NXGE_ERROR | rs);
161844961713Sgirish }
161944961713Sgirish 
162044961713Sgirish 
162144961713Sgirish /* Enable/Disable MII Link Status change interrupt */
162244961713Sgirish 
162344961713Sgirish nxge_status_t
162444961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
162544961713Sgirish {
162644961713Sgirish 	uint8_t			portn;
162744961713Sgirish 	nxge_port_mode_t	portmode;
162844961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
162944961713Sgirish 
163044961713Sgirish 	portn = nxgep->mac.portnum;
163144961713Sgirish 	portmode = nxgep->mac.portmode;
163244961713Sgirish 
163344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
163444961713Sgirish 
163544961713Sgirish 	if (enable == LINK_INTR_START) {
163644961713Sgirish 		if (portmode == PORT_10G_FIBER) {
163744961713Sgirish 			if ((rs = npi_xmac_xpcs_link_intr_enable(
163844961713Sgirish 						nxgep->npi_handle,
163944961713Sgirish 						portn)) != NPI_SUCCESS)
164044961713Sgirish 				goto fail;
164144961713Sgirish 		} else if (portmode == PORT_1G_FIBER) {
164244961713Sgirish 			if ((rs = npi_mac_pcs_link_intr_enable(
164344961713Sgirish 						nxgep->npi_handle,
164444961713Sgirish 						portn)) != NPI_SUCCESS)
164544961713Sgirish 				goto fail;
164644961713Sgirish 		} else if (portmode == PORT_1G_COPPER) {
164744961713Sgirish 			if ((rs = npi_mac_mif_link_intr_enable(
164844961713Sgirish 				nxgep->npi_handle,
164944961713Sgirish 				portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS)
165044961713Sgirish 				goto fail;
165144961713Sgirish 		} else
165244961713Sgirish 			goto fail;
165344961713Sgirish 	} else if (enable == LINK_INTR_STOP) {
165444961713Sgirish 		if (portmode == PORT_10G_FIBER) {
165544961713Sgirish 			if ((rs = npi_xmac_xpcs_link_intr_disable(
165644961713Sgirish 						nxgep->npi_handle,
165744961713Sgirish 						portn)) != NPI_SUCCESS)
165844961713Sgirish 				goto fail;
165944961713Sgirish 		} else  if (portmode == PORT_1G_FIBER) {
166044961713Sgirish 			if ((rs = npi_mac_pcs_link_intr_disable(
166144961713Sgirish 						nxgep->npi_handle,
166244961713Sgirish 						portn)) != NPI_SUCCESS)
166344961713Sgirish 				goto fail;
166444961713Sgirish 		} else if (portmode == PORT_1G_COPPER) {
166544961713Sgirish 			if ((rs = npi_mac_mif_link_intr_disable(
166644961713Sgirish 						nxgep->npi_handle,
166744961713Sgirish 						portn)) != NPI_SUCCESS)
166844961713Sgirish 				goto fail;
166944961713Sgirish 		} else
167044961713Sgirish 			goto fail;
167144961713Sgirish 	}
167244961713Sgirish 
167344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
167444961713Sgirish 
167544961713Sgirish 	return (NXGE_OK);
167644961713Sgirish fail:
167744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
167844961713Sgirish 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
167944961713Sgirish 			portn));
168044961713Sgirish 
168144961713Sgirish 	return (NXGE_ERROR | rs);
168244961713Sgirish }
168344961713Sgirish 
168444961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
168544961713Sgirish 
168644961713Sgirish nxge_status_t
168744961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
168844961713Sgirish {
168944961713Sgirish 	p_nxge_param_t	param_arr;
169044961713Sgirish 	p_nxge_stats_t	statsp;
169144961713Sgirish 	uint8_t		xcvr_portn;
169244961713Sgirish 	p_mii_regs_t	mii_regs;
169344961713Sgirish 	mii_bmcr_t	bmcr;
169444961713Sgirish 	mii_bmsr_t	bmsr;
169544961713Sgirish 	mii_anar_t	anar;
169644961713Sgirish 	mii_gcr_t	gcr;
169744961713Sgirish 	mii_esr_t	esr;
169844961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
169944961713Sgirish 	int		status = NXGE_OK;
170044961713Sgirish 
170144961713Sgirish 	uint_t delay;
170244961713Sgirish 
170344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
170444961713Sgirish 
170544961713Sgirish 	param_arr = nxgep->param_arr;
170644961713Sgirish 	statsp = nxgep->statsp;
170744961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
170844961713Sgirish 
170944961713Sgirish 	mii_regs = NULL;
171044961713Sgirish 
171144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
171244961713Sgirish 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
171344961713Sgirish 
171444961713Sgirish 	/*
171544961713Sgirish 	 * Reset the transceiver.
171644961713Sgirish 	 */
171744961713Sgirish 	delay = 0;
171844961713Sgirish 	bmcr.value = 0;
171944961713Sgirish 	bmcr.bits.reset = 1;
172044961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
172144961713Sgirish 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
172244961713Sgirish 		goto fail;
172344961713Sgirish 	do {
172444961713Sgirish 		drv_usecwait(500);
172544961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
172644961713Sgirish 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
172744961713Sgirish 				!= NXGE_OK)
172844961713Sgirish 			goto fail;
172944961713Sgirish 		delay++;
173044961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
173144961713Sgirish 	if (delay == 1000) {
173244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
173344961713Sgirish 		goto fail;
173444961713Sgirish 	}
173544961713Sgirish 
173644961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
173744961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
173844961713Sgirish 			&bmsr.value)) != NXGE_OK)
173944961713Sgirish 		goto fail;
174044961713Sgirish 
174144961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
174244961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
174344961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
174444961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
174544961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
174644961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
174744961713Sgirish 
174844961713Sgirish 	/*
174958324dfcSspeer 	 * Initialize the xcvr statistics.
175044961713Sgirish 	 */
175144961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
175244961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
175344961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
175444961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
175544961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
175644961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
175744961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
175844961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
175944961713Sgirish 
176044961713Sgirish 	/*
176144961713Sgirish 	 * Initialise the xcvr advertised capability statistics.
176244961713Sgirish 	 */
176344961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
176444961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
176544961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
176644961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
176744961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
176844961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
176944961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
177044961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
177144961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
177244961713Sgirish 					param_arr[param_anar_asmpause].value;
177344961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
177444961713Sgirish 
177544961713Sgirish 
177644961713Sgirish 	/*
177744961713Sgirish 	 * Check for extended status just in case we're
177844961713Sgirish 	 * running a Gigibit phy.
177944961713Sgirish 	 */
178044961713Sgirish 	if (bmsr.bits.extend_status) {
178144961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
178244961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
178344961713Sgirish 				!= NXGE_OK)
178444961713Sgirish 			goto fail;
178544961713Sgirish 		param_arr[param_anar_1000fdx].value &=
178644961713Sgirish 					esr.bits.link_1000fdx;
178744961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
178844961713Sgirish 
178944961713Sgirish 		statsp->mac_stats.cap_1000fdx =
179044961713Sgirish 			(esr.bits.link_1000Xfdx ||
179144961713Sgirish 				esr.bits.link_1000fdx);
179244961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
179344961713Sgirish 	} else {
179444961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
179544961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
179644961713Sgirish 	}
179744961713Sgirish 
179844961713Sgirish 	/*
179944961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
180044961713Sgirish 	 */
180144961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
180244961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
180344961713Sgirish 
180444961713Sgirish 	/*
180544961713Sgirish 	 * Initialise the link statistics.
180644961713Sgirish 	 */
180744961713Sgirish 	statsp->mac_stats.link_T4 = 0;
180844961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
180944961713Sgirish 	statsp->mac_stats.link_pause = 0;
181044961713Sgirish 	statsp->mac_stats.link_speed = 0;
181144961713Sgirish 	statsp->mac_stats.link_duplex = 0;
181244961713Sgirish 	statsp->mac_stats.link_up = 0;
181344961713Sgirish 
181444961713Sgirish 	/*
181544961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
181644961713Sgirish 	 */
181744961713Sgirish 	bmcr.value = 0;
181844961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
181944961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
182044961713Sgirish 		goto fail;
182144961713Sgirish 
182244961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
182344961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
182444961713Sgirish 		bmcr.bits.loopback = 1;
182544961713Sgirish 		bmcr.bits.enable_autoneg = 0;
182644961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
182744961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
182844961713Sgirish 		bmcr.bits.duplex_mode = 1;
182944961713Sgirish 		param_arr[param_autoneg].value = 0;
183044961713Sgirish 	} else {
183144961713Sgirish 		bmcr.bits.loopback = 0;
183244961713Sgirish 	}
183344961713Sgirish 
183444961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
183544961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
183644961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
183744961713Sgirish 		param_arr[param_autoneg].value = 0;
183844961713Sgirish 		bcm5464r_aux.value = 0;
183944961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
184044961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
184144961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
184244961713Sgirish 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
184344961713Sgirish 				!= NXGE_OK)
184444961713Sgirish 			goto fail;
184544961713Sgirish 	}
184644961713Sgirish 
184744961713Sgirish 	if (param_arr[param_autoneg].value) {
184844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
184944961713Sgirish 				"Restarting Auto-negotiation."));
185044961713Sgirish 		/*
185144961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
185244961713Sgirish 		 */
185344961713Sgirish 		anar.value = 0;
185444961713Sgirish 		anar.bits.selector = 1;
185544961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
185644961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
185744961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
185844961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
185944961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
186044961713Sgirish 		anar.bits.cap_asmpause = 0;
186144961713Sgirish 		anar.bits.cap_pause = 0;
186244961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
186344961713Sgirish 			param_arr[param_anar_100fdx].value ||
186444961713Sgirish 			param_arr[param_anar_10fdx].value) {
186544961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
186644961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
186744961713Sgirish 		}
186844961713Sgirish 
186944961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
187044961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
187144961713Sgirish 				!= NXGE_OK)
187244961713Sgirish 			goto fail;
187344961713Sgirish 		if (bmsr.bits.extend_status) {
187444961713Sgirish 			gcr.value = 0;
187544961713Sgirish 			gcr.bits.ms_mode_en =
187644961713Sgirish 				param_arr[param_master_cfg_enable].value;
187744961713Sgirish 			gcr.bits.master =
187844961713Sgirish 				param_arr[param_master_cfg_value].value;
187944961713Sgirish 			gcr.bits.link_1000fdx =
188044961713Sgirish 				param_arr[param_anar_1000fdx].value;
188144961713Sgirish 			gcr.bits.link_1000hdx =
188244961713Sgirish 				param_arr[param_anar_1000hdx].value;
188344961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
188444961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
188544961713Sgirish 				!= NXGE_OK)
188644961713Sgirish 				goto fail;
188744961713Sgirish 		}
188844961713Sgirish 
188944961713Sgirish 		bmcr.bits.enable_autoneg = 1;
189044961713Sgirish 		bmcr.bits.restart_autoneg = 1;
189144961713Sgirish 
189244961713Sgirish 	} else {
189344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
189444961713Sgirish 		bmcr.bits.speed_1000_sel =
189544961713Sgirish 			param_arr[param_anar_1000fdx].value |
189644961713Sgirish 				param_arr[param_anar_1000hdx].value;
189744961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
189844961713Sgirish 			(param_arr[param_anar_100fdx].value |
189944961713Sgirish 				param_arr[param_anar_100hdx].value);
190044961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
190144961713Sgirish 			statsp->mac_stats.link_speed = 1000;
190244961713Sgirish 			gcr.value = 0;
190344961713Sgirish 			gcr.bits.ms_mode_en =
190444961713Sgirish 				param_arr[param_master_cfg_enable].value;
190544961713Sgirish 			gcr.bits.master =
190644961713Sgirish 				param_arr[param_master_cfg_value].value;
190744961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
190844961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr),
190944961713Sgirish 				gcr.value))
191044961713Sgirish 				!= NXGE_OK)
191144961713Sgirish 				goto fail;
191244961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
191344961713Sgirish 				bmcr.bits.duplex_mode = 1;
191444961713Sgirish 				statsp->mac_stats.link_duplex = 2;
191544961713Sgirish 			} else
191644961713Sgirish 				statsp->mac_stats.link_duplex = 1;
191744961713Sgirish 		} else if (bmcr.bits.speed_sel) {
191844961713Sgirish 			statsp->mac_stats.link_speed = 100;
191944961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
192044961713Sgirish 				bmcr.bits.duplex_mode = 1;
192144961713Sgirish 				statsp->mac_stats.link_duplex = 2;
192244961713Sgirish 			} else
192344961713Sgirish 				statsp->mac_stats.link_duplex = 1;
192444961713Sgirish 		} else {
192544961713Sgirish 			statsp->mac_stats.link_speed = 10;
192644961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
192744961713Sgirish 				bmcr.bits.duplex_mode = 1;
192844961713Sgirish 				statsp->mac_stats.link_duplex = 2;
192944961713Sgirish 			} else
193044961713Sgirish 				statsp->mac_stats.link_duplex = 1;
193144961713Sgirish 		}
193244961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
193344961713Sgirish 			statsp->mac_stats.link_asmpause =
193444961713Sgirish 						statsp->mac_stats.cap_asmpause;
193544961713Sgirish 			statsp->mac_stats.link_pause =
193644961713Sgirish 						statsp->mac_stats.cap_pause;
193744961713Sgirish 		}
193844961713Sgirish 
193944961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
194044961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
194144961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
194244961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
194344961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
194444961713Sgirish 				gcr.value = 0;
194544961713Sgirish 				gcr.bits.ms_mode_en = 1;
194644961713Sgirish 				gcr.bits.master = 1;
194744961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
194844961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gcr),
194944961713Sgirish 					gcr.value))
195044961713Sgirish 					!= NXGE_OK)
195144961713Sgirish 					goto fail;
195244961713Sgirish 				bmcr.value = 0;
195344961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
195444961713Sgirish 				statsp->mac_stats.link_speed = 1000;
195544961713Sgirish 			} else if (statsp->port_stats.lb_mode
195644961713Sgirish 			    == nxge_lb_ext100) {
195744961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
195844961713Sgirish 				bmcr.value = 0;
195944961713Sgirish 				bmcr.bits.speed_sel = 1;
196044961713Sgirish 				bmcr.bits.duplex_mode = 1;
196144961713Sgirish 				statsp->mac_stats.link_speed = 100;
196244961713Sgirish 			} else if (statsp->port_stats.lb_mode
196344961713Sgirish 			    == nxge_lb_ext10) {
196444961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
196544961713Sgirish 				bmcr.value = 0;
196644961713Sgirish 				bmcr.bits.duplex_mode = 1;
196744961713Sgirish 				statsp->mac_stats.link_speed = 10;
196844961713Sgirish 			}
196944961713Sgirish 		}
197044961713Sgirish 	}
197144961713Sgirish 
197244961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
197344961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
197444961713Sgirish 			bmcr.value)) != NXGE_OK)
197544961713Sgirish 		goto fail;
197644961713Sgirish 
197744961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
197844961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
197944961713Sgirish 		goto fail;
198044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
198144961713Sgirish 
198244961713Sgirish 	/*
198344961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
198444961713Sgirish 	 */
198544961713Sgirish 	nxgep->soft_bmsr.value = 0;
198644961713Sgirish 
198744961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
198844961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
198944961713Sgirish 			&nxgep->bmsr.value)) != NXGE_OK)
199044961713Sgirish 		goto fail;
199144961713Sgirish 
199244961713Sgirish 	statsp->mac_stats.xcvr_inits++;
199344961713Sgirish 	nxgep->bmsr.value = 0;
199444961713Sgirish 
199544961713Sgirish fail:
199644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
199744961713Sgirish 			"<== nxge_mii_xcvr_init status 0x%x", status));
199844961713Sgirish 	return (status);
199944961713Sgirish }
200044961713Sgirish 
200144961713Sgirish /* Read from a MII compliant register */
200244961713Sgirish 
200344961713Sgirish nxge_status_t
200444961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
200544961713Sgirish 		uint16_t *value)
200644961713Sgirish {
200744961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
200844961713Sgirish 
200944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
201044961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
201144961713Sgirish 
201244961713Sgirish 	MUTEX_ENTER(&nxge_mii_lock);
201344961713Sgirish 
201444961713Sgirish 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
201544961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
201644961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
201744961713Sgirish 			goto fail;
201844961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
201944961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
202044961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
202144961713Sgirish 			goto fail;
202244961713Sgirish 	} else
202344961713Sgirish 		goto fail;
202444961713Sgirish 
202544961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
202644961713Sgirish 
202744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
202844961713Sgirish 			"xcvr_reg<%d> value=0x%x",
202944961713Sgirish 			xcvr_portn, xcvr_reg, *value));
203044961713Sgirish 	return (NXGE_OK);
203144961713Sgirish fail:
203244961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
203344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
203444961713Sgirish 			"nxge_mii_read: Failed to read mii on xcvr %d",
203544961713Sgirish 			xcvr_portn));
203644961713Sgirish 
203744961713Sgirish 	return (NXGE_ERROR | rs);
203844961713Sgirish }
203944961713Sgirish 
204044961713Sgirish /* Write to a MII compliant Register */
204144961713Sgirish 
204244961713Sgirish nxge_status_t
204344961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
204444961713Sgirish 		uint16_t value)
204544961713Sgirish {
204644961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
204744961713Sgirish 
204844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
204944961713Sgirish 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
205044961713Sgirish 			value));
205144961713Sgirish 
205244961713Sgirish 	MUTEX_ENTER(&nxge_mii_lock);
205344961713Sgirish 
205444961713Sgirish 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
205544961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
205644961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
205744961713Sgirish 			goto fail;
205844961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
205944961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
206044961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
206144961713Sgirish 			goto fail;
206244961713Sgirish 	} else
206344961713Sgirish 		goto fail;
206444961713Sgirish 
206544961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
206644961713Sgirish 
206744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
206844961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
206944961713Sgirish 	return (NXGE_OK);
207044961713Sgirish fail:
207144961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
207244961713Sgirish 
207344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
207444961713Sgirish 			"nxge_mii_write: Failed to write mii on xcvr %d",
207544961713Sgirish 			xcvr_portn));
207644961713Sgirish 
207744961713Sgirish 	return (NXGE_ERROR | rs);
207844961713Sgirish }
207944961713Sgirish 
208044961713Sgirish /* Perform read from Clause45 serdes / transceiver device */
208144961713Sgirish 
208244961713Sgirish nxge_status_t
208344961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
208444961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
208544961713Sgirish {
208644961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
208744961713Sgirish 
208844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
208944961713Sgirish 			xcvr_portn));
209044961713Sgirish 
209144961713Sgirish 	MUTEX_ENTER(&nxge_mdio_lock);
209244961713Sgirish 
209344961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
209444961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
209544961713Sgirish 		goto fail;
209644961713Sgirish 
209744961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
209844961713Sgirish 
209944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
210044961713Sgirish 			xcvr_portn));
210144961713Sgirish 	return (NXGE_OK);
210244961713Sgirish fail:
210344961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
210444961713Sgirish 
210544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
210644961713Sgirish 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
210744961713Sgirish 			xcvr_portn));
210844961713Sgirish 
210944961713Sgirish 	return (NXGE_ERROR | rs);
211044961713Sgirish }
211144961713Sgirish 
211244961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
211344961713Sgirish 
211444961713Sgirish nxge_status_t
211544961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
211644961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
211744961713Sgirish {
211844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
211944961713Sgirish 
212044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
212144961713Sgirish 			xcvr_portn));
212244961713Sgirish 
212344961713Sgirish 	MUTEX_ENTER(&nxge_mdio_lock);
212444961713Sgirish 
212544961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
212644961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
212744961713Sgirish 		goto fail;
212844961713Sgirish 
212944961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
213044961713Sgirish 
213144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
213244961713Sgirish 			xcvr_portn));
213344961713Sgirish 	return (NXGE_OK);
213444961713Sgirish fail:
213544961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
213644961713Sgirish 
213744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
213844961713Sgirish 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
213944961713Sgirish 			xcvr_portn));
214044961713Sgirish 
214144961713Sgirish 	return (NXGE_ERROR | rs);
214244961713Sgirish }
214344961713Sgirish 
214444961713Sgirish 
214544961713Sgirish /* Check MII to see if there is any link status change */
214644961713Sgirish 
214744961713Sgirish nxge_status_t
2148a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
2149a3c5bd6dSspeer 		nxge_link_state_t *link_up)
215044961713Sgirish {
215144961713Sgirish 	p_nxge_param_t	param_arr;
215244961713Sgirish 	p_nxge_stats_t	statsp;
215344961713Sgirish 	p_mii_regs_t	mii_regs;
215444961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
215544961713Sgirish 	mii_anar_t	anar;
215644961713Sgirish 	mii_anlpar_t	anlpar;
215744961713Sgirish 	mii_anar_t	an_common;
215844961713Sgirish 	mii_aner_t	aner;
215944961713Sgirish 	mii_gsr_t	gsr;
216044961713Sgirish 	nxge_status_t	status = NXGE_OK;
216144961713Sgirish 
216244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
216344961713Sgirish 
216444961713Sgirish 	mii_regs = NULL;
216544961713Sgirish 	param_arr = nxgep->param_arr;
216644961713Sgirish 	statsp = nxgep->statsp;
216744961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
2168a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
216944961713Sgirish 
217044961713Sgirish 	if (bmsr_ints.bits.link_status) {
217144961713Sgirish 		if (bmsr.bits.link_status) {
217244961713Sgirish 			soft_bmsr->bits.link_status = 1;
217344961713Sgirish 		} else {
217444961713Sgirish 			statsp->mac_stats.link_up = 0;
217544961713Sgirish 			soft_bmsr->bits.link_status = 0;
217644961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
217744961713Sgirish 					"Link down cable problem"));
2178a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
217944961713Sgirish 		}
218044961713Sgirish 	}
218144961713Sgirish 
218244961713Sgirish 	if (param_arr[param_autoneg].value) {
218344961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
218444961713Sgirish 			if (bmsr.bits.auto_neg_complete)
218544961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
218644961713Sgirish 			else
218744961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
218844961713Sgirish 		}
218944961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
219044961713Sgirish 			statsp->mac_stats.link_T4 = 0;
219144961713Sgirish 			statsp->mac_stats.link_speed = 0;
219244961713Sgirish 			statsp->mac_stats.link_duplex = 0;
219344961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
219444961713Sgirish 			statsp->mac_stats.link_pause = 0;
219544961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
219644961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
219744961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
219844961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
219944961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
220044961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
220144961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
220244961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
220344961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
220444961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
220544961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
220644961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
220744961713Sgirish 		}
220844961713Sgirish 	} else
220944961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
221044961713Sgirish 
221144961713Sgirish 	if ((bmsr_ints.bits.link_status ||
221244961713Sgirish 		bmsr_ints.bits.auto_neg_complete) &&
221344961713Sgirish 		soft_bmsr->bits.link_status &&
221444961713Sgirish 		soft_bmsr->bits.auto_neg_complete) {
221544961713Sgirish 		statsp->mac_stats.link_up = 1;
221644961713Sgirish 		if (param_arr[param_autoneg].value) {
221744961713Sgirish 			if ((status = nxge_mii_read(nxgep,
221844961713Sgirish 				statsp->mac_stats.xcvr_portn,
221944961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anar),
222044961713Sgirish 					&anar.value)) != NXGE_OK)
222144961713Sgirish 				goto fail;
222244961713Sgirish 			if ((status = nxge_mii_read(nxgep,
222344961713Sgirish 				statsp->mac_stats.xcvr_portn,
222444961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
222544961713Sgirish 					&anlpar.value)) != NXGE_OK)
222644961713Sgirish 				goto fail;
222744961713Sgirish 			if ((status = nxge_mii_read(nxgep,
222844961713Sgirish 				statsp->mac_stats.xcvr_portn,
222944961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->aner),
223044961713Sgirish 					&aner.value)) != NXGE_OK)
223144961713Sgirish 				goto fail;
223244961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
223344961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
223444961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
223544961713Sgirish 							anlpar.bits.cap_100fdx;
223644961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
223744961713Sgirish 							anlpar.bits.cap_100hdx;
223844961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
223944961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
224044961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
224144961713Sgirish 						anlpar.bits.cap_asmpause;
224244961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
224344961713Sgirish 			an_common.value = anar.value & anlpar.value;
224444961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
224544961713Sgirish 				param_arr[param_anar_1000hdx].value) {
224644961713Sgirish 				if ((status = nxge_mii_read(nxgep,
224744961713Sgirish 					statsp->mac_stats.xcvr_portn,
224844961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gsr),
224944961713Sgirish 						&gsr.value))
225044961713Sgirish 						!= NXGE_OK)
225144961713Sgirish 					goto fail;
225244961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
225344961713Sgirish 					gsr.bits.link_1000fdx;
225444961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
225544961713Sgirish 					gsr.bits.link_1000hdx;
225644961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
225744961713Sgirish 					gsr.bits.link_1000fdx) {
225844961713Sgirish 					statsp->mac_stats.link_speed = 1000;
225944961713Sgirish 					statsp->mac_stats.link_duplex = 2;
226044961713Sgirish 				} else if (
226144961713Sgirish 					param_arr[param_anar_1000hdx].value &&
226244961713Sgirish 						gsr.bits.link_1000hdx) {
226344961713Sgirish 					statsp->mac_stats.link_speed = 1000;
226444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
226544961713Sgirish 				}
226644961713Sgirish 			}
226744961713Sgirish 			if ((an_common.value != 0) &&
226844961713Sgirish 					!(statsp->mac_stats.link_speed)) {
226944961713Sgirish 				if (an_common.bits.cap_100T4) {
227044961713Sgirish 					statsp->mac_stats.link_T4 = 1;
227144961713Sgirish 					statsp->mac_stats.link_speed = 100;
227244961713Sgirish 					statsp->mac_stats.link_duplex = 1;
227344961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
227444961713Sgirish 					statsp->mac_stats.link_speed = 100;
227544961713Sgirish 					statsp->mac_stats.link_duplex = 2;
227644961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
227744961713Sgirish 					statsp->mac_stats.link_speed = 100;
227844961713Sgirish 					statsp->mac_stats.link_duplex = 1;
227944961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
228044961713Sgirish 					statsp->mac_stats.link_speed = 10;
228144961713Sgirish 					statsp->mac_stats.link_duplex = 2;
228244961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
228344961713Sgirish 					statsp->mac_stats.link_speed = 10;
228444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
228544961713Sgirish 				} else {
228644961713Sgirish 					goto fail;
228744961713Sgirish 				}
228844961713Sgirish 			}
228944961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
229044961713Sgirish 				statsp->mac_stats.link_asmpause =
229144961713Sgirish 					an_common.bits.cap_asmpause;
229244961713Sgirish 				if (statsp->mac_stats.link_asmpause)
229344961713Sgirish 				if ((statsp->mac_stats.cap_pause == 0) &&
229444961713Sgirish 						(statsp->mac_stats.lp_cap_pause
229544961713Sgirish 						== 1))
229644961713Sgirish 						statsp->mac_stats.link_pause
229744961713Sgirish 						= 0;
229844961713Sgirish 					else
229944961713Sgirish 						statsp->mac_stats.link_pause
230044961713Sgirish 						= 1;
230144961713Sgirish 				else
230244961713Sgirish 					statsp->mac_stats.link_pause =
230344961713Sgirish 						an_common.bits.cap_pause;
230444961713Sgirish 			}
230544961713Sgirish 		}
2306a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
2307a3c5bd6dSspeer 	}
2308a3c5bd6dSspeer 
2309a3c5bd6dSspeer 	if (nxgep->link_notify) {
2310a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
2311a3c5bd6dSspeer 				LINK_IS_DOWN);
2312a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
231344961713Sgirish 	}
231444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
231544961713Sgirish 	return (NXGE_OK);
231644961713Sgirish fail:
231744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
231844961713Sgirish 			"nxge_mii_check: Unable to check MII"));
231944961713Sgirish 	return (status);
232044961713Sgirish }
232144961713Sgirish 
232244961713Sgirish /* Add a multicast address entry into the HW hash table */
232344961713Sgirish 
232444961713Sgirish nxge_status_t
232544961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
232644961713Sgirish {
232744961713Sgirish 	uint32_t mchash;
232844961713Sgirish 	p_hash_filter_t hash_filter;
232944961713Sgirish 	uint16_t hash_bit;
233044961713Sgirish 	boolean_t rx_init = B_FALSE;
233144961713Sgirish 	uint_t j;
233244961713Sgirish 	nxge_status_t status = NXGE_OK;
233344961713Sgirish 
233444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
233544961713Sgirish 
233644961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
233744961713Sgirish 	mchash = crc32_mchash(addrp);
233844961713Sgirish 	if (nxgep->hash_filter == NULL) {
233944961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
234044961713Sgirish 			"Allocating hash filter storage."));
234144961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
234244961713Sgirish 					KM_SLEEP);
234344961713Sgirish 	}
234444961713Sgirish 	hash_filter = nxgep->hash_filter;
234544961713Sgirish 	j = mchash / HASH_REG_WIDTH;
234644961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
234744961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
234844961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
234944961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
235044961713Sgirish 		hash_filter->hash_ref_cnt++;
235144961713Sgirish 		rx_init = B_TRUE;
235244961713Sgirish 	}
235344961713Sgirish 	if (rx_init) {
235444961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
235544961713Sgirish 			goto fail;
235644961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
235744961713Sgirish 			goto fail;
235844961713Sgirish 	}
235944961713Sgirish 
236044961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
236144961713Sgirish 
236244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
236344961713Sgirish 
236444961713Sgirish 	return (NXGE_OK);
236544961713Sgirish fail:
236644961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
236744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
236844961713Sgirish 					"Unable to add multicast address"));
236944961713Sgirish 	return (status);
237044961713Sgirish }
237144961713Sgirish 
237244961713Sgirish /* Remove a multicast address entry from the HW hash table */
237344961713Sgirish 
237444961713Sgirish nxge_status_t
237544961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
237644961713Sgirish {
237744961713Sgirish 	uint32_t mchash;
237844961713Sgirish 	p_hash_filter_t hash_filter;
237944961713Sgirish 	uint16_t hash_bit;
238044961713Sgirish 	boolean_t rx_init = B_FALSE;
238144961713Sgirish 	uint_t j;
238244961713Sgirish 	nxge_status_t status = NXGE_OK;
238344961713Sgirish 
238444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
238544961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
238644961713Sgirish 	mchash = crc32_mchash(addrp);
238744961713Sgirish 	if (nxgep->hash_filter == NULL) {
238844961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
238944961713Sgirish 			"Hash filter already de_allocated."));
239044961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
239144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
239244961713Sgirish 		return (NXGE_OK);
239344961713Sgirish 	}
239444961713Sgirish 	hash_filter = nxgep->hash_filter;
239544961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
239644961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
239744961713Sgirish 		j = mchash / HASH_REG_WIDTH;
239844961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
239944961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
240044961713Sgirish 		hash_filter->hash_ref_cnt--;
240144961713Sgirish 		rx_init = B_TRUE;
240244961713Sgirish 	}
240344961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
240444961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
240544961713Sgirish 			"De-allocating hash filter storage."));
240644961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
240744961713Sgirish 		nxgep->hash_filter = NULL;
240844961713Sgirish 	}
240944961713Sgirish 
241044961713Sgirish 	if (rx_init) {
241144961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
241244961713Sgirish 			goto fail;
241344961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
241444961713Sgirish 			goto fail;
241544961713Sgirish 	}
241644961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
241744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
241844961713Sgirish 
241944961713Sgirish 	return (NXGE_OK);
242044961713Sgirish fail:
242144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
242244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
242344961713Sgirish 			"Unable to remove multicast address"));
242444961713Sgirish 
242544961713Sgirish 	return (status);
242644961713Sgirish }
242744961713Sgirish 
242844961713Sgirish /* Set MAC address into MAC address HW registers */
242944961713Sgirish 
243044961713Sgirish nxge_status_t
243144961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
243244961713Sgirish {
243344961713Sgirish 	nxge_status_t status = NXGE_OK;
243444961713Sgirish 
243544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
243644961713Sgirish 
243744961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
243844961713Sgirish 	/*
243944961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
244044961713Sgirish 	 */
244144961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
244244961713Sgirish 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
244344961713Sgirish 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
244444961713Sgirish 		goto nxge_set_mac_addr_exit;
244544961713Sgirish 	}
244644961713Sgirish 	nxgep->ouraddr = *addrp;
244744961713Sgirish 	/*
244844961713Sgirish 	 * Set new interface local address and re-init device.
244944961713Sgirish 	 * This is destructive to any other streams attached
245044961713Sgirish 	 * to this device.
245144961713Sgirish 	 */
245244961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
245344961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
245444961713Sgirish 		goto fail;
245544961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
245644961713Sgirish 		goto fail;
245744961713Sgirish 
245844961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
245944961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
246044961713Sgirish 	goto nxge_set_mac_addr_end;
246144961713Sgirish nxge_set_mac_addr_exit:
246244961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
246344961713Sgirish nxge_set_mac_addr_end:
246444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
246544961713Sgirish 
246644961713Sgirish 	return (NXGE_OK);
246744961713Sgirish fail:
246844961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
246944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
247044961713Sgirish 			"Unable to set mac address"));
247144961713Sgirish 	return (status);
247244961713Sgirish }
247344961713Sgirish 
2474*98ecde52Stm static
2475*98ecde52Stm check_link_state_t
2476*98ecde52Stm nxge_check_link_stop(
2477*98ecde52Stm 	nxge_t *nxge)
2478*98ecde52Stm {
2479*98ecde52Stm 	/* If the poll has been cancelled, return STOP. */
2480*98ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
2481*98ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
2482*98ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
2483*98ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
2484*98ecde52Stm 		cv_broadcast(&nxge->poll_cv);
2485*98ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
2486*98ecde52Stm 
2487*98ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
2488*98ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
2489*98ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
2490*98ecde52Stm 		    nxge->mac.portnum));
2491*98ecde52Stm 		return (CHECK_LINK_STOP);
2492*98ecde52Stm 	}
2493*98ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
2494*98ecde52Stm 
2495*98ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
2496*98ecde52Stm }
2497*98ecde52Stm 
249844961713Sgirish /* Check status of MII (MIF or PCS) link */
249944961713Sgirish 
250044961713Sgirish nxge_status_t
250144961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
250244961713Sgirish {
250344961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
250444961713Sgirish 	mii_anlpar_t anlpar;
250544961713Sgirish 	mii_gsr_t gsr;
250644961713Sgirish 	p_mii_regs_t mii_regs;
250744961713Sgirish 	nxge_status_t status = NXGE_OK;
250844961713Sgirish 	uint8_t portn;
2509a3c5bd6dSspeer 	nxge_link_state_t link_up;
251044961713Sgirish 
2511*98ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
2512*98ecde52Stm 		return (NXGE_ERROR);
2513*98ecde52Stm 
2514*98ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2515*98ecde52Stm 		return (NXGE_OK);
2516*98ecde52Stm 
251744961713Sgirish 	portn = nxgep->mac.portnum;
251844961713Sgirish 
251944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
2520*98ecde52Stm 	    portn));
252144961713Sgirish 
252244961713Sgirish 	mii_regs = NULL;
252344961713Sgirish 
252444961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
252544961713Sgirish 
252644961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
252744961713Sgirish 		goto nxge_check_mii_link_exit;
252844961713Sgirish 
252944961713Sgirish 	if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
253044961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
253144961713Sgirish 		&bmsr_data.value)) != NXGE_OK)
253244961713Sgirish 		goto fail;
253344961713Sgirish 
253444961713Sgirish 	if (nxgep->param_arr[param_autoneg].value) {
253544961713Sgirish 		if ((status = nxge_mii_read(nxgep,
253644961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn,
253744961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->gsr),
253844961713Sgirish 			&gsr.value)) != NXGE_OK)
253944961713Sgirish 			goto fail;
254044961713Sgirish 		if ((status = nxge_mii_read(nxgep,
254144961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn,
254244961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anlpar),
254344961713Sgirish 			&anlpar.value)) != NXGE_OK)
254444961713Sgirish 			goto fail;
254544961713Sgirish 		if (nxgep->statsp->mac_stats.link_up &&
254644961713Sgirish 			((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
254744961713Sgirish 				gsr.bits.link_1000fdx) ||
254844961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
254944961713Sgirish 				gsr.bits.link_1000hdx) ||
255044961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100T4 ^
255144961713Sgirish 				anlpar.bits.cap_100T4) ||
255244961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100fdx ^
255344961713Sgirish 				anlpar.bits.cap_100fdx) ||
255444961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100hdx ^
255544961713Sgirish 				anlpar.bits.cap_100hdx) ||
255644961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_10fdx ^
255744961713Sgirish 				anlpar.bits.cap_10fdx) ||
255844961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_10hdx ^
255944961713Sgirish 				anlpar.bits.cap_10hdx))) {
256044961713Sgirish 			bmsr_data.bits.link_status = 0;
256144961713Sgirish 		}
256244961713Sgirish 	}
256344961713Sgirish 
256444961713Sgirish 	/* Workaround for link down issue */
256544961713Sgirish 	if (bmsr_data.value == 0) {
256644961713Sgirish 		cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
256744961713Sgirish 		goto nxge_check_mii_link_exit;
256844961713Sgirish 	}
256944961713Sgirish 
257044961713Sgirish 	bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
257144961713Sgirish 	nxgep->bmsr.value = bmsr_data.value;
2572a3c5bd6dSspeer 	if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up))
2573*98ecde52Stm 	    != NXGE_OK)
257444961713Sgirish 		goto fail;
257544961713Sgirish 
257644961713Sgirish nxge_check_mii_link_exit:
257744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
2578a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
2579a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
2580a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
2581a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
2582a3c5bd6dSspeer 	}
258344961713Sgirish 
258444961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
258544961713Sgirish 
258644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
2587*98ecde52Stm 	    portn));
258844961713Sgirish 	return (NXGE_OK);
258944961713Sgirish 
259044961713Sgirish fail:
259144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
259244961713Sgirish 
259344961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
259444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2595*98ecde52Stm 	    "nxge_check_mii_link: Failed to check link port<%d>",
2596*98ecde52Stm 	    portn));
259744961713Sgirish 	return (status);
259844961713Sgirish }
259944961713Sgirish 
260044961713Sgirish 
260144961713Sgirish /*ARGSUSED*/
260244961713Sgirish nxge_status_t
260344961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
260444961713Sgirish {
260544961713Sgirish 	uint8_t		portn;
260614ea4bb7Ssd 
260744961713Sgirish 	nxge_status_t	status = NXGE_OK;
260844961713Sgirish 	boolean_t	link_up;
260944961713Sgirish 
2610*98ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
2611*98ecde52Stm 		return (NXGE_ERROR);
2612*98ecde52Stm 
2613*98ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2614*98ecde52Stm 		return (NXGE_OK);
2615*98ecde52Stm 
261644961713Sgirish 	portn = nxgep->mac.portnum;
261744961713Sgirish 
261844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
2619*98ecde52Stm 	    portn));
262044961713Sgirish 
262144961713Sgirish 	status = nxge_check_bcm8704_link(nxgep, &link_up);
262244961713Sgirish 
262344961713Sgirish 	if (status != NXGE_OK)
262444961713Sgirish 		goto fail;
262544961713Sgirish 
262644961713Sgirish 	if (link_up) {
2627a3c5bd6dSspeer 		if (nxgep->link_notify ||
2628a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 0) {
262944961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
263044961713Sgirish 				goto fail;
263144961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
263244961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
263344961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
263444961713Sgirish 
263544961713Sgirish 			nxge_link_is_up(nxgep);
2636a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
263744961713Sgirish 		}
263844961713Sgirish 	} else {
2639a3c5bd6dSspeer 		if (nxgep->link_notify ||
2640a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 1) {
264144961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
264244961713Sgirish 				goto fail;
264344961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
264444961713Sgirish 					"Link down cable problem"));
264544961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
264644961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
264744961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
264844961713Sgirish 
264944961713Sgirish 			nxge_link_is_down(nxgep);
2650a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
265144961713Sgirish 		}
265244961713Sgirish 	}
265344961713Sgirish 
265444961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
265544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
2656*98ecde52Stm 	    portn));
265744961713Sgirish 	return (NXGE_OK);
265844961713Sgirish 
265944961713Sgirish fail:
2660*98ecde52Stm 	(void) nxge_check_link_stop(nxgep);
2661*98ecde52Stm 
266244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2663*98ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
2664*98ecde52Stm 	    portn));
266544961713Sgirish 	return (status);
266644961713Sgirish }
266744961713Sgirish 
266844961713Sgirish 
266944961713Sgirish /* Declare link down */
267044961713Sgirish 
267144961713Sgirish void
267244961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
267344961713Sgirish {
267444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
267544961713Sgirish 
267644961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
267744961713Sgirish 
267844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
267944961713Sgirish }
268044961713Sgirish 
268144961713Sgirish /* Declare link up */
268244961713Sgirish 
268344961713Sgirish void
268444961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
268544961713Sgirish {
268644961713Sgirish 	uint32_t val;
268744961713Sgirish 
268844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
268944961713Sgirish 
269044961713Sgirish 	(void) nxge_xif_init(nxgep);
269144961713Sgirish 
269244961713Sgirish 	/* Clean up symbol errors incurred during link transition */
269344961713Sgirish 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
269444961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
269544961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
269644961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
269744961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
269844961713Sgirish 	}
269944961713Sgirish 
270044961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
270144961713Sgirish 
270244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
270344961713Sgirish }
270444961713Sgirish 
270544961713Sgirish /*
270644961713Sgirish  * Calculate the bit in the multicast address filter
270744961713Sgirish  * that selects the given * address.
270844961713Sgirish  * Note: For GEM, the last 8-bits are used.
270944961713Sgirish  */
271044961713Sgirish uint32_t
271144961713Sgirish crc32_mchash(p_ether_addr_t addr)
271244961713Sgirish {
271344961713Sgirish 	uint8_t *cp;
271444961713Sgirish 	uint32_t crc;
271544961713Sgirish 	uint32_t c;
271644961713Sgirish 	int byte;
271744961713Sgirish 	int bit;
271844961713Sgirish 
271944961713Sgirish 	cp = (uint8_t *)addr;
272044961713Sgirish 	crc = (uint32_t)0xffffffff;
272144961713Sgirish 	for (byte = 0; byte < 6; byte++) {
272244961713Sgirish 		c = (uint32_t)cp[byte];
272344961713Sgirish 		for (bit = 0; bit < 8; bit++) {
272444961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
272544961713Sgirish 				crc = (crc >> 1)^0xedb88320;
272644961713Sgirish 			else
272744961713Sgirish 				crc = (crc >> 1);
272844961713Sgirish 			c >>= 1;
272944961713Sgirish 		}
273044961713Sgirish 	}
273144961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
273244961713Sgirish }
273344961713Sgirish 
273444961713Sgirish /* Reset serdes */
273544961713Sgirish 
273644961713Sgirish nxge_status_t
273744961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
273844961713Sgirish {
273944961713Sgirish 	npi_handle_t		handle;
274044961713Sgirish 
274144961713Sgirish 	handle = nxgep->npi_handle;
274244961713Sgirish 
274344961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
274444961713Sgirish 	drv_usecwait(500);
274544961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
274644961713Sgirish 
274744961713Sgirish 	return (NXGE_OK);
274844961713Sgirish }
274944961713Sgirish 
275044961713Sgirish /* Monitor link status using interrupt or polling */
275144961713Sgirish 
275244961713Sgirish nxge_status_t
275344961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
275444961713Sgirish {
275544961713Sgirish 	nxge_status_t status = NXGE_OK;
275644961713Sgirish 
275744961713Sgirish 	/*
2758*98ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
2759*98ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
276044961713Sgirish 	 */
276144961713Sgirish 	if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
276244961713Sgirish 		return (NXGE_OK);
276344961713Sgirish 
276444961713Sgirish 	if (nxgep->statsp == NULL) {
276544961713Sgirish 		/* stats has not been allocated. */
276644961713Sgirish 		return (NXGE_OK);
276744961713Sgirish 	}
276844961713Sgirish 	/* Don't check link if we're not in internal loopback mode */
276944961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
277044961713Sgirish 		return (NXGE_OK);
277144961713Sgirish 
277244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2773*98ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
2774*98ecde52Stm 	    nxgep->mac.portnum, enable));
277544961713Sgirish 	if (enable == LINK_MONITOR_START) {
277644961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
277744961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
2778*98ecde52Stm 			    != NXGE_OK)
277944961713Sgirish 				goto fail;
278044961713Sgirish 		} else {
2781*98ecde52Stm 			timeout_id_t timerid;
2782*98ecde52Stm 
2783*98ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2784*98ecde52Stm 				return (NXGE_OK);
2785*98ecde52Stm 
278644961713Sgirish 			switch (nxgep->mac.portmode) {
278744961713Sgirish 			case PORT_10G_FIBER:
2788*98ecde52Stm 				timerid = timeout((fptrv_t)nxge_check_10g_link,
2789*98ecde52Stm 				    nxgep,
2790*98ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
2791*98ecde52Stm 				break;
279244961713Sgirish 
279344961713Sgirish 			case PORT_1G_COPPER:
279444961713Sgirish 			case PORT_1G_FIBER:
2795*98ecde52Stm 				timerid = timeout((fptrv_t)nxge_check_mii_link,
2796*98ecde52Stm 				    nxgep,
2797*98ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
2798*98ecde52Stm 				break;
279944961713Sgirish 			default:
2800*98ecde52Stm 				return (NXGE_ERROR);
280144961713Sgirish 			}
2802*98ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
2803*98ecde52Stm 			nxgep->nxge_link_poll_timerid = timerid;
2804*98ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
280544961713Sgirish 		}
280644961713Sgirish 	} else {
280744961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
280844961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
2809*98ecde52Stm 			    != NXGE_OK)
281044961713Sgirish 				goto fail;
281144961713Sgirish 		} else {
2812*98ecde52Stm 			clock_t rv;
2813*98ecde52Stm 
2814*98ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
2815*98ecde52Stm 
2816*98ecde52Stm 			/* If <timerid> == 0, the link monitor has */
2817*98ecde52Stm 			/* never been started, or just now stopped. */
2818*98ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
2819*98ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
2820*98ecde52Stm 				return (NXGE_OK);
2821*98ecde52Stm 			}
2822*98ecde52Stm 
2823*98ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
2824*98ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
2825*98ecde52Stm 			    &nxgep->poll_lock,
2826*98ecde52Stm 			    ddi_get_lbolt() +
2827*98ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
2828*98ecde52Stm 			    LINK_MONITOR_PERIOD));
2829*98ecde52Stm 			if (rv == -1) {
2830*98ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2831*98ecde52Stm 				    "==> stopping port %d: "
2832*98ecde52Stm 				    "cv_timedwait(%d) timed out",
2833*98ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
2834*98ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
283544961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
283644961713Sgirish 			}
2837*98ecde52Stm 
2838*98ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
283944961713Sgirish 		}
284044961713Sgirish 	}
284144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2842*98ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
2843*98ecde52Stm 	    nxgep->mac.portnum, enable));
284444961713Sgirish 	return (NXGE_OK);
284544961713Sgirish fail:
284644961713Sgirish 	return (status);
284744961713Sgirish }
284844961713Sgirish 
284944961713Sgirish /* Set promiscous mode */
285044961713Sgirish 
285144961713Sgirish nxge_status_t
285244961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
285344961713Sgirish {
285444961713Sgirish 	nxge_status_t status = NXGE_OK;
285544961713Sgirish 
285644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
285744961713Sgirish 		"==> nxge_set_promisc: on %d", on));
285844961713Sgirish 
285944961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
286044961713Sgirish 
286144961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
286244961713Sgirish 
286344961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
286444961713Sgirish 		goto fail;
286544961713Sgirish 	}
286644961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
286744961713Sgirish 		goto fail;
286844961713Sgirish 	}
286944961713Sgirish 
287044961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
287144961713Sgirish 
287244961713Sgirish 	if (on)
287344961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
287444961713Sgirish 	else
287544961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
287644961713Sgirish 
287744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
287844961713Sgirish 
287944961713Sgirish 	return (NXGE_OK);
288044961713Sgirish fail:
288144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
288244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
288344961713Sgirish 			"Unable to set promisc (%d)", on));
288444961713Sgirish 
288544961713Sgirish 	return (status);
288644961713Sgirish }
288744961713Sgirish 
288844961713Sgirish /*ARGSUSED*/
288944961713Sgirish uint_t
289044961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
289144961713Sgirish {
289244961713Sgirish #ifdef	NXGE_DEBUG
289344961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
289444961713Sgirish #endif
289544961713Sgirish #if NXGE_MIF
289644961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
289744961713Sgirish 	uint32_t		status;
289844961713Sgirish 	npi_handle_t		handle;
289944961713Sgirish 	uint8_t			portn;
290044961713Sgirish 	p_nxge_stats_t		statsp;
290144961713Sgirish #endif
290244961713Sgirish 
290344961713Sgirish #ifdef	NXGE_MIF
290444961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
290544961713Sgirish 		nxgep = ldvp->nxgep;
290644961713Sgirish 	}
290744961713Sgirish 	nxgep = ldvp->nxgep;
290844961713Sgirish #endif
290944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
291044961713Sgirish 
291144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
291244961713Sgirish 	return (DDI_INTR_CLAIMED);
291344961713Sgirish 
291444961713Sgirish mif_intr_fail:
291544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
291644961713Sgirish 	return (DDI_INTR_UNCLAIMED);
291744961713Sgirish }
291844961713Sgirish 
291944961713Sgirish /*ARGSUSED*/
292044961713Sgirish uint_t
292144961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
292244961713Sgirish {
292344961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
292444961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
292544961713Sgirish 	p_nxge_ldg_t		ldgp;
292644961713Sgirish 	uint32_t		status;
292744961713Sgirish 	npi_handle_t		handle;
292844961713Sgirish 	uint8_t			portn;
292944961713Sgirish 	p_nxge_stats_t		statsp;
293044961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
293144961713Sgirish 
293244961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
293344961713Sgirish 		nxgep = ldvp->nxgep;
293444961713Sgirish 	}
293544961713Sgirish 
293644961713Sgirish 	ldgp = ldvp->ldgp;
293744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
293844961713Sgirish 		"group %d", ldgp->ldg));
293944961713Sgirish 
294044961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
294144961713Sgirish 	/*
294244961713Sgirish 	 * This interrupt handler is for a specific
294344961713Sgirish 	 * mac port.
294444961713Sgirish 	 */
294544961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
294644961713Sgirish 	portn = nxgep->mac.portnum;
294744961713Sgirish 
294844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
294944961713Sgirish 		"==> nxge_mac_intr: reading mac stats: port<%d>", portn));
295044961713Sgirish 
295144961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
295244961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
295344961713Sgirish 					(xmac_tx_iconfig_t *)&status);
295444961713Sgirish 		if (rs != NPI_SUCCESS)
295544961713Sgirish 			goto npi_fail;
295644961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
295744961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
295844961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
295944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
296044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
296144961713Sgirish 			}
296244961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
296344961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
296444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
296544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
296644961713Sgirish 			}
296744961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
296844961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
296944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
297044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
297144961713Sgirish 			}
297244961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
297344961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
297444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
297544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
297644961713Sgirish 			}
297744961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
297844961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
297944961713Sgirish 							XTXMAC_BYTE_CNT_MASK;
298044961713Sgirish 			}
298144961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
298244961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
298344961713Sgirish 							XTXMAC_FRM_CNT_MASK;
298444961713Sgirish 			}
298544961713Sgirish 		}
298644961713Sgirish 
298744961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
298844961713Sgirish 					(xmac_rx_iconfig_t *)&status);
298944961713Sgirish 		if (rs != NPI_SUCCESS)
299044961713Sgirish 			goto npi_fail;
299144961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
299244961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
299344961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
299444961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
299544961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
299644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
299744961713Sgirish 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
299844961713Sgirish 			}
299944961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
300044961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
300144961713Sgirish 							XRXMAC_CRC_ER_CNT_MASK;
300244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
300344961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
300444961713Sgirish 			}
300544961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
300644961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
300744961713Sgirish 							MAC_LEN_ER_CNT_MASK;
300844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
300944961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
301044961713Sgirish 			}
301144961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
301244961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
301344961713Sgirish 							XRXMAC_CD_VIO_CNT_MASK;
301444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
301544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
301644961713Sgirish 			}
301744961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
301844961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
301944961713Sgirish 							XRXMAC_BT_CNT_MASK;
302044961713Sgirish 			}
302144961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
302244961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
302344961713Sgirish 							XRXMAC_HIST_CNT1_MASK;
302444961713Sgirish 			}
302544961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
302644961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
302744961713Sgirish 							XRXMAC_HIST_CNT2_MASK;
302844961713Sgirish 			}
302944961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
303044961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
303144961713Sgirish 							XRXMAC_HIST_CNT3_MASK;
303244961713Sgirish 			}
303344961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
303444961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
303544961713Sgirish 							XRXMAC_HIST_CNT4_MASK;
303644961713Sgirish 			}
303744961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
303844961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
303944961713Sgirish 							XRXMAC_HIST_CNT5_MASK;
304044961713Sgirish 			}
304144961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
304244961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
304344961713Sgirish 							XRXMAC_HIST_CNT6_MASK;
304444961713Sgirish 			}
304544961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
304644961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
304744961713Sgirish 							XRXMAC_BC_FRM_CNT_MASK;
304844961713Sgirish 			}
304944961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
305044961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
305144961713Sgirish 							XRXMAC_MC_FRM_CNT_MASK;
305244961713Sgirish 			}
305344961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
305444961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
305544961713Sgirish 							XRXMAC_FRAG_CNT_MASK;
305644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
305744961713Sgirish 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
305844961713Sgirish 			}
305944961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
306044961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
306144961713Sgirish 							XRXMAC_AL_ER_CNT_MASK;
306244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
306344961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
306444961713Sgirish 			}
306544961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
306644961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
306744961713Sgirish 							XMAC_LINK_FLT_CNT_MASK;
306844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
306944961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
307044961713Sgirish 			}
307144961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
307244961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
307344961713Sgirish 			}
307444961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
307544961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
307644961713Sgirish 			}
307744961713Sgirish 		}
307844961713Sgirish 
307944961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
308044961713Sgirish 						(xmac_ctl_iconfig_t *)&status);
308144961713Sgirish 		if (rs != NPI_SUCCESS)
308244961713Sgirish 			goto npi_fail;
308344961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
308444961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
308544961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
308644961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
308744961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
308844961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
308944961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
309044961713Sgirish 		}
309144961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
309244961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
309344961713Sgirish 						(bmac_tx_iconfig_t *)&status);
309444961713Sgirish 		if (rs != NPI_SUCCESS)
309544961713Sgirish 			goto npi_fail;
309644961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
309744961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
309844961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
309944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
310044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
310144961713Sgirish 			}
310244961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
310344961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
310444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
310544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
310644961713Sgirish 			}
310744961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
310844961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
310944961713Sgirish 							BTXMAC_BYTE_CNT_MASK;
311044961713Sgirish 			}
311144961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
311244961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
311344961713Sgirish 							BTXMAC_FRM_CNT_MASK;
311444961713Sgirish 			}
311544961713Sgirish 		}
311644961713Sgirish 
311744961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
311844961713Sgirish 						(bmac_rx_iconfig_t *)&status);
311944961713Sgirish 		if (rs != NPI_SUCCESS)
312044961713Sgirish 			goto npi_fail;
312144961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
312244961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
312344961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
312444961713Sgirish 			}
312544961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
312644961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
312744961713Sgirish 							RXMAC_FRM_CNT_MASK;
312844961713Sgirish 			}
312944961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
313044961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
313144961713Sgirish 							BMAC_CRC_ER_CNT_MASK;
313244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
313344961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
313444961713Sgirish 			}
313544961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
313644961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
313744961713Sgirish 							MAC_LEN_ER_CNT_MASK;
313844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
313944961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
314044961713Sgirish 			}
314144961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
314244961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
314344961713Sgirish 							BMAC_CD_VIO_CNT_MASK;
314444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
314544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
314644961713Sgirish 			}
314744961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
314844961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
314944961713Sgirish 							BRXMAC_BYTE_CNT_MASK;
315044961713Sgirish 			}
315144961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
315244961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
315344961713Sgirish 							BMAC_AL_ER_CNT_MASK;
315444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
315544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
315644961713Sgirish 			}
315744961713Sgirish 
315844961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
315944961713Sgirish 						(bmac_ctl_iconfig_t *)&status);
316044961713Sgirish 			if (rs != NPI_SUCCESS)
316144961713Sgirish 				goto npi_fail;
316244961713Sgirish 
316344961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
316444961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
316544961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
316644961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
316744961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
316844961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
316944961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
317044961713Sgirish 			}
317144961713Sgirish 		}
317244961713Sgirish 
317344961713Sgirish 	if (ldgp->nldvs == 1) {
317444961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
317544961713Sgirish 			B_TRUE, ldgp->ldg_timer);
317644961713Sgirish 	}
317744961713Sgirish 
317844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
317944961713Sgirish 	return (DDI_INTR_CLAIMED);
318044961713Sgirish 
318144961713Sgirish npi_fail:
318244961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
318344961713Sgirish 	return (DDI_INTR_UNCLAIMED);
318444961713Sgirish }
318544961713Sgirish 
318644961713Sgirish nxge_status_t
318744961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
318844961713Sgirish {
318944961713Sgirish 	uint8_t		phy_port_addr;
319044961713Sgirish 	nxge_status_t	status = NXGE_OK;
319144961713Sgirish 	boolean_t	rx_sig_ok;
319244961713Sgirish 	boolean_t	pcs_blk_lock;
319344961713Sgirish 	boolean_t	link_align;
319444961713Sgirish 	uint16_t	val1, val2, val3;
319544961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
319644961713Sgirish 	uint16_t	val_debug;
319744961713Sgirish 	uint16_t	val;
319844961713Sgirish #endif
319944961713Sgirish 
320044961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
320144961713Sgirish 
320244961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
320344961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
320444961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
320544961713Sgirish 	if ((val_debug & ~0x200) != 0) {
320644961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
320744961713Sgirish 				nxgep->mac.portnum, val_debug);
320844961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
320944961713Sgirish 				&val_debug);
321044961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
321144961713Sgirish 				nxgep->mac.portnum, val_debug);
321244961713Sgirish 	}
321344961713Sgirish 
321444961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
321544961713Sgirish 					XPCS_REG_DESCWERR_COUNTER, &val);
321644961713Sgirish 	if (val != 0)
321744961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
321844961713Sgirish 
321944961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
322044961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
322144961713Sgirish 	if (val != 0)
322244961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
322344961713Sgirish 
322444961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
322544961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
322644961713Sgirish 	if (val != 0)
322744961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
322844961713Sgirish #endif
322944961713Sgirish 
323044961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
323144961713Sgirish 
323244961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
323344961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
323444961713Sgirish 			BCM8704_PMA_PMD_DEV_ADDR,
323544961713Sgirish 			BCM8704_PMD_RECEIVE_SIG_DETECT,
323644961713Sgirish 			&val1);
323744961713Sgirish 	if (status != NXGE_OK)
323844961713Sgirish 		goto fail;
323944961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
324044961713Sgirish 
324144961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
324244961713Sgirish 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
324344961713Sgirish 			BCM8704_PCS_DEV_ADDR,
324444961713Sgirish 			BCM8704_10GBASE_R_PCS_STATUS_REG,
324544961713Sgirish 			&val2)) != NPI_SUCCESS)
324644961713Sgirish 		goto fail;
324744961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
324844961713Sgirish 
324944961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
325044961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
325144961713Sgirish 			BCM8704_PHYXS_ADDR,
325244961713Sgirish 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
325344961713Sgirish 			&val3);
325444961713Sgirish 	if (status != NXGE_OK)
325544961713Sgirish 		goto fail;
325644961713Sgirish 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
325744961713Sgirish 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
325844961713Sgirish 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
325944961713Sgirish 
326044961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
326144961713Sgirish 	/* Temp workaround for link down issue */
326244961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
326344961713Sgirish 		if (val2 != 0x4) {
326444961713Sgirish 			pcs_blk_lock = B_TRUE;
326544961713Sgirish 			cmn_err(CE_NOTE,
326644961713Sgirish 				"!LINK DEBUG: port%d PHY Dev3 "
326744961713Sgirish 				"Reg 0x20 = 0x%x\n",
326844961713Sgirish 				nxgep->mac.portnum, val2);
326944961713Sgirish 		}
327044961713Sgirish 	}
327144961713Sgirish 
327244961713Sgirish 	if (link_align == B_FALSE) {
327344961713Sgirish 		if (val3 != 0x140f) {
327444961713Sgirish 			link_align = B_TRUE;
327544961713Sgirish 			cmn_err(CE_NOTE,
327644961713Sgirish 				"!LINK DEBUG: port%d PHY Dev4 "
327744961713Sgirish 				"Reg 0x18 = 0x%x\n",
327844961713Sgirish 				nxgep->mac.portnum, val3);
327944961713Sgirish 		}
328044961713Sgirish 	}
328144961713Sgirish 
328244961713Sgirish 	if (rx_sig_ok == B_FALSE) {
328344961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
328444961713Sgirish 			rx_sig_ok = B_TRUE;
328544961713Sgirish 			cmn_err(CE_NOTE,
328644961713Sgirish 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
328744961713Sgirish 				nxgep->mac.portnum);
328844961713Sgirish 		}
328944961713Sgirish 	}
329044961713Sgirish #endif
329144961713Sgirish 
329244961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
329344961713Sgirish 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
329444961713Sgirish 
329544961713Sgirish 	return (NXGE_OK);
329644961713Sgirish fail:
329744961713Sgirish 	return (status);
329844961713Sgirish }
329944961713Sgirish 
330044961713Sgirish 
330144961713Sgirish nxge_status_t
330244961713Sgirish nxge_get_xcvr_type(p_nxge_t nxgep)
330344961713Sgirish {
330444961713Sgirish 	nxge_status_t status = NXGE_OK;
330556d930aeSspeer 	char *phy_type;
330644961713Sgirish 	char *prop_val;
330744961713Sgirish 
330856d930aeSspeer 	if (nxgep->niu_type == N2_NIU) {
330956d930aeSspeer 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
331056d930aeSspeer 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
331156d930aeSspeer 			if (strcmp("xgf", prop_val) == 0) {
331256d930aeSspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
331356d930aeSspeer 				    XPCS_XCVR;
331456d930aeSspeer 				nxgep->mac.portmode = PORT_10G_FIBER;
331556d930aeSspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
331656d930aeSspeer 				    "10G Fiber Xcvr"));
331756d930aeSspeer 			} else if (strcmp("mif", prop_val) == 0) {
331856d930aeSspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
331956d930aeSspeer 				    INT_MII_XCVR;
332056d930aeSspeer 				nxgep->mac.portmode = PORT_1G_COPPER;
332156d930aeSspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
332256d930aeSspeer 				    "1G Copper Xcvr"));
332356d930aeSspeer 			} else if (strcmp("pcs", prop_val) == 0) {
332456d930aeSspeer 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
332556d930aeSspeer 				nxgep->mac.portmode = PORT_1G_FIBER;
332656d930aeSspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
332756d930aeSspeer 				    "1G Fiber Xcvr"));
332856d930aeSspeer 			} else if (strcmp("xgc", prop_val) == 0) {
332956d930aeSspeer 				nxgep->statsp->mac_stats.xcvr_inuse =
333056d930aeSspeer 				    XPCS_XCVR;
333156d930aeSspeer 				nxgep->mac.portmode = PORT_10G_COPPER;
333256d930aeSspeer 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
333356d930aeSspeer 				    "10G Copper Xcvr"));
333456d930aeSspeer 			} else {
333556d930aeSspeer 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
333656d930aeSspeer 				    "Unknown phy-type: %s", prop_val));
333756d930aeSspeer 				ddi_prop_free(prop_val);
333856d930aeSspeer 				return (NXGE_ERROR);
333956d930aeSspeer 			}
334056d930aeSspeer 			status = NXGE_OK;
334156d930aeSspeer 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
334256d930aeSspeer 			    nxgep->dip, "phy-type", prop_val);
334356d930aeSspeer 			ddi_prop_free(prop_val);
334456d930aeSspeer 			return (status);
334544961713Sgirish 		} else {
334644961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
334756d930aeSspeer 			    "Exiting...phy-type property not found"));
334844961713Sgirish 			return (NXGE_ERROR);
334944961713Sgirish 		}
335056d930aeSspeer 	}
335156d930aeSspeer 
335256d930aeSspeer 	if (!nxgep->vpd_info.ver_valid) {
335356d930aeSspeer 		/*
335456d930aeSspeer 		 * read the phy type from the SEEPROM - NCR registers
335556d930aeSspeer 		 */
335656d930aeSspeer 		status = nxge_espc_phy_type_get(nxgep);
335756d930aeSspeer 		if (status != NXGE_OK)
335856d930aeSspeer 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
335956d930aeSspeer 			    "[%s] invalid...please update",
336056d930aeSspeer 			    nxgep->vpd_info.ver));
336156d930aeSspeer 		return (status);
336256d930aeSspeer 	}
336356d930aeSspeer 
336456d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
336556d930aeSspeer 	    "Reading phy type from expansion ROM"));
336656d930aeSspeer 	/*
336756d930aeSspeer 	 * Try to read the phy type from the vpd data read off the
336856d930aeSspeer 	 * expansion ROM.
336956d930aeSspeer 	 */
337056d930aeSspeer 	phy_type = nxgep->vpd_info.phy_type;
337156d930aeSspeer 	if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') {
337256d930aeSspeer 		nxgep->mac.portmode = PORT_1G_COPPER;
337356d930aeSspeer 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
337456d930aeSspeer 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
337556d930aeSspeer 	    phy_type[2] == 'f') {
337656d930aeSspeer 		nxgep->mac.portmode = PORT_10G_FIBER;
337756d930aeSspeer 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
337856d930aeSspeer 	} else if (phy_type[0] == 'p' && phy_type[1] == 'c' &&
337956d930aeSspeer 	    phy_type[2] == 's') {
338056d930aeSspeer 		nxgep->mac.portmode = PORT_1G_FIBER;
338156d930aeSspeer 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
338256d930aeSspeer 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
338356d930aeSspeer 	    phy_type[2] == 'c') {
338456d930aeSspeer 		nxgep->mac.portmode = PORT_10G_COPPER;
338556d930aeSspeer 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
338644961713Sgirish 	} else {
338756d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
338856d930aeSspeer 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
338956d930aeSspeer 		    phy_type[0], phy_type[1], phy_type[2]));
339044961713Sgirish 		/*
339156d930aeSspeer 		 * read the phy type from the SEEPROM - NCR registers
339244961713Sgirish 		 */
339356d930aeSspeer 		status = nxge_espc_phy_type_get(nxgep);
339456d930aeSspeer 		if (status != NXGE_OK)
339556d930aeSspeer 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
339656d930aeSspeer 			    "[%s] invalid...please update",
339756d930aeSspeer 			    nxgep->vpd_info.ver));
339844961713Sgirish 	}
339944961713Sgirish 
340044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
340144961713Sgirish 	return (status);
340244961713Sgirish }
340344961713Sgirish 
340444961713Sgirish nxge_status_t
340544961713Sgirish nxge_10g_link_led_on(p_nxge_t nxgep)
340644961713Sgirish {
340744961713Sgirish 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
340844961713Sgirish 							!= NPI_SUCCESS)
340944961713Sgirish 		return (NXGE_ERROR);
341044961713Sgirish 	else
341144961713Sgirish 		return (NXGE_OK);
341244961713Sgirish }
341344961713Sgirish 
341444961713Sgirish nxge_status_t
341544961713Sgirish nxge_10g_link_led_off(p_nxge_t nxgep)
341644961713Sgirish {
341744961713Sgirish 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
341844961713Sgirish 							!= NPI_SUCCESS)
341944961713Sgirish 		return (NXGE_ERROR);
342044961713Sgirish 	else
342144961713Sgirish 		return (NXGE_OK);
342244961713Sgirish }
342356d930aeSspeer 
342456d930aeSspeer boolean_t
342556d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
342656d930aeSspeer {
342756d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
342856d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
342956d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
343056d930aeSspeer 		return (B_FALSE);
343156d930aeSspeer 	else
343256d930aeSspeer 		return (B_TRUE);
343356d930aeSspeer }
3434