xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 4782:e732e74f057e)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
223859Sml29623  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <sys/nxge/nxge_impl.h>
293859Sml29623 #include <sys/nxge/nxge_mac.h>
303859Sml29623 
314693Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
324693Stm144005 #define	LM_WAIT_MULTIPLIER	8
334693Stm144005 
343859Sml29623 extern uint32_t nxge_no_link_notify;
354732Sdavemq extern boolean_t nxge_no_msg;
363859Sml29623 extern uint32_t nxge_lb_dbg;
373859Sml29623 extern nxge_os_mutex_t	nxge_mdio_lock;
383859Sml29623 extern nxge_os_mutex_t	nxge_mii_lock;
393859Sml29623 extern boolean_t nxge_jumbo_enable;
403859Sml29623 
414693Stm144005 typedef enum {
424693Stm144005 	CHECK_LINK_RESCHEDULE,
434693Stm144005 	CHECK_LINK_STOP
444693Stm144005 } check_link_state_t;
454693Stm144005 
464693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
474693Stm144005 
483859Sml29623 /*
493859Sml29623  * Ethernet broadcast address definition.
503859Sml29623  */
513859Sml29623 static ether_addr_st etherbroadcastaddr =
523859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
534732Sdavemq /*
544732Sdavemq  * Ethernet zero address definition.
554732Sdavemq  */
564185Sspeer static ether_addr_st etherzeroaddr =
574185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
584732Sdavemq /*
594732Sdavemq  * Supported chip types
604732Sdavemq  */
614732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
624732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
634732Sdavemq 
644732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
654732Sdavemq 				sizeof (uint32_t))
664732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
674732Sdavemq 				sizeof (uint32_t))
684732Sdavemq /*
694732Sdavemq  * static functions
704732Sdavemq  */
714732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
724732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
734732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
744732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
754732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
764732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
774732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
784732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
794732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
804732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
814732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
824732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
834732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
844732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
854732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
864732Sdavemq 
874732Sdavemq /*
884732Sdavemq  * xcvr tables for supported transceivers
894732Sdavemq  */
904732Sdavemq 
914732Sdavemq static nxge_xcvr_table_t nxge_n2_table = {
924732Sdavemq 	nxge_n2_serdes_init,
934732Sdavemq 	nxge_10G_xcvr_init,
944732Sdavemq 	nxge_10G_link_intr_stop,
954732Sdavemq 	nxge_10G_link_intr_start,
964732Sdavemq 	nxge_check_10g_link,
974732Sdavemq 	BCM8704_DEV_ID,
984732Sdavemq 	PCS_XCVR,
994732Sdavemq 	BCM8704_N2_PORT_ADDR_BASE
1004732Sdavemq };
1014732Sdavemq 
1024732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
1034732Sdavemq 	nxge_neptune_10G_serdes_init,
1044732Sdavemq 	nxge_10G_xcvr_init,
1054732Sdavemq 	nxge_10G_link_intr_stop,
1064732Sdavemq 	nxge_10G_link_intr_start,
1074732Sdavemq 	nxge_check_10g_link,
1084732Sdavemq 	BCM8704_DEV_ID,
1094732Sdavemq 	PCS_XCVR,
1104732Sdavemq 	BCM8704_NEPTUNE_PORT_ADDR_BASE
1114732Sdavemq };
1124732Sdavemq 
1134732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
1144732Sdavemq 	NULL,
1154732Sdavemq 	nxge_1G_xcvr_init,
1164732Sdavemq 	nxge_1G_copper_link_intr_stop,
1174732Sdavemq 	nxge_1G_copper_link_intr_start,
1184732Sdavemq 	nxge_check_mii_link,
1194732Sdavemq 	BCM5464R_PHY_ID,
1204732Sdavemq 	INT_MII_XCVR,
1214732Sdavemq 	BCM5464_NEPTUNE_PORT_ADDR_BASE
1224732Sdavemq };
1234732Sdavemq 
1244732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
1254732Sdavemq 	nxge_1G_serdes_init,
1264732Sdavemq 	nxge_1G_xcvr_init,
1274732Sdavemq 	nxge_1G_fiber_link_intr_stop,
1284732Sdavemq 	nxge_1G_fiber_link_intr_start,
1294732Sdavemq 	nxge_check_mii_link,
1304732Sdavemq 	0,
1314732Sdavemq 	PCS_XCVR,
1324732Sdavemq 	0
1334732Sdavemq };
1344732Sdavemq 
1354732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
1364732Sdavemq 	nxge_neptune_10G_serdes_init,
1374732Sdavemq 	NULL,
1384732Sdavemq 	NULL,
1394732Sdavemq 	NULL,
1404732Sdavemq 	0,
1414732Sdavemq 	PCS_XCVR,
1424732Sdavemq 	0
1434732Sdavemq };
1443859Sml29623 
1453859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
1463859Sml29623 
1474732Sdavemq /* Set up the PHY specific values. */
1484732Sdavemq 
1494732Sdavemq nxge_status_t
1504732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
1514732Sdavemq {
1524732Sdavemq 	nxge_status_t	status = NXGE_OK;
1534732Sdavemq 	uint32_t	port_type;
1544732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1554732Sdavemq 
1564732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
1574732Sdavemq 	    portn));
1584732Sdavemq 
1594732Sdavemq 	if (nxgep->niu_type == N2_NIU) {
1604732Sdavemq 		nxgep->mac.portmode = PORT_10G_FIBER;
1614732Sdavemq 		nxgep->xcvr = nxge_n2_table;
1624732Sdavemq 		nxgep->xcvr.xcvr_addr += portn;
1634732Sdavemq 	} else {
1644732Sdavemq 		port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn);
1654732Sdavemq 		port_type = port_type & (NXGE_PORT_TYPE_MASK);
1664732Sdavemq 		switch (port_type) {
1674732Sdavemq 		case NXGE_PORT_1G_COPPER:
1684732Sdavemq 			nxgep->mac.portmode = PORT_1G_COPPER;
1694732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
1704732Sdavemq 			if (nxgep->nxge_hw_p->platform_type ==
1714732Sdavemq 			    P_NEPTUNE_MARAMBA_P1) {
1724732Sdavemq 				nxgep->xcvr.xcvr_addr =
1734732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
1744732Sdavemq 			} else if (nxgep->nxge_hw_p->platform_type ==
1754732Sdavemq 			    P_NEPTUNE_MARAMBA_P0) {
1764732Sdavemq 				nxgep->xcvr.xcvr_addr =
1774732Sdavemq 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
1784732Sdavemq 			}
1794732Sdavemq 			/*
1804732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
1814732Sdavemq 			 * swapped with ethernet port number. This is
1824732Sdavemq 			 * designed for better signal integrity in routing.
1834732Sdavemq 			 */
1844732Sdavemq 			switch (portn) {
1854732Sdavemq 			case 0:
1864732Sdavemq 				nxgep->xcvr.xcvr_addr += 3;
1874732Sdavemq 				break;
1884732Sdavemq 			case 1:
1894732Sdavemq 				nxgep->xcvr.xcvr_addr += 2;
1904732Sdavemq 				break;
1914732Sdavemq 			case 2:
1924732Sdavemq 				nxgep->xcvr.xcvr_addr += 1;
1934732Sdavemq 				break;
1944732Sdavemq 			case 3:
1954732Sdavemq 				break;
1964732Sdavemq 			default:
1974732Sdavemq 				return (NXGE_ERROR);
1984732Sdavemq 			}
1994732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
2004732Sdavemq 			break;
2014732Sdavemq 		case NXGE_PORT_10G_COPPER:
2024732Sdavemq 			nxgep->mac.portmode = PORT_10G_COPPER;
2034732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
2044732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
2054732Sdavemq 			break;
2064732Sdavemq 		case NXGE_PORT_1G_FIBRE:
2074732Sdavemq 			nxgep->mac.portmode = PORT_1G_FIBER;
2084732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
2094732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr"));
2104732Sdavemq 			break;
2114732Sdavemq 		case NXGE_PORT_10G_FIBRE:
2124732Sdavemq 			nxgep->mac.portmode = PORT_10G_FIBER;
2134732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
2144732Sdavemq 			if ((nxgep->nxge_hw_p->platform_type ==
2154732Sdavemq 			    P_NEPTUNE_MARAMBA_P0) ||
2164732Sdavemq 			    (nxgep->nxge_hw_p->platform_type ==
2174732Sdavemq 			    P_NEPTUNE_MARAMBA_P1)) {
2184732Sdavemq 				nxgep->xcvr.xcvr_addr =
2194732Sdavemq 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
2204732Sdavemq 				/*
2214732Sdavemq 				 * Switch off LED for corresponding copper
2224732Sdavemq 				 * port
2234732Sdavemq 				 */
2244732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
2254732Sdavemq 			}
2264732Sdavemq 			nxgep->xcvr.xcvr_addr += portn;
2274732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr"));
2284732Sdavemq 			break;
2294732Sdavemq 		default:
2304732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2314732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
2324732Sdavemq 			return (NXGE_ERROR);
2334732Sdavemq 		}
2344732Sdavemq 	}
2354732Sdavemq 
2364732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
2374732Sdavemq 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
2384732Sdavemq 	nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id;
2394732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
2404732Sdavemq 
2414732Sdavemq 	return (status);
2424732Sdavemq }
2434732Sdavemq 
2443859Sml29623 /* Initialize the entire MAC and physical layer */
2453859Sml29623 
2463859Sml29623 nxge_status_t
2473859Sml29623 nxge_mac_init(p_nxge_t nxgep)
2483859Sml29623 {
2493859Sml29623 	uint8_t			portn;
2503859Sml29623 	nxge_status_t		status = NXGE_OK;
2513859Sml29623 
2523859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2533859Sml29623 
2543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
2553859Sml29623 
2563859Sml29623 	nxgep->mac.portnum = portn;
2573859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
2583859Sml29623 
2593859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
2603859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
2613859Sml29623 
2623859Sml29623 	/* Initialize XIF to configure a network mode */
2633859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
2643859Sml29623 		goto fail;
2653859Sml29623 	}
2663859Sml29623 
2673859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
2683859Sml29623 		goto fail;
2693859Sml29623 	}
2703859Sml29623 
2713859Sml29623 	/* Initialize TX and RX MACs */
2723859Sml29623 	/*
2733859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
2743859Sml29623 	 */
2753859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
2763859Sml29623 		goto fail;
2773859Sml29623 
2783859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
2793859Sml29623 		goto fail;
2803859Sml29623 
2813859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
2823859Sml29623 		goto fail;
2833859Sml29623 
2843859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
2853859Sml29623 		goto fail;
2863859Sml29623 
2873859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
2883859Sml29623 		goto fail;
2893859Sml29623 
2903859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
2913859Sml29623 		goto fail;
2923859Sml29623 
2933859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
2943859Sml29623 
2953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
2963859Sml29623 
2973859Sml29623 	return (NXGE_OK);
2983859Sml29623 fail:
2993859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3003859Sml29623 			"nxge_mac_init: failed to initialize MAC port<%d>",
3013859Sml29623 			portn));
3023859Sml29623 	return (status);
3033859Sml29623 }
3043859Sml29623 
3053859Sml29623 /* Initialize the Ethernet Link */
3063859Sml29623 
3073859Sml29623 nxge_status_t
3083859Sml29623 nxge_link_init(p_nxge_t nxgep)
3093859Sml29623 {
3103859Sml29623 	nxge_status_t		status = NXGE_OK;
3113859Sml29623 #ifdef	NXGE_DEBUG
3123859Sml29623 	uint8_t			portn;
3133859Sml29623 
3143859Sml29623 	portn = nxgep->mac.portnum;
3153859Sml29623 
3163859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
3173859Sml29623 #endif
3183859Sml29623 
3193859Sml29623 	if (nxgep->niu_type == N2_NIU) {
3203859Sml29623 		/* Workaround to get link up in both NIU ports */
3213859Sml29623 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
3223859Sml29623 			goto fail;
3233859Sml29623 	}
3243859Sml29623 	NXGE_DELAY(200000);
3253859Sml29623 	/* Initialize internal serdes */
3263859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
3273859Sml29623 		goto fail;
3283859Sml29623 	NXGE_DELAY(200000);
3293859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
3303859Sml29623 		goto fail;
3313859Sml29623 
3323859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
3333859Sml29623 
3343859Sml29623 	return (NXGE_OK);
3353859Sml29623 
3363859Sml29623 fail:
3373859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3383859Sml29623 		"nxge_link_init: ",
3393859Sml29623 		"failed to initialize Ethernet link on port<%d>",
3403859Sml29623 		portn));
3413859Sml29623 
3423859Sml29623 	return (status);
3433859Sml29623 }
3443859Sml29623 
3453859Sml29623 
3463859Sml29623 /* Initialize the XIF sub-block within the MAC */
3473859Sml29623 
3483859Sml29623 nxge_status_t
3493859Sml29623 nxge_xif_init(p_nxge_t nxgep)
3503859Sml29623 {
3513859Sml29623 	uint32_t		xif_cfg = 0;
3523859Sml29623 	npi_attr_t		ap;
3533859Sml29623 	uint8_t			portn;
3543859Sml29623 	nxge_port_t		portt;
3553859Sml29623 	nxge_port_mode_t	portmode;
3563859Sml29623 	p_nxge_stats_t		statsp;
3573859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
3583859Sml29623 	npi_handle_t		handle;
3593859Sml29623 
3603859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3613859Sml29623 
3623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
3633859Sml29623 
3643859Sml29623 	handle = nxgep->npi_handle;
3653859Sml29623 	portmode = nxgep->mac.portmode;
3663859Sml29623 	portt = nxgep->mac.porttype;
3673859Sml29623 	statsp = nxgep->statsp;
3683859Sml29623 
3693859Sml29623 	if (portt == PORT_TYPE_XMAC) {
3703859Sml29623 
3713859Sml29623 		/* Setup XIF Configuration for XMAC */
3723859Sml29623 
3733859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
3743859Sml29623 					(portmode == PORT_10G_COPPER))
3753859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
3763859Sml29623 
3773859Sml29623 		if (portmode == PORT_1G_COPPER) {
3783859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
3793859Sml29623 		}
3803859Sml29623 
3813859Sml29623 		/* Set MAC Internal Loopback if necessary */
3823859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
3833859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
3843859Sml29623 
3853859Sml29623 		if (statsp->mac_stats.link_speed == 100)
3863859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
3873859Sml29623 
3883859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
3893859Sml29623 
3903859Sml29623 		if (portmode == PORT_10G_FIBER) {
3913859Sml29623 			if (statsp->mac_stats.link_up) {
3923859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
3933859Sml29623 			} else {
3943859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
3953859Sml29623 			}
3963859Sml29623 		}
3973859Sml29623 
3983859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
3993859Sml29623 		if (rs != NPI_SUCCESS)
4003859Sml29623 			goto fail;
4013859Sml29623 
4023859Sml29623 		nxgep->mac.xif_config = xif_cfg;
4033859Sml29623 
4043859Sml29623 		/* Set Port Mode */
4053859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
4063859Sml29623 					(portmode == PORT_10G_COPPER)) {
4073859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
4083859Sml29623 						MAC_XGMII_MODE, rs);
4093859Sml29623 			if (rs != NPI_SUCCESS)
4103859Sml29623 				goto fail;
4113859Sml29623 			if (statsp->mac_stats.link_up) {
4123859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
4133859Sml29623 					goto fail;
4143859Sml29623 			} else {
4153859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
4163859Sml29623 					goto fail;
4173859Sml29623 			}
4183859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
4193859Sml29623 						(portmode == PORT_1G_COPPER)) {
4203859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
4213859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
4223859Sml29623 							MAC_GMII_MODE, rs);
4233859Sml29623 			} else {
4243859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
4253859Sml29623 							MAC_MII_MODE, rs);
4263859Sml29623 			}
4273859Sml29623 			if (rs != NPI_SUCCESS)
4283859Sml29623 				goto fail;
4293859Sml29623 		} else {
4303859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4313859Sml29623 					"nxge_xif_init: Unknown port mode (%d)"
4323859Sml29623 					" for port<%d>", portmode, portn));
4333859Sml29623 			goto fail;
4343859Sml29623 		}
4353859Sml29623 
4363859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
4373859Sml29623 
4383859Sml29623 		/* Setup XIF Configuration for BMAC */
4393859Sml29623 
4403859Sml29623 		if (portmode == PORT_1G_COPPER) {
4413859Sml29623 			if (statsp->mac_stats.link_speed == 100)
4423859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
4433859Sml29623 		}
4443859Sml29623 
4453859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
4463859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
4473859Sml29623 
4483859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
4493859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
4503859Sml29623 
4513859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
4523859Sml29623 
4533859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
4543859Sml29623 		if (rs != NPI_SUCCESS)
4553859Sml29623 			goto fail;
4563859Sml29623 		nxgep->mac.xif_config = xif_cfg;
4573859Sml29623 	}
4583859Sml29623 
4593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
4603859Sml29623 	return (NXGE_OK);
4613859Sml29623 fail:
4623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4633859Sml29623 			"nxge_xif_init: Failed to initialize XIF port<%d>",
4643859Sml29623 			portn));
4653859Sml29623 	return (NXGE_ERROR | rs);
4663859Sml29623 }
4673859Sml29623 
4683859Sml29623 /* Initialize the PCS sub-block in the MAC */
4693859Sml29623 
4703859Sml29623 nxge_status_t
4713859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
4723859Sml29623 {
4733859Sml29623 	pcs_cfg_t		pcs_cfg;
4743859Sml29623 	uint32_t		val;
4753859Sml29623 	uint8_t			portn;
4763859Sml29623 	nxge_port_mode_t	portmode;
4773859Sml29623 	npi_handle_t		handle;
4783859Sml29623 	p_nxge_stats_t		statsp;
4793859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
4803859Sml29623 
4813859Sml29623 	handle = nxgep->npi_handle;
4823859Sml29623 	portmode = nxgep->mac.portmode;
4833859Sml29623 	portn = nxgep->mac.portnum;
4843859Sml29623 	statsp = nxgep->statsp;
4853859Sml29623 
4863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
4873859Sml29623 
4883859Sml29623 	if (portmode == PORT_1G_FIBER) {
4893859Sml29623 		/* Initialize port's PCS */
4903859Sml29623 		pcs_cfg.value = 0;
4913859Sml29623 		pcs_cfg.bits.w0.enable = 1;
4923859Sml29623 		pcs_cfg.bits.w0.mask = 1;
4933859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
4943859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
4953859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
4963859Sml29623 			goto fail;
4973859Sml29623 
4983859Sml29623 	} else if ((portmode == PORT_10G_FIBER) ||
4993859Sml29623 						(portmode == PORT_10G_COPPER)) {
5003859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
5013859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
5023859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
5033859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
5043859Sml29623 
5053859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
5063859Sml29623 			goto fail;
5073859Sml29623 
5083859Sml29623 		/* Set XPCS Internal Loopback if necessary */
5093859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
5103859Sml29623 						XPCS_REG_CONTROL1, &val))
5113859Sml29623 						!= NPI_SUCCESS)
5123859Sml29623 			goto fail;
5133859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
5143859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
5153859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
5163859Sml29623 		else
5173859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
5183859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
5193859Sml29623 						XPCS_REG_CONTROL1, val))
5203859Sml29623 						!= NPI_SUCCESS)
5213859Sml29623 			goto fail;
5223859Sml29623 
5233859Sml29623 		/* Clear descw errors */
5243859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
5253859Sml29623 						XPCS_REG_DESCWERR_COUNTER, 0))
5263859Sml29623 						!= NPI_SUCCESS)
5273859Sml29623 			goto fail;
5283859Sml29623 		/* Clear symbol errors */
5293859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
5303859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
5313859Sml29623 					!= NPI_SUCCESS)
5323859Sml29623 			goto fail;
5333859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
5343859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
5353859Sml29623 					!= NPI_SUCCESS)
5363859Sml29623 			goto fail;
5373859Sml29623 
5383859Sml29623 	} else if (portmode == PORT_1G_COPPER) {
5393859Sml29623 		if (portn < 4) {
5403859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
5413859Sml29623 					PCS_DATAPATH_MODE_MII);
5423859Sml29623 		}
5433859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
5443859Sml29623 			goto fail;
5453859Sml29623 
5463859Sml29623 	} else {
5473859Sml29623 		goto fail;
5483859Sml29623 	}
5493859Sml29623 pass:
5503859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
5513859Sml29623 	return (NXGE_OK);
5523859Sml29623 fail:
5533859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5543859Sml29623 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
5553859Sml29623 			portn));
5563859Sml29623 	return (NXGE_ERROR | rs);
5573859Sml29623 }
5583859Sml29623 
5593859Sml29623 /* Initialize the Internal Serdes */
5603859Sml29623 
5613859Sml29623 nxge_status_t
5623859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
5633859Sml29623 {
5643859Sml29623 	p_nxge_stats_t		statsp;
5653859Sml29623 #ifdef	NXGE_DEBUG
5663859Sml29623 	uint8_t			portn;
5673859Sml29623 #endif
5683859Sml29623 	nxge_status_t		status = NXGE_OK;
5693859Sml29623 
5703859Sml29623 #ifdef	NXGE_DEBUG
5713859Sml29623 	portn = nxgep->mac.portnum;
5723859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5734732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
5743859Sml29623 #endif
5753859Sml29623 
5764732Sdavemq 	if (nxgep->xcvr.serdes_init) {
5774732Sdavemq 		statsp = nxgep->statsp;
5784732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
5794732Sdavemq 		if (status != NXGE_OK)
5803859Sml29623 			goto fail;
5814732Sdavemq 		statsp->mac_stats.serdes_inits++;
5823859Sml29623 	}
5833859Sml29623 
5843859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
5854732Sdavemq 	    portn));
5863859Sml29623 
5873859Sml29623 	return (NXGE_OK);
5883859Sml29623 
5893859Sml29623 fail:
5903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5914732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
5924732Sdavemq 	    portn));
5933859Sml29623 
5943859Sml29623 	return (status);
5953859Sml29623 }
5963859Sml29623 
5973859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
5983859Sml29623 
5994732Sdavemq static nxge_status_t
6003859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
6013859Sml29623 {
6023859Sml29623 	uint8_t portn;
6033859Sml29623 	int chan;
6043859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
6053859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
6063859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
6073859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
6083859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
6093859Sml29623 	esr_ti_testcfg_t test_cfg;
6103859Sml29623 	nxge_status_t status = NXGE_OK;
6113859Sml29623 
6123859Sml29623 	portn = nxgep->mac.portnum;
6133859Sml29623 
6143859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
6153859Sml29623 			portn));
6163859Sml29623 
6173859Sml29623 	tx_cfg_l.value = 0;
6183859Sml29623 	tx_cfg_h.value = 0;
6193859Sml29623 	rx_cfg_l.value = 0;
6203859Sml29623 	rx_cfg_h.value = 0;
6213859Sml29623 	pll_cfg_l.value = 0;
6223859Sml29623 	test_cfg.value = 0;
6233859Sml29623 
6243859Sml29623 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
6253859Sml29623 		/* 0x0E01 */
6263859Sml29623 		tx_cfg_l.bits.entx = 1;
6273859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
6283859Sml29623 
6293859Sml29623 		/* 0x9101 */
6303859Sml29623 		rx_cfg_l.bits.enrx = 1;
6313859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
6323859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
6333859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
6343859Sml29623 
6353859Sml29623 		/* 0x0008 */
6363859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
6373859Sml29623 
6383859Sml29623 		/* Set loopback mode if necessary */
6393859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
6403859Sml29623 			tx_cfg_l.bits.entest = 1;
6413859Sml29623 			rx_cfg_l.bits.entest = 1;
6423859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
6433859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
6443859Sml29623 				ESR_N2_DEV_ADDR,
6453859Sml29623 				ESR_N2_TEST_CFG_REG, test_cfg.value))
6463859Sml29623 				!= NXGE_OK)
6473859Sml29623 			goto fail;
6483859Sml29623 		}
6493859Sml29623 
6503859Sml29623 		/* Use default PLL value */
6513859Sml29623 
6523859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
6533859Sml29623 
6543859Sml29623 		/* 0x0E21 */
6553859Sml29623 		tx_cfg_l.bits.entx = 1;
6563859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
6573859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
6583859Sml29623 
6593859Sml29623 		/* 0x9121 */
6603859Sml29623 		rx_cfg_l.bits.enrx = 1;
6613859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
6623859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
6633859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
6643859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
6653859Sml29623 
6663859Sml29623 		/* 0x8 */
6673859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
6683859Sml29623 
6693859Sml29623 		/* MPY = 0x100 */
6703859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
6713859Sml29623 
6723859Sml29623 		/* Set PLL */
6733859Sml29623 		pll_cfg_l.bits.enpll = 1;
6743859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
6753859Sml29623 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
6763859Sml29623 				!= NXGE_OK)
6773859Sml29623 			goto fail;
6783859Sml29623 	} else {
6793859Sml29623 		goto fail;
6803859Sml29623 	}
6813859Sml29623 
6823859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
6833859Sml29623 
6843859Sml29623 	NXGE_DELAY(20);
6853859Sml29623 
6863859Sml29623 	/* init TX channels */
6873859Sml29623 	for (chan = 0; chan < 4; chan++) {
6883859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
6893859Sml29623 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
6903859Sml29623 				!= NXGE_OK)
6913859Sml29623 			goto fail;
6923859Sml29623 
6933859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
6943859Sml29623 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
6953859Sml29623 				!= NXGE_OK)
6963859Sml29623 			goto fail;
6973859Sml29623 	}
6983859Sml29623 
6993859Sml29623 	/* init RX channels */
7003859Sml29623 	for (chan = 0; chan < 4; chan++) {
7013859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
7023859Sml29623 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
7033859Sml29623 				!= NXGE_OK)
7043859Sml29623 			goto fail;
7053859Sml29623 
7063859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
7073859Sml29623 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
7083859Sml29623 				!= NXGE_OK)
7093859Sml29623 			goto fail;
7103859Sml29623 	}
7113859Sml29623 
7123859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
7133859Sml29623 			portn));
7143859Sml29623 
7153859Sml29623 	return (NXGE_OK);
7163859Sml29623 fail:
7173859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7183859Sml29623 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
7193859Sml29623 				portn));
7203859Sml29623 
7213859Sml29623 	return (status);
7223859Sml29623 }
7233859Sml29623 
7244732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
7254732Sdavemq 
7264732Sdavemq static nxge_status_t
7274732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
7283859Sml29623 {
7293859Sml29623 	npi_handle_t		handle;
7303859Sml29623 	uint8_t			portn;
7313859Sml29623 	int			chan;
7323859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
7333859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
7343859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
7353859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
7363859Sml29623 	uint64_t		val;
7373859Sml29623 	uint16_t		val16l;
7383859Sml29623 	uint16_t		val16h;
7393859Sml29623 	nxge_status_t		status = NXGE_OK;
7403859Sml29623 
7413859Sml29623 	portn = nxgep->mac.portnum;
7423859Sml29623 
7433859Sml29623 	if ((portn != 0) && (portn != 1))
7443859Sml29623 		return (NXGE_OK);
7453859Sml29623 
7464732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7474732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
7483859Sml29623 
7493859Sml29623 	handle = nxgep->npi_handle;
7504732Sdavemq 	switch (portn) {
7514732Sdavemq 	case 0:
7524732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
7534732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
7544732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
7554732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
7564732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
7574732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
7584732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
7594732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
7604732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
7614732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
7624732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
7634732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
7644732Sdavemq 
7654732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
7664732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
7674732Sdavemq 			ESR_REG_WR(handle,
7684732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
7694732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
7704732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
7714732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
7724732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
7734732Sdavemq 		} else {
7744732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
7753859Sml29623 		}
7764732Sdavemq 		break;
7774732Sdavemq 	case 1:
7784732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
7794732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
7804732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
7814732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
7824732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
7834732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
7844732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
7854732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
7864732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
7874732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
7884732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
7894732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
7904732Sdavemq 
7914732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
7924732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
7934732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
7944732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
7954732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
7964732Sdavemq 		} else {
7974732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
7983859Sml29623 		}
7994732Sdavemq 		break;
8004732Sdavemq 	default:
8014732Sdavemq 		/* Nothing to do here */
8024732Sdavemq 		goto done;
8034732Sdavemq 	}
8044732Sdavemq 
8054732Sdavemq 	/* init TX RX channels */
8064732Sdavemq 	for (chan = 0; chan < 4; chan++) {
8074732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
8084732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
8094732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
8103859Sml29623 			goto fail;
8114732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
8124732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
8134732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
8143859Sml29623 			goto fail;
8153859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
8164732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
8174732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
8183859Sml29623 			goto fail;
8193859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
8204732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
8214732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
8224732Sdavemq 			goto fail;
8234732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
8244732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
8254732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
8264732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
8274732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
8284732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
8294732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
8304732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
8314732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
8324732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
8334732Sdavemq 			goto fail;
8344732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
8354732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
8364732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
8374732Sdavemq 			goto fail;
8384732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
8394732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
8404732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
8414732Sdavemq 			goto fail;
8424732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
8434732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
8444732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
8453859Sml29623 			goto fail;
8463859Sml29623 		}
8473859Sml29623 
8484732Sdavemq 	/* Apply Tx core reset */
8494732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
8504732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
8514732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
8524732Sdavemq 		goto fail;
8534732Sdavemq 
8544732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
8554732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
8564732Sdavemq 	    NXGE_OK)
8574732Sdavemq 		goto fail;
8584732Sdavemq 
8594732Sdavemq 	NXGE_DELAY(200);
8604732Sdavemq 
8614732Sdavemq 	/* Apply Rx core reset */
8624732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
8634732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
8644732Sdavemq 	    NXGE_OK)
8654732Sdavemq 		goto fail;
8664732Sdavemq 
8674732Sdavemq 	NXGE_DELAY(200);
8684732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
8694732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
8704732Sdavemq 		goto fail;
8714732Sdavemq 
8724732Sdavemq 	NXGE_DELAY(200);
8734732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
8744732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
8754732Sdavemq 	    &val16l)) != NXGE_OK)
8764732Sdavemq 		goto fail;
8774732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
8784732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
8794732Sdavemq 		goto fail;
8804732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
8814732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8824732Sdavemq 		    "Failed to reset port<%d> XAUI Serdes", portn));
8834732Sdavemq 	}
8844732Sdavemq 
8854732Sdavemq 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
8864732Sdavemq 
8874732Sdavemq 	if (portn == 0) {
8884732Sdavemq 		if ((val & ESR_SIG_P0_BITS_MASK) !=
8893859Sml29623 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
8903859Sml29623 					ESR_SIG_XSERDES_RDY_P0 |
8913859Sml29623 					ESR_SIG_XDETECT_P0_CH3 |
8923859Sml29623 					ESR_SIG_XDETECT_P0_CH2 |
8933859Sml29623 					ESR_SIG_XDETECT_P0_CH1 |
8943859Sml29623 					ESR_SIG_XDETECT_P0_CH0)) {
8954732Sdavemq 			goto fail;
8964732Sdavemq 		}
8974732Sdavemq 	} else if (portn == 1) {
8984732Sdavemq 		if ((val & ESR_SIG_P1_BITS_MASK) !=
8993859Sml29623 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
9003859Sml29623 					ESR_SIG_XSERDES_RDY_P1 |
9013859Sml29623 					ESR_SIG_XDETECT_P1_CH3 |
9023859Sml29623 					ESR_SIG_XDETECT_P1_CH2 |
9033859Sml29623 					ESR_SIG_XDETECT_P1_CH1 |
9043859Sml29623 					ESR_SIG_XDETECT_P1_CH0)) {
9053859Sml29623 			goto fail;
9063859Sml29623 		}
9073859Sml29623 	}
9083859Sml29623 
9093859Sml29623 done:
9104732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9114732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
9124732Sdavemq 
9133859Sml29623 	return (NXGE_OK);
9143859Sml29623 fail:
9154732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9164732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
9174732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
9183859Sml29623 
9193859Sml29623 	return (status);
9203859Sml29623 }
9213859Sml29623 
9224732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
9234732Sdavemq 
9244732Sdavemq static nxge_status_t
9254732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
9263859Sml29623 {
9274732Sdavemq 	npi_handle_t		handle;
9284732Sdavemq 	uint8_t			portn;
9294732Sdavemq 	uint64_t		val;
9303859Sml29623 
9313859Sml29623 	portn = nxgep->mac.portnum;
9324732Sdavemq 
9334732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9344732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
9354732Sdavemq 
9364732Sdavemq 	handle = nxgep->npi_handle;
9374732Sdavemq 
9384732Sdavemq 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
9394732Sdavemq 	val &= ~ESR_PLL_CFG_FBDIV_2;
9404732Sdavemq 	switch (portn) {
9414732Sdavemq 	case 0:
9424732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_0;
9434732Sdavemq 		break;
9444732Sdavemq 	case 1:
9454732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_1;
9464732Sdavemq 		break;
9474732Sdavemq 	case 2:
9484732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_2;
9494732Sdavemq 		break;
9504732Sdavemq 	case 3:
9514732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_3;
9524732Sdavemq 		break;
9534732Sdavemq 	default:
9544732Sdavemq 		goto fail;
9553859Sml29623 	}
9563859Sml29623 
9574732Sdavemq 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
9584732Sdavemq 
9594732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9604732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
9613859Sml29623 	return (NXGE_OK);
9624732Sdavemq fail:
9634732Sdavemq 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
9644732Sdavemq 	    "nxge_1G_serdes_init: "
9654732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
9664732Sdavemq 	    portn));
9674732Sdavemq 
9684732Sdavemq 	return (NXGE_ERROR);
9693859Sml29623 }
9703859Sml29623 
9714732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */
9724732Sdavemq 
9734732Sdavemq static nxge_status_t
9744732Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep)
9753859Sml29623 {
9763859Sml29623 	p_nxge_stats_t		statsp;
9773859Sml29623 	uint16_t		val;
9783859Sml29623 #ifdef	NXGE_DEBUG
9793859Sml29623 	uint8_t			portn;
9803859Sml29623 	uint16_t		val1;
9813859Sml29623 #endif
9823859Sml29623 	uint8_t			phy_port_addr;
9833859Sml29623 	pmd_tx_control_t	tx_ctl;
9843859Sml29623 	control_t		ctl;
9853859Sml29623 	phyxs_control_t		phyxs_ctl;
9863859Sml29623 	pcs_control_t		pcs_ctl;
9873859Sml29623 	uint32_t		delay = 0;
9883859Sml29623 	optics_dcntr_t		op_ctr;
9893859Sml29623 	nxge_status_t		status = NXGE_OK;
9903859Sml29623 #ifdef	NXGE_DEBUG
9913859Sml29623 	portn = nxgep->mac.portnum;
9923859Sml29623 #endif
9934732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
9944732Sdavemq 	    portn));
9954732Sdavemq 
9964732Sdavemq 	statsp = nxgep->statsp;
9974732Sdavemq 
9984732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
9994732Sdavemq 
10004732Sdavemq 	/* Disable Link LEDs */
10014732Sdavemq 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
10024732Sdavemq 		goto fail;
10034732Sdavemq 
10044732Sdavemq 	/* Set Clause 45 */
10054732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
10064732Sdavemq 
10074732Sdavemq 	/* Reset the transceiver */
10084732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
10094732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
10104732Sdavemq 		goto fail;
10114732Sdavemq 
10124732Sdavemq 	phyxs_ctl.bits.reset = 1;
10134732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
10144732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
10154732Sdavemq 		goto fail;
10164732Sdavemq 
10174732Sdavemq 	do {
10184732Sdavemq 		drv_usecwait(500);
10194732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10204732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
10214732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
10224732Sdavemq 			goto fail;
10234732Sdavemq 		delay++;
10244732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
10254732Sdavemq 	if (delay == 100) {
10264732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
10274732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
10284732Sdavemq 		status = NXGE_ERROR;
10294732Sdavemq 		goto fail;
10304732Sdavemq 	}
10314732Sdavemq 
10324732Sdavemq 	/* Set to 0x7FBF */
10334732Sdavemq 	ctl.value = 0;
10344732Sdavemq 	ctl.bits.res1 = 0x3F;
10354732Sdavemq 	ctl.bits.optxon_lvl = 1;
10364732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
10374732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
10384732Sdavemq 	ctl.bits.optxflt_lvl = 1;
10394732Sdavemq 	ctl.bits.opprflt_lvl = 1;
10404732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
10414732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
10424732Sdavemq 	ctl.bits.optxrst_lvl = 1;
10434732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
10444732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
10454732Sdavemq 	    != NXGE_OK)
10464732Sdavemq 		goto fail;
10474732Sdavemq 
10484732Sdavemq 	/* Set to 0x164 */
10494732Sdavemq 	tx_ctl.value = 0;
10504732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
10514732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
10524732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
10534732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
10544732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
10554732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
10564732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
10574732Sdavemq 		goto fail;
10584732Sdavemq 	/*
10594732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
10604732Sdavemq 	 * back these registers twice after written.
10614732Sdavemq 	 */
10624732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10634732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
10644732Sdavemq 	    != NXGE_OK)
10654732Sdavemq 		goto fail;
10664732Sdavemq 
10674732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10684732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
10694732Sdavemq 	    != NXGE_OK)
10704732Sdavemq 		goto fail;
10714732Sdavemq 
10724732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10734732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
10744732Sdavemq 	    != NXGE_OK)
10754732Sdavemq 		goto fail;
10764732Sdavemq 
10774732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10784732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
10794732Sdavemq 	    != NXGE_OK)
10804732Sdavemq 		goto fail;
10814732Sdavemq 
10824732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
10834732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10844732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
10854732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
10864732Sdavemq 		goto fail;
10874732Sdavemq 	op_ctr.bits.gpio_sel = 0x3;
10884732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
10894732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
10904732Sdavemq 	    op_ctr.value)) != NXGE_OK)
10914732Sdavemq 		goto fail;
10924732Sdavemq 
10934732Sdavemq 	NXGE_DELAY(1000000);
10944732Sdavemq 
10954732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
10964732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
10974732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
10984732Sdavemq 	    != NXGE_OK)
10994732Sdavemq 		goto fail;
11004732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
11014732Sdavemq 		pcs_ctl.bits.loopback = 1;
11024732Sdavemq 	else
11034732Sdavemq 		pcs_ctl.bits.loopback = 0;
11044732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
11054732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
11064732Sdavemq 	    != NXGE_OK)
11074732Sdavemq 		goto fail;
11084732Sdavemq 
11094732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
11104732Sdavemq 	if (status != NXGE_OK)
11114732Sdavemq 		goto fail;
11124732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11134732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
11144732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
11154732Sdavemq 	if (status != NXGE_OK)
11164732Sdavemq 		goto fail;
11174732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11184732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
11194732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
11204732Sdavemq 	if (status != NXGE_OK)
11214732Sdavemq 		goto fail;
11224732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11234732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
11244732Sdavemq 
11254732Sdavemq #ifdef	NXGE_DEBUG
11264732Sdavemq 	/* Diagnose link issue if link is not up */
11274732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
11284732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
11294732Sdavemq 	    &val);
11304732Sdavemq 	if (status != NXGE_OK)
11314732Sdavemq 		goto fail;
11324732Sdavemq 
11334732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
11344732Sdavemq 				BCM8704_USER_DEV3_ADDR,
11354732Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
11364732Sdavemq 				&val);
11374732Sdavemq 	if (status != NXGE_OK)
11384732Sdavemq 		goto fail;
11394732Sdavemq 
11404732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
11414732Sdavemq 				BCM8704_USER_DEV3_ADDR,
11424732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
11434732Sdavemq 				&val1);
11444732Sdavemq 	if (status != NXGE_OK)
11454732Sdavemq 		goto fail;
11464732Sdavemq 
11474732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
11484732Sdavemq 				BCM8704_USER_DEV3_ADDR,
11494732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
11504732Sdavemq 				&val1);
11514732Sdavemq 	if (status != NXGE_OK)
11524732Sdavemq 		goto fail;
11534732Sdavemq 
11544732Sdavemq 	if (val != 0x3FC) {
11554732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
11564732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11574732Sdavemq 			    "Cable not connected to peer or bad"
11584732Sdavemq 			    " cable on port<%d>\n", portn));
11594732Sdavemq 		} else if (val == 0x639C) {
11604732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
11614732Sdavemq 			    "Optical module (XFP) is bad or absent"
11624732Sdavemq 			    " on port<%d>\n", portn));
11634732Sdavemq 		}
11644732Sdavemq 	}
11654732Sdavemq #endif
11664732Sdavemq 
11674732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
11684732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
11694732Sdavemq 
11704732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
11714732Sdavemq 	    portn));
11724732Sdavemq 	return (NXGE_OK);
11734732Sdavemq 
11744732Sdavemq fail:
11754732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11764732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
11774732Sdavemq 	    "port<%d>", portn));
11784732Sdavemq 	return (status);
11794732Sdavemq }
11804732Sdavemq 
11814732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
11824732Sdavemq 
11834732Sdavemq static nxge_status_t
11844732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
11854732Sdavemq {
11864732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
11874732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
11884732Sdavemq 	nxge_status_t		status = NXGE_OK;
11894732Sdavemq 
11904732Sdavemq 	/* Set Clause 22 */
11914732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
11924732Sdavemq 
11934732Sdavemq 	/* Set capability flags */
11944732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
11954732Sdavemq 	statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value;
11964732Sdavemq 	statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
11974732Sdavemq 
11984732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
11994732Sdavemq 
12004732Sdavemq 	return (status);
12014732Sdavemq }
12024732Sdavemq 
12034732Sdavemq /* Initialize transceiver */
12044732Sdavemq 
12054732Sdavemq nxge_status_t
12064732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
12074732Sdavemq {
12084732Sdavemq 	p_nxge_stats_t		statsp;
12094732Sdavemq #ifdef	NXGE_DEBUG
12104732Sdavemq 	uint8_t			portn;
12114732Sdavemq #endif
12124732Sdavemq 
12134732Sdavemq 	nxge_status_t		status = NXGE_OK;
12144732Sdavemq #ifdef	NXGE_DEBUG
12154732Sdavemq 	portn = nxgep->mac.portnum;
12164732Sdavemq #endif
12173859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
12183859Sml29623 	statsp = nxgep->statsp;
12193859Sml29623 
12203859Sml29623 	/*
12213859Sml29623 	 * Initialize the xcvr statistics.
12223859Sml29623 	 */
12233859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
12243859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
12253859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
12263859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
12273859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
12283859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
12293859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
12303859Sml29623 	statsp->mac_stats.cap_pause = 0;
12313859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
12323859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
12333859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
12343859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
12353859Sml29623 
12363859Sml29623 	/*
12373859Sml29623 	 * Initialize the link statistics.
12383859Sml29623 	 */
12393859Sml29623 	statsp->mac_stats.link_T4 = 0;
12403859Sml29623 	statsp->mac_stats.link_asmpause = 0;
12413859Sml29623 	statsp->mac_stats.link_pause = 0;
12423859Sml29623 
12434732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
12444732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
12453859Sml29623 		if (status != NXGE_OK)
12463859Sml29623 			goto fail;
12474732Sdavemq 		statsp->mac_stats.xcvr_inits++;
12483859Sml29623 	}
12493859Sml29623 
12504732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
12514732Sdavemq 	    portn));
12523859Sml29623 	return (NXGE_OK);
12533859Sml29623 
12543859Sml29623 fail:
12553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12564732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
12574732Sdavemq 	    portn));
12583859Sml29623 	return (status);
12593859Sml29623 }
12603859Sml29623 
12613859Sml29623 
12623859Sml29623 /* Initialize the TxMAC sub-block */
12633859Sml29623 
12643859Sml29623 nxge_status_t
12653859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
12663859Sml29623 {
12673859Sml29623 	npi_attr_t		ap;
12683859Sml29623 	uint8_t			portn;
12693859Sml29623 	nxge_port_mode_t	portmode;
12703859Sml29623 	nxge_port_t		portt;
12713859Sml29623 	npi_handle_t		handle;
12723859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
12733859Sml29623 
12743859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
12753859Sml29623 	portt    = nxgep->mac.porttype;
12763859Sml29623 	handle   = nxgep->npi_handle;
12773859Sml29623 	portmode = nxgep->mac.portmode;
12783859Sml29623 
12793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
12803859Sml29623 			portn));
12813859Sml29623 
12823859Sml29623 	/* Set Max and Min Frame Size */
12833859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
12843859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
12853859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
12863859Sml29623 	} else {
12873859Sml29623 		SET_MAC_ATTR2(handle, ap, portn,
12883859Sml29623 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
12893859Sml29623 	}
12903859Sml29623 
12913859Sml29623 	if (rs != NPI_SUCCESS)
12923859Sml29623 		goto fail;
12933859Sml29623 	if (nxgep->param_arr[param_accept_jumbo].value ||
12943859Sml29623 		nxgep->mac.is_jumbo == B_TRUE)
12953859Sml29623 		nxgep->mac.maxframesize = 0x2400;
12963859Sml29623 	else
12973859Sml29623 		nxgep->mac.maxframesize = 0x5EE + 4;
12983859Sml29623 	nxgep->mac.minframesize = 64;
12993859Sml29623 
13003859Sml29623 	if (portt == PORT_TYPE_XMAC) {
13013859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
13023859Sml29623 				0)) != NPI_SUCCESS)
13033859Sml29623 			goto fail;
13043859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
13053859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
13063859Sml29623 					(portmode == PORT_10G_COPPER)) {
13073859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
13083859Sml29623 					XGMII_IPG_12_15, rs);
13093859Sml29623 			if (rs != NPI_SUCCESS)
13103859Sml29623 				goto fail;
13113859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
13123859Sml29623 		} else {
13133859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
13143859Sml29623 					MII_GMII_IPG_12, rs);
13153859Sml29623 			if (rs != NPI_SUCCESS)
13163859Sml29623 				goto fail;
13173859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
13183859Sml29623 		}
13193859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
13203859Sml29623 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
13213859Sml29623 			goto fail;
13223859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
13233859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
13243859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
13253859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
13263859Sml29623 
13273859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
13283859Sml29623 							!= NPI_SUCCESS)
13293859Sml29623 			goto fail;
13303859Sml29623 
13313859Sml29623 	} else {
13323859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
13333859Sml29623 				0)) != NPI_SUCCESS)
13343859Sml29623 			goto fail;
13353859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
13363859Sml29623 
13373859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
13383859Sml29623 				rs);
13393859Sml29623 		if (rs != NPI_SUCCESS)
13403859Sml29623 			goto fail;
13413859Sml29623 		nxgep->mac.ctrltype = 0x8808;
13423859Sml29623 
13433859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
13443859Sml29623 		if (rs != NPI_SUCCESS)
13453859Sml29623 			goto fail;
13463859Sml29623 		nxgep->mac.pa_size = 0x7;
13473859Sml29623 
13483859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
13493859Sml29623 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
13503859Sml29623 			goto fail;
13513859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
13523859Sml29623 	}
13533859Sml29623 
13543859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
13553859Sml29623 			portn));
13563859Sml29623 
13573859Sml29623 	return (NXGE_OK);
13583859Sml29623 fail:
13593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13603859Sml29623 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
13613859Sml29623 					portn));
13623859Sml29623 
13633859Sml29623 	return (NXGE_ERROR | rs);
13643859Sml29623 }
13653859Sml29623 
13663859Sml29623 /* Initialize the RxMAC sub-block */
13673859Sml29623 
13683859Sml29623 nxge_status_t
13693859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
13703859Sml29623 {
13713859Sml29623 	npi_attr_t		ap;
13723859Sml29623 	uint32_t		i;
13733859Sml29623 	uint16_t		hashtab_e;
13743859Sml29623 	p_hash_filter_t		hash_filter;
13753859Sml29623 	nxge_port_t		portt;
13763859Sml29623 	uint8_t			portn;
13773859Sml29623 	npi_handle_t		handle;
13783859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
13793859Sml29623 	uint16_t 		*addr16p;
13803859Sml29623 	uint16_t 		addr0, addr1, addr2;
13813859Sml29623 	xmac_rx_config_t	xconfig;
13823859Sml29623 	bmac_rx_config_t	bconfig;
13833859Sml29623 
13843859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
13853859Sml29623 
13863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
13873859Sml29623 			portn));
13883859Sml29623 	handle = nxgep->npi_handle;
13893859Sml29623 	portt = nxgep->mac.porttype;
13903859Sml29623 
13913859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
13923859Sml29623 	addr0 = ntohs(addr16p[2]);
13933859Sml29623 	addr1 = ntohs(addr16p[1]);
13943859Sml29623 	addr2 = ntohs(addr16p[0]);
13953859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
13963859Sml29623 		rs);
13973859Sml29623 
13983859Sml29623 	if (rs != NPI_SUCCESS)
13993859Sml29623 		goto fail;
14003859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
14013859Sml29623 	if (rs != NPI_SUCCESS)
14023859Sml29623 		goto fail;
14033859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
14043859Sml29623 	if (rs != NPI_SUCCESS)
14053859Sml29623 		goto fail;
14063859Sml29623 
14073859Sml29623 	/*
14083859Sml29623 	 * Load the multicast hash filter bits.
14093859Sml29623 	 */
14103859Sml29623 	hash_filter = nxgep->hash_filter;
14113859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
14123859Sml29623 		if (hash_filter != NULL) {
14133859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
14143859Sml29623 				(NMCFILTER_REGS - 1) - i];
14153859Sml29623 		} else {
14163859Sml29623 			hashtab_e = 0;
14173859Sml29623 		}
14183859Sml29623 
14193859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
14203859Sml29623 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
14213859Sml29623 			goto fail;
14223859Sml29623 	}
14233859Sml29623 
14243859Sml29623 	if (portt == PORT_TYPE_XMAC) {
14253859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
14263859Sml29623 				0)) != NPI_SUCCESS)
14273859Sml29623 			goto fail;
14283859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
14293859Sml29623 
14303859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
14313859Sml29623 
14323859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
14333859Sml29623 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
14343859Sml29623 			~CFG_XMAC_RX_STRIP_CRC;
14353859Sml29623 
14363859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
14373859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
14383859Sml29623 
14393859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
14403859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
14413859Sml29623 
14423859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
14433859Sml29623 
14443859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
14453859Sml29623 					xconfig)) != NPI_SUCCESS)
14463859Sml29623 			goto fail;
14473859Sml29623 		nxgep->mac.rx_config = xconfig;
14483859Sml29623 
14493859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
14503859Sml29623 
14513859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
14523859Sml29623 							!= NPI_SUCCESS)
14533859Sml29623 			goto fail;
14543859Sml29623 	} else {
14553859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
14563859Sml29623 
14573859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
14583859Sml29623 					0) != NPI_SUCCESS)
14593859Sml29623 			goto fail;
14603859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
14613859Sml29623 
14623859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
14633859Sml29623 			~CFG_BMAC_RX_STRIP_CRC;
14643859Sml29623 
14653859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
14663859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
14673859Sml29623 
14683859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
14693859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
14703859Sml29623 
14713859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
14723859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
14733859Sml29623 					bconfig)) != NPI_SUCCESS)
14743859Sml29623 			goto fail;
14753859Sml29623 		nxgep->mac.rx_config = bconfig;
14763859Sml29623 
14773859Sml29623 		/* Always enable comparison of mac unique address */
14783859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
14793859Sml29623 					!= NPI_SUCCESS)
14803859Sml29623 			goto fail;
14813859Sml29623 	}
14823859Sml29623 
14833859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
14843859Sml29623 			portn));
14853859Sml29623 
14863859Sml29623 	return (NXGE_OK);
14873859Sml29623 
14883859Sml29623 fail:
14893859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14903859Sml29623 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
14913859Sml29623 				portn));
14923859Sml29623 
14933859Sml29623 	return (NXGE_ERROR | rs);
14943859Sml29623 }
14953859Sml29623 
14963859Sml29623 /* Enable TXMAC */
14973859Sml29623 
14983859Sml29623 nxge_status_t
14993859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
15003859Sml29623 {
15013859Sml29623 	npi_handle_t	handle;
15023859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15033859Sml29623 	nxge_status_t	status = NXGE_OK;
15043859Sml29623 
15053859Sml29623 	handle = nxgep->npi_handle;
15063859Sml29623 
15073859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
15083859Sml29623 			nxgep->mac.portnum));
15093859Sml29623 
15103859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
15113859Sml29623 		goto fail;
15123859Sml29623 
15133859Sml29623 	/* based on speed */
15143859Sml29623 	nxgep->msg_min = ETHERMIN;
15153859Sml29623 
15163859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15173859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
15183859Sml29623 						CFG_XMAC_TX)) != NPI_SUCCESS)
15193859Sml29623 			goto fail;
15203859Sml29623 	} else {
15213859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
15223859Sml29623 						CFG_BMAC_TX)) != NPI_SUCCESS)
15233859Sml29623 			goto fail;
15243859Sml29623 	}
15253859Sml29623 
15263859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
15273859Sml29623 			nxgep->mac.portnum));
15283859Sml29623 
15293859Sml29623 	return (NXGE_OK);
15303859Sml29623 fail:
15313859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15323859Sml29623 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
15333859Sml29623 			nxgep->mac.portnum));
15343859Sml29623 	if (rs != NPI_SUCCESS)
15353859Sml29623 		return (NXGE_ERROR | rs);
15363859Sml29623 	else
15373859Sml29623 		return (status);
15383859Sml29623 }
15393859Sml29623 
15403859Sml29623 /* Disable TXMAC */
15413859Sml29623 
15423859Sml29623 nxge_status_t
15433859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
15443859Sml29623 {
15453859Sml29623 	npi_handle_t	handle;
15463859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15473859Sml29623 
15483859Sml29623 	handle = nxgep->npi_handle;
15493859Sml29623 
15503859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
15513859Sml29623 			nxgep->mac.portnum));
15523859Sml29623 
15533859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15543859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
15553859Sml29623 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
15563859Sml29623 			goto fail;
15573859Sml29623 	} else {
15583859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
15593859Sml29623 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
15603859Sml29623 			goto fail;
15613859Sml29623 	}
15623859Sml29623 
15633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
15643859Sml29623 			nxgep->mac.portnum));
15653859Sml29623 	return (NXGE_OK);
15663859Sml29623 fail:
15673859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15683859Sml29623 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
15693859Sml29623 			nxgep->mac.portnum));
15703859Sml29623 	return (NXGE_ERROR | rs);
15713859Sml29623 }
15723859Sml29623 
15733859Sml29623 /* Enable RXMAC */
15743859Sml29623 
15753859Sml29623 nxge_status_t
15763859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
15773859Sml29623 {
15783859Sml29623 	npi_handle_t	handle;
15793859Sml29623 	uint8_t 	portn;
15803859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
15813859Sml29623 	nxge_status_t	status = NXGE_OK;
15823859Sml29623 
15833859Sml29623 	handle = nxgep->npi_handle;
15843859Sml29623 	portn = nxgep->mac.portnum;
15853859Sml29623 
15863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
15873859Sml29623 			portn));
15883859Sml29623 
15893859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
15903859Sml29623 		goto fail;
15913859Sml29623 
15923859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
15933859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
15943859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
15953859Sml29623 			goto fail;
15963859Sml29623 	} else {
15973859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
15983859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
15993859Sml29623 			goto fail;
16003859Sml29623 	}
16013859Sml29623 
16023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
16033859Sml29623 			portn));
16043859Sml29623 
16053859Sml29623 	return (NXGE_OK);
16063859Sml29623 fail:
16073859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16083859Sml29623 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
16093859Sml29623 			portn));
16103859Sml29623 
16113859Sml29623 	if (rs != NPI_SUCCESS)
16123859Sml29623 		return (NXGE_ERROR | rs);
16133859Sml29623 	else
16143859Sml29623 		return (status);
16153859Sml29623 }
16163859Sml29623 
16173859Sml29623 /* Disable RXMAC */
16183859Sml29623 
16193859Sml29623 nxge_status_t
16203859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
16213859Sml29623 {
16223859Sml29623 	npi_handle_t	handle;
16233859Sml29623 	uint8_t		portn;
16243859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
16253859Sml29623 
16263859Sml29623 	handle = nxgep->npi_handle;
16273859Sml29623 	portn = nxgep->mac.portnum;
16283859Sml29623 
16293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
16303859Sml29623 			portn));
16313859Sml29623 
16323859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
16333859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
16343859Sml29623 						CFG_XMAC_RX)) != NPI_SUCCESS)
16353859Sml29623 			goto fail;
16363859Sml29623 	} else {
16373859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
16383859Sml29623 						CFG_BMAC_RX)) != NPI_SUCCESS)
16393859Sml29623 			goto fail;
16403859Sml29623 	}
16413859Sml29623 
16423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
16433859Sml29623 			portn));
16443859Sml29623 	return (NXGE_OK);
16453859Sml29623 fail:
16463859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16473859Sml29623 			"nxgep_rx_mac_disable: ",
16483859Sml29623 			"Failed to disable port<%d> RxMAC",
16493859Sml29623 			portn));
16503859Sml29623 
16513859Sml29623 	return (NXGE_ERROR | rs);
16523859Sml29623 }
16533859Sml29623 
16543859Sml29623 /* Reset TXMAC */
16553859Sml29623 
16563859Sml29623 nxge_status_t
16573859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
16583859Sml29623 {
16593859Sml29623 	npi_handle_t	handle;
16603859Sml29623 	uint8_t		portn;
16613859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
16623859Sml29623 
16633859Sml29623 	handle = nxgep->npi_handle;
16643859Sml29623 	portn = nxgep->mac.portnum;
16653859Sml29623 
16663859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
16673859Sml29623 			portn));
16683859Sml29623 
16693859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
16703859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
16713859Sml29623 		    != NPI_SUCCESS)
16723859Sml29623 			goto fail;
16733859Sml29623 	} else {
16743859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
16753859Sml29623 					!= NPI_SUCCESS)
16763859Sml29623 			goto fail;
16773859Sml29623 	}
16783859Sml29623 
16793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
16803859Sml29623 			portn));
16813859Sml29623 
16823859Sml29623 	return (NXGE_OK);
16833859Sml29623 fail:
16843859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16853859Sml29623 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
16863859Sml29623 			portn));
16873859Sml29623 
16883859Sml29623 	return (NXGE_ERROR | rs);
16893859Sml29623 }
16903859Sml29623 
16913859Sml29623 /* Reset RXMAC */
16923859Sml29623 
16933859Sml29623 nxge_status_t
16943859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
16953859Sml29623 {
16963859Sml29623 	npi_handle_t	handle;
16973859Sml29623 	uint8_t		portn;
16983859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
16993859Sml29623 
17003859Sml29623 	handle = nxgep->npi_handle;
17013859Sml29623 	portn = nxgep->mac.portnum;
17023859Sml29623 
17033859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
17043859Sml29623 			portn));
17053859Sml29623 
17063859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
17073859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
17083859Sml29623 		    != NPI_SUCCESS)
17093859Sml29623 		goto fail;
17103859Sml29623 	} else {
17113859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
17123859Sml29623 					!= NPI_SUCCESS)
17133859Sml29623 		goto fail;
17143859Sml29623 	}
17153859Sml29623 
17163859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
17173859Sml29623 			portn));
17183859Sml29623 
17193859Sml29623 	return (NXGE_OK);
17203859Sml29623 fail:
17213859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17223859Sml29623 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
17233859Sml29623 			portn));
17243859Sml29623 	return (NXGE_ERROR | rs);
17253859Sml29623 }
17263859Sml29623 
17274732Sdavemq /* 10G fiber link interrupt start routine */
17284732Sdavemq 
17294732Sdavemq static nxge_status_t
17304732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
17314732Sdavemq {
17324732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
17334732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
17344732Sdavemq 
17354732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
17364732Sdavemq 
17374732Sdavemq 	if (rs != NPI_SUCCESS)
17384732Sdavemq 		return (NXGE_ERROR | rs);
17394732Sdavemq 	else
17404732Sdavemq 		return (NXGE_OK);
17414732Sdavemq }
17424732Sdavemq 
17434732Sdavemq /* 10G fiber link interrupt stop routine */
17444732Sdavemq 
17454732Sdavemq static nxge_status_t
17464732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
17474732Sdavemq {
17484732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
17494732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
17504732Sdavemq 
17514732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
17524732Sdavemq 
17534732Sdavemq 	if (rs != NPI_SUCCESS)
17544732Sdavemq 		return (NXGE_ERROR | rs);
17554732Sdavemq 	else
17564732Sdavemq 		return (NXGE_OK);
17574732Sdavemq }
17584732Sdavemq 
17594732Sdavemq /* 1G fiber link interrupt start routine */
17604732Sdavemq 
17614732Sdavemq static nxge_status_t
17624732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
17634732Sdavemq {
17644732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
17654732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
17664732Sdavemq 
17674732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
17684732Sdavemq 	if (rs != NPI_SUCCESS)
17694732Sdavemq 		return (NXGE_ERROR | rs);
17704732Sdavemq 	else
17714732Sdavemq 		return (NXGE_OK);
17724732Sdavemq }
17734732Sdavemq 
17744732Sdavemq /* 1G fiber link interrupt stop routine */
17754732Sdavemq 
17764732Sdavemq static nxge_status_t
17774732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
17784732Sdavemq {
17794732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
17804732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
17814732Sdavemq 
17824732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
17834732Sdavemq 
17844732Sdavemq 	if (rs != NPI_SUCCESS)
17854732Sdavemq 		return (NXGE_ERROR | rs);
17864732Sdavemq 	else
17874732Sdavemq 		return (NXGE_OK);
17884732Sdavemq }
17894732Sdavemq 
17904732Sdavemq /* 1G copper link interrupt start routine */
17914732Sdavemq 
17924732Sdavemq static nxge_status_t
17934732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
17944732Sdavemq {
17954732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
17964732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
17974732Sdavemq 
17984732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
17994732Sdavemq 	    MII_BMSR, BMSR_LSTATUS);
18004732Sdavemq 
18014732Sdavemq 	if (rs != NPI_SUCCESS)
18024732Sdavemq 		return (NXGE_ERROR | rs);
18034732Sdavemq 	else
18044732Sdavemq 		return (NXGE_OK);
18054732Sdavemq }
18064732Sdavemq 
18074732Sdavemq /* 1G copper link interrupt stop routine */
18084732Sdavemq 
18094732Sdavemq static nxge_status_t
18104732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
18114732Sdavemq {
18124732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
18134732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
18144732Sdavemq 
18154732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
18164732Sdavemq 
18174732Sdavemq 	if (rs != NPI_SUCCESS)
18184732Sdavemq 		return (NXGE_ERROR | rs);
18194732Sdavemq 	else
18204732Sdavemq 		return (NXGE_OK);
18214732Sdavemq }
18224732Sdavemq 
18234732Sdavemq /* Enable/Disable Link Status change interrupt */
18243859Sml29623 
18253859Sml29623 nxge_status_t
18263859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
18273859Sml29623 {
18284732Sdavemq 	uint8_t		portn;
18294732Sdavemq 	nxge_status_t	status = NXGE_OK;
18303859Sml29623 
18313859Sml29623 	portn = nxgep->mac.portnum;
18323859Sml29623 
18333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
18344732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
18354732Sdavemq 		return (NXGE_OK);
18364732Sdavemq 
18374732Sdavemq 	if (enable == LINK_INTR_START)
18384732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
18394732Sdavemq 	else if (enable == LINK_INTR_STOP)
18404732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
18414732Sdavemq 	if (status != NXGE_OK)
18424732Sdavemq 		goto fail;
18433859Sml29623 
18443859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
18453859Sml29623 
18463859Sml29623 	return (NXGE_OK);
18473859Sml29623 fail:
18483859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18493859Sml29623 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
18503859Sml29623 			portn));
18513859Sml29623 
18524732Sdavemq 	return (status);
18533859Sml29623 }
18543859Sml29623 
18553859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
18563859Sml29623 
18573859Sml29623 nxge_status_t
18583859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
18593859Sml29623 {
18603859Sml29623 	p_nxge_param_t	param_arr;
18613859Sml29623 	p_nxge_stats_t	statsp;
18623859Sml29623 	uint8_t		xcvr_portn;
18633859Sml29623 	p_mii_regs_t	mii_regs;
18643859Sml29623 	mii_bmcr_t	bmcr;
18653859Sml29623 	mii_bmsr_t	bmsr;
18663859Sml29623 	mii_anar_t	anar;
18673859Sml29623 	mii_gcr_t	gcr;
18683859Sml29623 	mii_esr_t	esr;
18693859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
18703859Sml29623 	int		status = NXGE_OK;
18713859Sml29623 
18723859Sml29623 	uint_t delay;
18733859Sml29623 
18743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
18753859Sml29623 
18763859Sml29623 	param_arr = nxgep->param_arr;
18773859Sml29623 	statsp = nxgep->statsp;
18783859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
18793859Sml29623 
18803859Sml29623 	mii_regs = NULL;
18813859Sml29623 
18823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18833859Sml29623 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
18843859Sml29623 
18853859Sml29623 	/*
18863859Sml29623 	 * Reset the transceiver.
18873859Sml29623 	 */
18883859Sml29623 	delay = 0;
18893859Sml29623 	bmcr.value = 0;
18903859Sml29623 	bmcr.bits.reset = 1;
18913859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
18923859Sml29623 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
18933859Sml29623 		goto fail;
18943859Sml29623 	do {
18953859Sml29623 		drv_usecwait(500);
18963859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
18973859Sml29623 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
18983859Sml29623 				!= NXGE_OK)
18993859Sml29623 			goto fail;
19003859Sml29623 		delay++;
19013859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
19023859Sml29623 	if (delay == 1000) {
19033859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
19043859Sml29623 		goto fail;
19053859Sml29623 	}
19063859Sml29623 
19073859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
19083859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
19093859Sml29623 			&bmsr.value)) != NXGE_OK)
19103859Sml29623 		goto fail;
19113859Sml29623 
19123859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
19133859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
19143859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
19153859Sml29623 	param_arr[param_anar_100hdx].value = 0;
19163859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
19173859Sml29623 	param_arr[param_anar_10hdx].value = 0;
19183859Sml29623 
19193859Sml29623 	/*
19203859Sml29623 	 * Initialize the xcvr statistics.
19213859Sml29623 	 */
19223859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
19233859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
19243859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
19253859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
19263859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
19273859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
19283859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
19293859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
19303859Sml29623 
19313859Sml29623 	/*
19323859Sml29623 	 * Initialise the xcvr advertised capability statistics.
19333859Sml29623 	 */
19343859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
19353859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
19363859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
19373859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
19383859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
19393859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
19403859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
19413859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
19423859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
19433859Sml29623 					param_arr[param_anar_asmpause].value;
19443859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
19453859Sml29623 
19463859Sml29623 
19473859Sml29623 	/*
19483859Sml29623 	 * Check for extended status just in case we're
19493859Sml29623 	 * running a Gigibit phy.
19503859Sml29623 	 */
19513859Sml29623 	if (bmsr.bits.extend_status) {
19523859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
19533859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
19543859Sml29623 				!= NXGE_OK)
19553859Sml29623 			goto fail;
19563859Sml29623 		param_arr[param_anar_1000fdx].value &=
19573859Sml29623 					esr.bits.link_1000fdx;
19583859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
19593859Sml29623 
19603859Sml29623 		statsp->mac_stats.cap_1000fdx =
19613859Sml29623 			(esr.bits.link_1000Xfdx ||
19623859Sml29623 				esr.bits.link_1000fdx);
19633859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
19643859Sml29623 	} else {
19653859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
19663859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
19673859Sml29623 	}
19683859Sml29623 
19693859Sml29623 	/*
19703859Sml29623 	 * Initialize 1G Statistics once the capability is established.
19713859Sml29623 	 */
19723859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
19733859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
19743859Sml29623 
19753859Sml29623 	/*
19763859Sml29623 	 * Initialise the link statistics.
19773859Sml29623 	 */
19783859Sml29623 	statsp->mac_stats.link_T4 = 0;
19793859Sml29623 	statsp->mac_stats.link_asmpause = 0;
19803859Sml29623 	statsp->mac_stats.link_pause = 0;
19813859Sml29623 	statsp->mac_stats.link_speed = 0;
19823859Sml29623 	statsp->mac_stats.link_duplex = 0;
19833859Sml29623 	statsp->mac_stats.link_up = 0;
19843859Sml29623 
19853859Sml29623 	/*
19863859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
19873859Sml29623 	 */
19883859Sml29623 	bmcr.value = 0;
19893859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
19903859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
19913859Sml29623 		goto fail;
19923859Sml29623 
19933859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
19943859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
19953859Sml29623 		bmcr.bits.loopback = 1;
19963859Sml29623 		bmcr.bits.enable_autoneg = 0;
19973859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
19983859Sml29623 			bmcr.bits.speed_1000_sel = 1;
19993859Sml29623 		bmcr.bits.duplex_mode = 1;
20003859Sml29623 		param_arr[param_autoneg].value = 0;
20013859Sml29623 	} else {
20023859Sml29623 		bmcr.bits.loopback = 0;
20033859Sml29623 	}
20043859Sml29623 
20053859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
20063859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
20073859Sml29623 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
20083859Sml29623 		param_arr[param_autoneg].value = 0;
20093859Sml29623 		bcm5464r_aux.value = 0;
20103859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
20113859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
20123859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
20133859Sml29623 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
20143859Sml29623 				!= NXGE_OK)
20153859Sml29623 			goto fail;
20163859Sml29623 	}
20173859Sml29623 
20183859Sml29623 	if (param_arr[param_autoneg].value) {
20193859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20203859Sml29623 				"Restarting Auto-negotiation."));
20213859Sml29623 		/*
20223859Sml29623 		 * Setup our Auto-negotiation advertisement register.
20233859Sml29623 		 */
20243859Sml29623 		anar.value = 0;
20253859Sml29623 		anar.bits.selector = 1;
20263859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
20273859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
20283859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
20293859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
20303859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
20313859Sml29623 		anar.bits.cap_asmpause = 0;
20323859Sml29623 		anar.bits.cap_pause = 0;
20333859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
20343859Sml29623 			param_arr[param_anar_100fdx].value ||
20353859Sml29623 			param_arr[param_anar_10fdx].value) {
20363859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
20373859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
20383859Sml29623 		}
20393859Sml29623 
20403859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
20413859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
20423859Sml29623 				!= NXGE_OK)
20433859Sml29623 			goto fail;
20443859Sml29623 		if (bmsr.bits.extend_status) {
20453859Sml29623 			gcr.value = 0;
20463859Sml29623 			gcr.bits.ms_mode_en =
20473859Sml29623 				param_arr[param_master_cfg_enable].value;
20483859Sml29623 			gcr.bits.master =
20493859Sml29623 				param_arr[param_master_cfg_value].value;
20503859Sml29623 			gcr.bits.link_1000fdx =
20513859Sml29623 				param_arr[param_anar_1000fdx].value;
20523859Sml29623 			gcr.bits.link_1000hdx =
20533859Sml29623 				param_arr[param_anar_1000hdx].value;
20543859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
20553859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
20563859Sml29623 				!= NXGE_OK)
20573859Sml29623 				goto fail;
20583859Sml29623 		}
20593859Sml29623 
20603859Sml29623 		bmcr.bits.enable_autoneg = 1;
20613859Sml29623 		bmcr.bits.restart_autoneg = 1;
20623859Sml29623 
20633859Sml29623 	} else {
20643859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
20653859Sml29623 		bmcr.bits.speed_1000_sel =
20663859Sml29623 			param_arr[param_anar_1000fdx].value |
20673859Sml29623 				param_arr[param_anar_1000hdx].value;
20683859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
20693859Sml29623 			(param_arr[param_anar_100fdx].value |
20703859Sml29623 				param_arr[param_anar_100hdx].value);
20713859Sml29623 		if (bmcr.bits.speed_1000_sel) {
20723859Sml29623 			statsp->mac_stats.link_speed = 1000;
20733859Sml29623 			gcr.value = 0;
20743859Sml29623 			gcr.bits.ms_mode_en =
20753859Sml29623 				param_arr[param_master_cfg_enable].value;
20763859Sml29623 			gcr.bits.master =
20773859Sml29623 				param_arr[param_master_cfg_value].value;
20783859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
20793859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->gcr),
20803859Sml29623 				gcr.value))
20813859Sml29623 				!= NXGE_OK)
20823859Sml29623 				goto fail;
20833859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
20843859Sml29623 				bmcr.bits.duplex_mode = 1;
20853859Sml29623 				statsp->mac_stats.link_duplex = 2;
20863859Sml29623 			} else
20873859Sml29623 				statsp->mac_stats.link_duplex = 1;
20883859Sml29623 		} else if (bmcr.bits.speed_sel) {
20893859Sml29623 			statsp->mac_stats.link_speed = 100;
20903859Sml29623 			if (param_arr[param_anar_100fdx].value) {
20913859Sml29623 				bmcr.bits.duplex_mode = 1;
20923859Sml29623 				statsp->mac_stats.link_duplex = 2;
20933859Sml29623 			} else
20943859Sml29623 				statsp->mac_stats.link_duplex = 1;
20953859Sml29623 		} else {
20963859Sml29623 			statsp->mac_stats.link_speed = 10;
20973859Sml29623 			if (param_arr[param_anar_10fdx].value) {
20983859Sml29623 				bmcr.bits.duplex_mode = 1;
20993859Sml29623 				statsp->mac_stats.link_duplex = 2;
21003859Sml29623 			} else
21013859Sml29623 				statsp->mac_stats.link_duplex = 1;
21023859Sml29623 		}
21033859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
21043859Sml29623 			statsp->mac_stats.link_asmpause =
21053859Sml29623 						statsp->mac_stats.cap_asmpause;
21063859Sml29623 			statsp->mac_stats.link_pause =
21073859Sml29623 						statsp->mac_stats.cap_pause;
21083859Sml29623 		}
21093859Sml29623 
21103859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
21113859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
21123859Sml29623 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
21133859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
21143859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
21153859Sml29623 				gcr.value = 0;
21163859Sml29623 				gcr.bits.ms_mode_en = 1;
21173859Sml29623 				gcr.bits.master = 1;
21183859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
21193859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gcr),
21203859Sml29623 					gcr.value))
21213859Sml29623 					!= NXGE_OK)
21223859Sml29623 					goto fail;
21233859Sml29623 				bmcr.value = 0;
21243859Sml29623 				bmcr.bits.speed_1000_sel = 1;
21253859Sml29623 				statsp->mac_stats.link_speed = 1000;
21263859Sml29623 			} else if (statsp->port_stats.lb_mode
21273859Sml29623 			    == nxge_lb_ext100) {
21283859Sml29623 				/* BCM5464R 100mbps external loopback mode */
21293859Sml29623 				bmcr.value = 0;
21303859Sml29623 				bmcr.bits.speed_sel = 1;
21313859Sml29623 				bmcr.bits.duplex_mode = 1;
21323859Sml29623 				statsp->mac_stats.link_speed = 100;
21333859Sml29623 			} else if (statsp->port_stats.lb_mode
21343859Sml29623 			    == nxge_lb_ext10) {
21353859Sml29623 				/* BCM5464R 10mbps external loopback mode */
21363859Sml29623 				bmcr.value = 0;
21373859Sml29623 				bmcr.bits.duplex_mode = 1;
21383859Sml29623 				statsp->mac_stats.link_speed = 10;
21393859Sml29623 			}
21403859Sml29623 		}
21413859Sml29623 	}
21423859Sml29623 
21433859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
21443859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
21453859Sml29623 			bmcr.value)) != NXGE_OK)
21463859Sml29623 		goto fail;
21473859Sml29623 
21483859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
21493859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
21503859Sml29623 		goto fail;
21513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
21523859Sml29623 
21533859Sml29623 	/*
21543859Sml29623 	 * Initialize the xcvr status kept in the context structure.
21553859Sml29623 	 */
21563859Sml29623 	nxgep->soft_bmsr.value = 0;
21573859Sml29623 
21583859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
21593859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
21603859Sml29623 			&nxgep->bmsr.value)) != NXGE_OK)
21613859Sml29623 		goto fail;
21623859Sml29623 
21633859Sml29623 	statsp->mac_stats.xcvr_inits++;
21643859Sml29623 	nxgep->bmsr.value = 0;
21653859Sml29623 
21663859Sml29623 fail:
21673859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21683859Sml29623 			"<== nxge_mii_xcvr_init status 0x%x", status));
21693859Sml29623 	return (status);
21703859Sml29623 }
21713859Sml29623 
21723859Sml29623 /* Read from a MII compliant register */
21733859Sml29623 
21743859Sml29623 nxge_status_t
21753859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
21763859Sml29623 		uint16_t *value)
21773859Sml29623 {
21783859Sml29623 	npi_status_t rs = NPI_SUCCESS;
21793859Sml29623 
21803859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
21813859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
21823859Sml29623 
21833859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
21843859Sml29623 
21853859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
21863859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
21873859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
21883859Sml29623 			goto fail;
21893859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
21903859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
21913859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
21923859Sml29623 			goto fail;
21933859Sml29623 	} else
21943859Sml29623 		goto fail;
21953859Sml29623 
21963859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
21973859Sml29623 
21983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
21993859Sml29623 			"xcvr_reg<%d> value=0x%x",
22003859Sml29623 			xcvr_portn, xcvr_reg, *value));
22013859Sml29623 	return (NXGE_OK);
22023859Sml29623 fail:
22033859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
22043859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
22053859Sml29623 			"nxge_mii_read: Failed to read mii on xcvr %d",
22063859Sml29623 			xcvr_portn));
22073859Sml29623 
22083859Sml29623 	return (NXGE_ERROR | rs);
22093859Sml29623 }
22103859Sml29623 
22113859Sml29623 /* Write to a MII compliant Register */
22123859Sml29623 
22133859Sml29623 nxge_status_t
22143859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
22153859Sml29623 		uint16_t value)
22163859Sml29623 {
22173859Sml29623 	npi_status_t rs = NPI_SUCCESS;
22183859Sml29623 
22193859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
22203859Sml29623 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
22213859Sml29623 			value));
22223859Sml29623 
22233859Sml29623 	MUTEX_ENTER(&nxge_mii_lock);
22243859Sml29623 
22253859Sml29623 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
22263859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
22273859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
22283859Sml29623 			goto fail;
22293859Sml29623 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
22303859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
22313859Sml29623 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
22323859Sml29623 			goto fail;
22333859Sml29623 	} else
22343859Sml29623 		goto fail;
22353859Sml29623 
22363859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
22373859Sml29623 
22383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
22393859Sml29623 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
22403859Sml29623 	return (NXGE_OK);
22413859Sml29623 fail:
22423859Sml29623 	MUTEX_EXIT(&nxge_mii_lock);
22433859Sml29623 
22443859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
22453859Sml29623 			"nxge_mii_write: Failed to write mii on xcvr %d",
22463859Sml29623 			xcvr_portn));
22473859Sml29623 
22483859Sml29623 	return (NXGE_ERROR | rs);
22493859Sml29623 }
22503859Sml29623 
22513859Sml29623 /* Perform read from Clause45 serdes / transceiver device */
22523859Sml29623 
22533859Sml29623 nxge_status_t
22543859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
22553859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
22563859Sml29623 {
22573859Sml29623 	npi_status_t rs = NPI_SUCCESS;
22583859Sml29623 
22593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
22603859Sml29623 			xcvr_portn));
22613859Sml29623 
22623859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
22633859Sml29623 
22643859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
22653859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
22663859Sml29623 		goto fail;
22673859Sml29623 
22683859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
22693859Sml29623 
22703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
22713859Sml29623 			xcvr_portn));
22723859Sml29623 	return (NXGE_OK);
22733859Sml29623 fail:
22743859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
22753859Sml29623 
22763859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
22773859Sml29623 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
22783859Sml29623 			xcvr_portn));
22793859Sml29623 
22803859Sml29623 	return (NXGE_ERROR | rs);
22813859Sml29623 }
22823859Sml29623 
22833859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
22843859Sml29623 
22853859Sml29623 nxge_status_t
22863859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
22873859Sml29623 		uint16_t xcvr_reg, uint16_t value)
22883859Sml29623 {
22893859Sml29623 	npi_status_t rs = NPI_SUCCESS;
22903859Sml29623 
22913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
22923859Sml29623 			xcvr_portn));
22933859Sml29623 
22943859Sml29623 	MUTEX_ENTER(&nxge_mdio_lock);
22953859Sml29623 
22963859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
22973859Sml29623 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
22983859Sml29623 		goto fail;
22993859Sml29623 
23003859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
23013859Sml29623 
23023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
23033859Sml29623 			xcvr_portn));
23043859Sml29623 	return (NXGE_OK);
23053859Sml29623 fail:
23063859Sml29623 	MUTEX_EXIT(&nxge_mdio_lock);
23073859Sml29623 
23083859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23093859Sml29623 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
23103859Sml29623 			xcvr_portn));
23113859Sml29623 
23123859Sml29623 	return (NXGE_ERROR | rs);
23133859Sml29623 }
23143859Sml29623 
23153859Sml29623 
23163859Sml29623 /* Check MII to see if there is any link status change */
23173859Sml29623 
23183859Sml29623 nxge_status_t
23193859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
23203859Sml29623 		nxge_link_state_t *link_up)
23213859Sml29623 {
23223859Sml29623 	p_nxge_param_t	param_arr;
23233859Sml29623 	p_nxge_stats_t	statsp;
23243859Sml29623 	p_mii_regs_t	mii_regs;
23253859Sml29623 	p_mii_bmsr_t	soft_bmsr;
23263859Sml29623 	mii_anar_t	anar;
23273859Sml29623 	mii_anlpar_t	anlpar;
23283859Sml29623 	mii_anar_t	an_common;
23293859Sml29623 	mii_aner_t	aner;
23303859Sml29623 	mii_gsr_t	gsr;
23313859Sml29623 	nxge_status_t	status = NXGE_OK;
23323859Sml29623 
23333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
23343859Sml29623 
23353859Sml29623 	mii_regs = NULL;
23363859Sml29623 	param_arr = nxgep->param_arr;
23373859Sml29623 	statsp = nxgep->statsp;
23383859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
23393859Sml29623 	*link_up = LINK_NO_CHANGE;
23403859Sml29623 
23413859Sml29623 	if (bmsr_ints.bits.link_status) {
23423859Sml29623 		if (bmsr.bits.link_status) {
23433859Sml29623 			soft_bmsr->bits.link_status = 1;
23443859Sml29623 		} else {
23453859Sml29623 			statsp->mac_stats.link_up = 0;
23463859Sml29623 			soft_bmsr->bits.link_status = 0;
23473859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23483859Sml29623 					"Link down cable problem"));
23493859Sml29623 			*link_up = LINK_IS_DOWN;
23503859Sml29623 		}
23513859Sml29623 	}
23523859Sml29623 
23533859Sml29623 	if (param_arr[param_autoneg].value) {
23543859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
23553859Sml29623 			if (bmsr.bits.auto_neg_complete)
23563859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
23573859Sml29623 			else
23583859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
23593859Sml29623 		}
23603859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
23613859Sml29623 			statsp->mac_stats.link_T4 = 0;
23623859Sml29623 			statsp->mac_stats.link_speed = 0;
23633859Sml29623 			statsp->mac_stats.link_duplex = 0;
23643859Sml29623 			statsp->mac_stats.link_asmpause = 0;
23653859Sml29623 			statsp->mac_stats.link_pause = 0;
23663859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
23673859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
23683859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
23693859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
23703859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
23713859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
23723859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
23733859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
23743859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
23753859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
23763859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
23773859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
23783859Sml29623 		}
23793859Sml29623 	} else
23803859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
23813859Sml29623 
23823859Sml29623 	if ((bmsr_ints.bits.link_status ||
23833859Sml29623 		bmsr_ints.bits.auto_neg_complete) &&
23843859Sml29623 		soft_bmsr->bits.link_status &&
23853859Sml29623 		soft_bmsr->bits.auto_neg_complete) {
23863859Sml29623 		statsp->mac_stats.link_up = 1;
23873859Sml29623 		if (param_arr[param_autoneg].value) {
23883859Sml29623 			if ((status = nxge_mii_read(nxgep,
23893859Sml29623 				statsp->mac_stats.xcvr_portn,
23903859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anar),
23913859Sml29623 					&anar.value)) != NXGE_OK)
23923859Sml29623 				goto fail;
23933859Sml29623 			if ((status = nxge_mii_read(nxgep,
23943859Sml29623 				statsp->mac_stats.xcvr_portn,
23953859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
23963859Sml29623 					&anlpar.value)) != NXGE_OK)
23973859Sml29623 				goto fail;
23983859Sml29623 			if ((status = nxge_mii_read(nxgep,
23993859Sml29623 				statsp->mac_stats.xcvr_portn,
24003859Sml29623 				(uint8_t)(uint64_t)(&mii_regs->aner),
24013859Sml29623 					&aner.value)) != NXGE_OK)
24023859Sml29623 				goto fail;
24033859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
24043859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
24053859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
24063859Sml29623 							anlpar.bits.cap_100fdx;
24073859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
24083859Sml29623 							anlpar.bits.cap_100hdx;
24093859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
24103859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
24113859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
24123859Sml29623 						anlpar.bits.cap_asmpause;
24133859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
24143859Sml29623 			an_common.value = anar.value & anlpar.value;
24153859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
24163859Sml29623 				param_arr[param_anar_1000hdx].value) {
24173859Sml29623 				if ((status = nxge_mii_read(nxgep,
24183859Sml29623 					statsp->mac_stats.xcvr_portn,
24193859Sml29623 					(uint8_t)(uint64_t)(&mii_regs->gsr),
24203859Sml29623 						&gsr.value))
24213859Sml29623 						!= NXGE_OK)
24223859Sml29623 					goto fail;
24233859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
24243859Sml29623 					gsr.bits.link_1000fdx;
24253859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
24263859Sml29623 					gsr.bits.link_1000hdx;
24273859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
24283859Sml29623 					gsr.bits.link_1000fdx) {
24293859Sml29623 					statsp->mac_stats.link_speed = 1000;
24303859Sml29623 					statsp->mac_stats.link_duplex = 2;
24313859Sml29623 				} else if (
24323859Sml29623 					param_arr[param_anar_1000hdx].value &&
24333859Sml29623 						gsr.bits.link_1000hdx) {
24343859Sml29623 					statsp->mac_stats.link_speed = 1000;
24353859Sml29623 					statsp->mac_stats.link_duplex = 1;
24363859Sml29623 				}
24373859Sml29623 			}
24383859Sml29623 			if ((an_common.value != 0) &&
24393859Sml29623 					!(statsp->mac_stats.link_speed)) {
24403859Sml29623 				if (an_common.bits.cap_100T4) {
24413859Sml29623 					statsp->mac_stats.link_T4 = 1;
24423859Sml29623 					statsp->mac_stats.link_speed = 100;
24433859Sml29623 					statsp->mac_stats.link_duplex = 1;
24443859Sml29623 				} else if (an_common.bits.cap_100fdx) {
24453859Sml29623 					statsp->mac_stats.link_speed = 100;
24463859Sml29623 					statsp->mac_stats.link_duplex = 2;
24473859Sml29623 				} else if (an_common.bits.cap_100hdx) {
24483859Sml29623 					statsp->mac_stats.link_speed = 100;
24493859Sml29623 					statsp->mac_stats.link_duplex = 1;
24503859Sml29623 				} else if (an_common.bits.cap_10fdx) {
24513859Sml29623 					statsp->mac_stats.link_speed = 10;
24523859Sml29623 					statsp->mac_stats.link_duplex = 2;
24533859Sml29623 				} else if (an_common.bits.cap_10hdx) {
24543859Sml29623 					statsp->mac_stats.link_speed = 10;
24553859Sml29623 					statsp->mac_stats.link_duplex = 1;
24563859Sml29623 				} else {
24573859Sml29623 					goto fail;
24583859Sml29623 				}
24593859Sml29623 			}
24603859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
24613859Sml29623 				statsp->mac_stats.link_asmpause =
24623859Sml29623 					an_common.bits.cap_asmpause;
24633859Sml29623 				if (statsp->mac_stats.link_asmpause)
24643859Sml29623 				if ((statsp->mac_stats.cap_pause == 0) &&
24653859Sml29623 						(statsp->mac_stats.lp_cap_pause
24663859Sml29623 						== 1))
24673859Sml29623 						statsp->mac_stats.link_pause
24683859Sml29623 						= 0;
24693859Sml29623 					else
24703859Sml29623 						statsp->mac_stats.link_pause
24713859Sml29623 						= 1;
24723859Sml29623 				else
24733859Sml29623 					statsp->mac_stats.link_pause =
24743859Sml29623 						an_common.bits.cap_pause;
24753859Sml29623 			}
24763859Sml29623 		}
24773859Sml29623 		*link_up = LINK_IS_UP;
24783859Sml29623 	}
24793859Sml29623 
24803859Sml29623 	if (nxgep->link_notify) {
24813859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
24823859Sml29623 				LINK_IS_DOWN);
24833859Sml29623 		nxgep->link_notify = B_FALSE;
24843859Sml29623 	}
24853859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
24863859Sml29623 	return (NXGE_OK);
24873859Sml29623 fail:
24883859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24893859Sml29623 			"nxge_mii_check: Unable to check MII"));
24903859Sml29623 	return (status);
24913859Sml29623 }
24923859Sml29623 
24933859Sml29623 /* Add a multicast address entry into the HW hash table */
24943859Sml29623 
24953859Sml29623 nxge_status_t
24963859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
24973859Sml29623 {
24983859Sml29623 	uint32_t mchash;
24993859Sml29623 	p_hash_filter_t hash_filter;
25003859Sml29623 	uint16_t hash_bit;
25013859Sml29623 	boolean_t rx_init = B_FALSE;
25023859Sml29623 	uint_t j;
25033859Sml29623 	nxge_status_t status = NXGE_OK;
25043859Sml29623 
25053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
25063859Sml29623 
25073859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
25083859Sml29623 	mchash = crc32_mchash(addrp);
25093859Sml29623 	if (nxgep->hash_filter == NULL) {
25103859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
25113859Sml29623 			"Allocating hash filter storage."));
25123859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
25133859Sml29623 					KM_SLEEP);
25143859Sml29623 	}
25153859Sml29623 	hash_filter = nxgep->hash_filter;
25163859Sml29623 	j = mchash / HASH_REG_WIDTH;
25173859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
25183859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
25193859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
25203859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
25213859Sml29623 		hash_filter->hash_ref_cnt++;
25223859Sml29623 		rx_init = B_TRUE;
25233859Sml29623 	}
25243859Sml29623 	if (rx_init) {
25253859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
25263859Sml29623 			goto fail;
25273859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
25283859Sml29623 			goto fail;
25293859Sml29623 	}
25303859Sml29623 
25313859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25323859Sml29623 
25333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
25343859Sml29623 
25353859Sml29623 	return (NXGE_OK);
25363859Sml29623 fail:
25373859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25383859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
25393859Sml29623 					"Unable to add multicast address"));
25403859Sml29623 	return (status);
25413859Sml29623 }
25423859Sml29623 
25433859Sml29623 /* Remove a multicast address entry from the HW hash table */
25443859Sml29623 
25453859Sml29623 nxge_status_t
25463859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
25473859Sml29623 {
25483859Sml29623 	uint32_t mchash;
25493859Sml29623 	p_hash_filter_t hash_filter;
25503859Sml29623 	uint16_t hash_bit;
25513859Sml29623 	boolean_t rx_init = B_FALSE;
25523859Sml29623 	uint_t j;
25533859Sml29623 	nxge_status_t status = NXGE_OK;
25543859Sml29623 
25553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
25563859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
25573859Sml29623 	mchash = crc32_mchash(addrp);
25583859Sml29623 	if (nxgep->hash_filter == NULL) {
25593859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
25603859Sml29623 			"Hash filter already de_allocated."));
25613859Sml29623 		RW_EXIT(&nxgep->filter_lock);
25623859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
25633859Sml29623 		return (NXGE_OK);
25643859Sml29623 	}
25653859Sml29623 	hash_filter = nxgep->hash_filter;
25663859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
25673859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
25683859Sml29623 		j = mchash / HASH_REG_WIDTH;
25693859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
25703859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
25713859Sml29623 		hash_filter->hash_ref_cnt--;
25723859Sml29623 		rx_init = B_TRUE;
25733859Sml29623 	}
25743859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
25753859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
25763859Sml29623 			"De-allocating hash filter storage."));
25773859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
25783859Sml29623 		nxgep->hash_filter = NULL;
25793859Sml29623 	}
25803859Sml29623 
25813859Sml29623 	if (rx_init) {
25823859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
25833859Sml29623 			goto fail;
25843859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
25853859Sml29623 			goto fail;
25863859Sml29623 	}
25873859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
25893859Sml29623 
25903859Sml29623 	return (NXGE_OK);
25913859Sml29623 fail:
25923859Sml29623 	RW_EXIT(&nxgep->filter_lock);
25933859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
25943859Sml29623 			"Unable to remove multicast address"));
25953859Sml29623 
25963859Sml29623 	return (status);
25973859Sml29623 }
25983859Sml29623 
25993859Sml29623 /* Set MAC address into MAC address HW registers */
26003859Sml29623 
26013859Sml29623 nxge_status_t
26023859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
26033859Sml29623 {
26043859Sml29623 	nxge_status_t status = NXGE_OK;
26053859Sml29623 
26063859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
26073859Sml29623 
26083859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
26093859Sml29623 	/*
26103859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
26113859Sml29623 	 */
26123859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
26133859Sml29623 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
26143859Sml29623 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
26153859Sml29623 		goto nxge_set_mac_addr_exit;
26163859Sml29623 	}
26173859Sml29623 	nxgep->ouraddr = *addrp;
26183859Sml29623 	/*
26193859Sml29623 	 * Set new interface local address and re-init device.
26203859Sml29623 	 * This is destructive to any other streams attached
26213859Sml29623 	 * to this device.
26223859Sml29623 	 */
26233859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
26243859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
26253859Sml29623 		goto fail;
26263859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
26273859Sml29623 		goto fail;
26283859Sml29623 
26293859Sml29623 	RW_EXIT(&nxgep->filter_lock);
26303859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
26313859Sml29623 	goto nxge_set_mac_addr_end;
26323859Sml29623 nxge_set_mac_addr_exit:
26333859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
26343859Sml29623 nxge_set_mac_addr_end:
26353859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
26363859Sml29623 
26373859Sml29623 	return (NXGE_OK);
26383859Sml29623 fail:
26393859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
26403859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
26413859Sml29623 			"Unable to set mac address"));
26423859Sml29623 	return (status);
26433859Sml29623 }
26443859Sml29623 
26454693Stm144005 static
26464693Stm144005 check_link_state_t
26474693Stm144005 nxge_check_link_stop(
26484693Stm144005 	nxge_t *nxge)
26494693Stm144005 {
26504693Stm144005 	/* If the poll has been cancelled, return STOP. */
26514693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
26524693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
26534693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
26544693Stm144005 		nxge->nxge_link_poll_timerid = 0;
26554693Stm144005 		cv_broadcast(&nxge->poll_cv);
26564693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
26574693Stm144005 
26584693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
26594693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
26604693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
26614693Stm144005 		    nxge->mac.portnum));
26624693Stm144005 		return (CHECK_LINK_STOP);
26634693Stm144005 	}
26644693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
26654693Stm144005 
26664693Stm144005 	return (CHECK_LINK_RESCHEDULE);
26674693Stm144005 }
26684693Stm144005 
26693859Sml29623 /* Check status of MII (MIF or PCS) link */
26703859Sml29623 
26714732Sdavemq static nxge_status_t
26723859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
26733859Sml29623 {
26743859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
26753859Sml29623 	mii_anlpar_t anlpar;
26763859Sml29623 	mii_gsr_t gsr;
26773859Sml29623 	p_mii_regs_t mii_regs;
26783859Sml29623 	nxge_status_t status = NXGE_OK;
26793859Sml29623 	uint8_t portn;
26803859Sml29623 	nxge_link_state_t link_up;
26813859Sml29623 
26824693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
26834693Stm144005 		return (NXGE_ERROR);
26844693Stm144005 
26854693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
26864693Stm144005 		return (NXGE_OK);
26874693Stm144005 
26883859Sml29623 	portn = nxgep->mac.portnum;
26893859Sml29623 
26903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
26914693Stm144005 	    portn));
26923859Sml29623 
26933859Sml29623 	mii_regs = NULL;
26943859Sml29623 
26953859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
26963859Sml29623 
26973859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
26983859Sml29623 		goto nxge_check_mii_link_exit;
26993859Sml29623 
27003859Sml29623 	if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
27013859Sml29623 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
27023859Sml29623 		&bmsr_data.value)) != NXGE_OK)
27033859Sml29623 		goto fail;
27043859Sml29623 
27053859Sml29623 	if (nxgep->param_arr[param_autoneg].value) {
27063859Sml29623 		if ((status = nxge_mii_read(nxgep,
27073859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn,
27083859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->gsr),
27093859Sml29623 			&gsr.value)) != NXGE_OK)
27103859Sml29623 			goto fail;
27113859Sml29623 		if ((status = nxge_mii_read(nxgep,
27123859Sml29623 			nxgep->statsp->mac_stats.xcvr_portn,
27133859Sml29623 			(uint8_t)(uint64_t)(&mii_regs->anlpar),
27143859Sml29623 			&anlpar.value)) != NXGE_OK)
27153859Sml29623 			goto fail;
27163859Sml29623 		if (nxgep->statsp->mac_stats.link_up &&
27173859Sml29623 			((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
27183859Sml29623 				gsr.bits.link_1000fdx) ||
27193859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
27203859Sml29623 				gsr.bits.link_1000hdx) ||
27213859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100T4 ^
27223859Sml29623 				anlpar.bits.cap_100T4) ||
27233859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100fdx ^
27243859Sml29623 				anlpar.bits.cap_100fdx) ||
27253859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_100hdx ^
27263859Sml29623 				anlpar.bits.cap_100hdx) ||
27273859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_10fdx ^
27283859Sml29623 				anlpar.bits.cap_10fdx) ||
27293859Sml29623 			(nxgep->statsp->mac_stats.lp_cap_10hdx ^
27303859Sml29623 				anlpar.bits.cap_10hdx))) {
27313859Sml29623 			bmsr_data.bits.link_status = 0;
27323859Sml29623 		}
27333859Sml29623 	}
27343859Sml29623 
27353859Sml29623 	/* Workaround for link down issue */
27363859Sml29623 	if (bmsr_data.value == 0) {
27374732Sdavemq 		cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n",
27384732Sdavemq 		    nxgep->instance);
27393859Sml29623 		goto nxge_check_mii_link_exit;
27403859Sml29623 	}
27413859Sml29623 
27423859Sml29623 	bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
27433859Sml29623 	nxgep->bmsr.value = bmsr_data.value;
27443859Sml29623 	if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up))
27454693Stm144005 	    != NXGE_OK)
27463859Sml29623 		goto fail;
27473859Sml29623 
27483859Sml29623 nxge_check_mii_link_exit:
27493859Sml29623 	RW_EXIT(&nxgep->filter_lock);
27503859Sml29623 	if (link_up == LINK_IS_UP) {
27513859Sml29623 		nxge_link_is_up(nxgep);
27523859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
27533859Sml29623 		nxge_link_is_down(nxgep);
27543859Sml29623 	}
27553859Sml29623 
27563859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
27573859Sml29623 
27583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
27594693Stm144005 	    portn));
27603859Sml29623 	return (NXGE_OK);
27613859Sml29623 
27623859Sml29623 fail:
27633859Sml29623 	RW_EXIT(&nxgep->filter_lock);
27643859Sml29623 
27653859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
27663859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27674693Stm144005 	    "nxge_check_mii_link: Failed to check link port<%d>",
27684693Stm144005 	    portn));
27693859Sml29623 	return (status);
27703859Sml29623 }
27713859Sml29623 
27723859Sml29623 
27733859Sml29623 /*ARGSUSED*/
27744732Sdavemq static nxge_status_t
27753859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
27763859Sml29623 {
27773859Sml29623 	uint8_t		portn;
27783859Sml29623 
27793859Sml29623 	nxge_status_t	status = NXGE_OK;
27803859Sml29623 	boolean_t	link_up;
27813859Sml29623 
27824693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
27834693Stm144005 		return (NXGE_ERROR);
27844693Stm144005 
27854693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
27864693Stm144005 		return (NXGE_OK);
27874693Stm144005 
27883859Sml29623 	portn = nxgep->mac.portnum;
27893859Sml29623 
27903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
27914693Stm144005 	    portn));
27923859Sml29623 
27933859Sml29623 	status = nxge_check_bcm8704_link(nxgep, &link_up);
27943859Sml29623 
27953859Sml29623 	if (status != NXGE_OK)
27963859Sml29623 		goto fail;
27973859Sml29623 
27983859Sml29623 	if (link_up) {
27993859Sml29623 		if (nxgep->link_notify ||
28003859Sml29623 			nxgep->statsp->mac_stats.link_up == 0) {
28013859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
28023859Sml29623 				goto fail;
28033859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
28043859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
28053859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
28063859Sml29623 
28073859Sml29623 			nxge_link_is_up(nxgep);
28083859Sml29623 			nxgep->link_notify = B_FALSE;
28093859Sml29623 		}
28103859Sml29623 	} else {
28113859Sml29623 		if (nxgep->link_notify ||
28123859Sml29623 			nxgep->statsp->mac_stats.link_up == 1) {
28133859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
28143859Sml29623 				goto fail;
28153859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
28164732Sdavemq 			    "Link down cable problem"));
28173859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
28183859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
28193859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
28203859Sml29623 
28213859Sml29623 			nxge_link_is_down(nxgep);
28223859Sml29623 			nxgep->link_notify = B_FALSE;
28233859Sml29623 		}
28243859Sml29623 	}
28253859Sml29623 
28263859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
28273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
28284693Stm144005 	    portn));
28293859Sml29623 	return (NXGE_OK);
28303859Sml29623 
28313859Sml29623 fail:
28324693Stm144005 	(void) nxge_check_link_stop(nxgep);
28334693Stm144005 
28343859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
28354693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
28364693Stm144005 	    portn));
28373859Sml29623 	return (status);
28383859Sml29623 }
28393859Sml29623 
28403859Sml29623 
28413859Sml29623 /* Declare link down */
28423859Sml29623 
28433859Sml29623 void
28443859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
28453859Sml29623 {
28464732Sdavemq 	p_nxge_stats_t statsp;
28474732Sdavemq 	char link_stat_msg[64];
28484732Sdavemq 
28493859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
28503859Sml29623 
28514732Sdavemq 	statsp = nxgep->statsp;
28524732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
28534732Sdavemq 	    statsp->mac_stats.xcvr_portn);
28544732Sdavemq 
28554732Sdavemq 	if (nxge_no_msg == B_FALSE) {
28564732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
28574732Sdavemq 	}
28584732Sdavemq 
28593859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
28603859Sml29623 
28613859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
28623859Sml29623 }
28633859Sml29623 
28643859Sml29623 /* Declare link up */
28653859Sml29623 
28663859Sml29623 void
28673859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
28683859Sml29623 {
28694732Sdavemq 	p_nxge_stats_t statsp;
28704732Sdavemq 	char link_stat_msg[64];
28713859Sml29623 	uint32_t val;
28723859Sml29623 
28733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
28743859Sml29623 
28754732Sdavemq 	statsp = nxgep->statsp;
28764732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
28774732Sdavemq 	    statsp->mac_stats.xcvr_portn,
28784732Sdavemq 	    statsp->mac_stats.link_speed);
28794732Sdavemq 
28804732Sdavemq 	if (statsp->mac_stats.link_T4)
28814732Sdavemq 		(void) strcat(link_stat_msg, "T4");
28824732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
28834732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
28844732Sdavemq 	else
28854732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
28864732Sdavemq 
28873859Sml29623 	(void) nxge_xif_init(nxgep);
28883859Sml29623 
28893859Sml29623 	/* Clean up symbol errors incurred during link transition */
28903859Sml29623 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
28913859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
28923859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
28933859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
28943859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
28953859Sml29623 	}
28963859Sml29623 
28974732Sdavemq 	if (nxge_no_msg == B_FALSE) {
28984732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
28994732Sdavemq 	}
29004732Sdavemq 
29013859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
29023859Sml29623 
29033859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
29043859Sml29623 }
29053859Sml29623 
29063859Sml29623 /*
29073859Sml29623  * Calculate the bit in the multicast address filter
29083859Sml29623  * that selects the given * address.
29093859Sml29623  * Note: For GEM, the last 8-bits are used.
29103859Sml29623  */
29113859Sml29623 uint32_t
29123859Sml29623 crc32_mchash(p_ether_addr_t addr)
29133859Sml29623 {
29143859Sml29623 	uint8_t *cp;
29153859Sml29623 	uint32_t crc;
29163859Sml29623 	uint32_t c;
29173859Sml29623 	int byte;
29183859Sml29623 	int bit;
29193859Sml29623 
29203859Sml29623 	cp = (uint8_t *)addr;
29213859Sml29623 	crc = (uint32_t)0xffffffff;
29223859Sml29623 	for (byte = 0; byte < 6; byte++) {
29233859Sml29623 		c = (uint32_t)cp[byte];
29243859Sml29623 		for (bit = 0; bit < 8; bit++) {
29253859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
29263859Sml29623 				crc = (crc >> 1)^0xedb88320;
29273859Sml29623 			else
29283859Sml29623 				crc = (crc >> 1);
29293859Sml29623 			c >>= 1;
29303859Sml29623 		}
29313859Sml29623 	}
29323859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
29333859Sml29623 }
29343859Sml29623 
29353859Sml29623 /* Reset serdes */
29363859Sml29623 
29373859Sml29623 nxge_status_t
29383859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
29393859Sml29623 {
29403859Sml29623 	npi_handle_t		handle;
29413859Sml29623 
29423859Sml29623 	handle = nxgep->npi_handle;
29433859Sml29623 
29443859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
29453859Sml29623 	drv_usecwait(500);
29463859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
29473859Sml29623 
29483859Sml29623 	return (NXGE_OK);
29493859Sml29623 }
29503859Sml29623 
29513859Sml29623 /* Monitor link status using interrupt or polling */
29523859Sml29623 
29533859Sml29623 nxge_status_t
29543859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
29553859Sml29623 {
29563859Sml29623 	nxge_status_t status = NXGE_OK;
29573859Sml29623 
29583859Sml29623 	/*
29594693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
29604693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
29613859Sml29623 	 */
29623859Sml29623 	if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
29633859Sml29623 		return (NXGE_OK);
29643859Sml29623 
29653859Sml29623 	if (nxgep->statsp == NULL) {
29663859Sml29623 		/* stats has not been allocated. */
29673859Sml29623 		return (NXGE_OK);
29683859Sml29623 	}
29693859Sml29623 	/* Don't check link if we're not in internal loopback mode */
29703859Sml29623 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
29713859Sml29623 		return (NXGE_OK);
29723859Sml29623 
29733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29744693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
29754693Stm144005 	    nxgep->mac.portnum, enable));
29763859Sml29623 	if (enable == LINK_MONITOR_START) {
29773859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
29783859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
29794693Stm144005 			    != NXGE_OK)
29803859Sml29623 				goto fail;
29813859Sml29623 		} else {
29824693Stm144005 			timeout_id_t timerid;
29834693Stm144005 
29844693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
29854693Stm144005 				return (NXGE_OK);
29864693Stm144005 
29874732Sdavemq 			if (nxgep->xcvr.check_link) {
29884732Sdavemq 				timerid = timeout(
29894732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
29904693Stm144005 				    nxgep,
29914693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
29924732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
29934732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
29944732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
29954732Sdavemq 			} else {
29964693Stm144005 				return (NXGE_ERROR);
29973859Sml29623 			}
29983859Sml29623 		}
29993859Sml29623 	} else {
30003859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
30013859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
30024693Stm144005 			    != NXGE_OK)
30033859Sml29623 				goto fail;
30043859Sml29623 		} else {
30054693Stm144005 			clock_t rv;
30064693Stm144005 
30074693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
30084693Stm144005 
30094693Stm144005 			/* If <timerid> == 0, the link monitor has */
30104693Stm144005 			/* never been started, or just now stopped. */
30114693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
30124693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
30134693Stm144005 				return (NXGE_OK);
30144693Stm144005 			}
30154693Stm144005 
30164693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
30174693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
30184693Stm144005 			    &nxgep->poll_lock,
30194693Stm144005 			    ddi_get_lbolt() +
30204693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
30214693Stm144005 			    LINK_MONITOR_PERIOD));
30224693Stm144005 			if (rv == -1) {
30234693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30244693Stm144005 				    "==> stopping port %d: "
30254693Stm144005 				    "cv_timedwait(%d) timed out",
30264693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
30274693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
30283859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
30293859Sml29623 			}
30304693Stm144005 
30314693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
30323859Sml29623 		}
30333859Sml29623 	}
30343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30354693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
30364693Stm144005 	    nxgep->mac.portnum, enable));
30373859Sml29623 	return (NXGE_OK);
30383859Sml29623 fail:
30393859Sml29623 	return (status);
30403859Sml29623 }
30413859Sml29623 
30423859Sml29623 /* Set promiscous mode */
30433859Sml29623 
30443859Sml29623 nxge_status_t
30453859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
30463859Sml29623 {
30473859Sml29623 	nxge_status_t status = NXGE_OK;
30483859Sml29623 
30494732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
30503859Sml29623 
30513859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
30523859Sml29623 
30533859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
30543859Sml29623 
30553859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
30563859Sml29623 		goto fail;
30573859Sml29623 	}
30583859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
30593859Sml29623 		goto fail;
30603859Sml29623 	}
30613859Sml29623 
30623859Sml29623 	RW_EXIT(&nxgep->filter_lock);
30633859Sml29623 
30643859Sml29623 	if (on)
30653859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
30663859Sml29623 	else
30673859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
30683859Sml29623 
30693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
30703859Sml29623 
30713859Sml29623 	return (NXGE_OK);
30723859Sml29623 fail:
30733859Sml29623 	RW_EXIT(&nxgep->filter_lock);
30743859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
30754732Sdavemq 	    "Unable to set promisc (%d)", on));
30763859Sml29623 
30773859Sml29623 	return (status);
30783859Sml29623 }
30793859Sml29623 
30803859Sml29623 /*ARGSUSED*/
30813859Sml29623 uint_t
30823859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
30833859Sml29623 {
30843859Sml29623 #ifdef	NXGE_DEBUG
30853859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
30863859Sml29623 #endif
30873859Sml29623 #if NXGE_MIF
30883859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
30893859Sml29623 	uint32_t		status;
30903859Sml29623 	npi_handle_t		handle;
30913859Sml29623 	uint8_t			portn;
30923859Sml29623 	p_nxge_stats_t		statsp;
30933859Sml29623 #endif
30943859Sml29623 
30953859Sml29623 #ifdef	NXGE_MIF
30963859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
30973859Sml29623 		nxgep = ldvp->nxgep;
30983859Sml29623 	}
30993859Sml29623 	nxgep = ldvp->nxgep;
31003859Sml29623 #endif
31013859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
31023859Sml29623 
31033859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
31043859Sml29623 	return (DDI_INTR_CLAIMED);
31053859Sml29623 
31063859Sml29623 mif_intr_fail:
31073859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
31083859Sml29623 	return (DDI_INTR_UNCLAIMED);
31093859Sml29623 }
31103859Sml29623 
31113859Sml29623 /*ARGSUSED*/
31123859Sml29623 uint_t
31133859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
31143859Sml29623 {
31153859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
31163859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
31173859Sml29623 	p_nxge_ldg_t		ldgp;
31183859Sml29623 	uint32_t		status;
31193859Sml29623 	npi_handle_t		handle;
31203859Sml29623 	uint8_t			portn;
31213859Sml29623 	p_nxge_stats_t		statsp;
31223859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
31233859Sml29623 
31243859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
31253859Sml29623 		nxgep = ldvp->nxgep;
31263859Sml29623 	}
31273859Sml29623 
31283859Sml29623 	ldgp = ldvp->ldgp;
31293859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
31304732Sdavemq 	    "group %d", ldgp->ldg));
31313859Sml29623 
31323859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
31333859Sml29623 	/*
31343859Sml29623 	 * This interrupt handler is for a specific
31353859Sml29623 	 * mac port.
31363859Sml29623 	 */
31373859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
31383859Sml29623 	portn = nxgep->mac.portnum;
31393859Sml29623 
31403859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
31414732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
31423859Sml29623 
31433859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
31443859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
31453859Sml29623 					(xmac_tx_iconfig_t *)&status);
31463859Sml29623 		if (rs != NPI_SUCCESS)
31473859Sml29623 			goto npi_fail;
31483859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
31493859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
31503859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
31513859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31523859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
31533859Sml29623 			}
31543859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
31553859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
31563859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31573859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
31583859Sml29623 			}
31593859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
31603859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
31613859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31623859Sml29623 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
31633859Sml29623 			}
31643859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
31653859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
31663859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31673859Sml29623 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
31683859Sml29623 			}
31693859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
31703859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
31713859Sml29623 							XTXMAC_BYTE_CNT_MASK;
31723859Sml29623 			}
31733859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
31743859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
31753859Sml29623 							XTXMAC_FRM_CNT_MASK;
31763859Sml29623 			}
31773859Sml29623 		}
31783859Sml29623 
31793859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
31803859Sml29623 					(xmac_rx_iconfig_t *)&status);
31813859Sml29623 		if (rs != NPI_SUCCESS)
31823859Sml29623 			goto npi_fail;
31833859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
31843859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
31853859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
31863859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
31873859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
31883859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31893859Sml29623 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
31903859Sml29623 			}
31913859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
31923859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
31933859Sml29623 							XRXMAC_CRC_ER_CNT_MASK;
31943859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
31953859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
31963859Sml29623 			}
31973859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
31983859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
31993859Sml29623 							MAC_LEN_ER_CNT_MASK;
32003859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32013859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
32023859Sml29623 			}
32033859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
32043859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
32053859Sml29623 							XRXMAC_CD_VIO_CNT_MASK;
32063859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32073859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
32083859Sml29623 			}
32093859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
32103859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
32113859Sml29623 							XRXMAC_BT_CNT_MASK;
32123859Sml29623 			}
32133859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
32143859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
32153859Sml29623 							XRXMAC_HIST_CNT1_MASK;
32163859Sml29623 			}
32173859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
32183859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
32193859Sml29623 							XRXMAC_HIST_CNT2_MASK;
32203859Sml29623 			}
32213859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
32223859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
32233859Sml29623 							XRXMAC_HIST_CNT3_MASK;
32243859Sml29623 			}
32253859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
32263859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
32273859Sml29623 							XRXMAC_HIST_CNT4_MASK;
32283859Sml29623 			}
32293859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
32303859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
32313859Sml29623 							XRXMAC_HIST_CNT5_MASK;
32323859Sml29623 			}
32333859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
32343859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
32353859Sml29623 							XRXMAC_HIST_CNT6_MASK;
32363859Sml29623 			}
32373859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
32383859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
32393859Sml29623 							XRXMAC_BC_FRM_CNT_MASK;
32403859Sml29623 			}
32413859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
32423859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
32433859Sml29623 							XRXMAC_MC_FRM_CNT_MASK;
32443859Sml29623 			}
32453859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
32463859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
32473859Sml29623 							XRXMAC_FRAG_CNT_MASK;
32483859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32493859Sml29623 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
32503859Sml29623 			}
32513859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
32523859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
32533859Sml29623 							XRXMAC_AL_ER_CNT_MASK;
32543859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32553859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
32563859Sml29623 			}
32573859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
32583859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
32593859Sml29623 							XMAC_LINK_FLT_CNT_MASK;
32603859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32613859Sml29623 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
32623859Sml29623 			}
32633859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
32643859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
32653859Sml29623 			}
32663859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
32673859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
32683859Sml29623 			}
32693859Sml29623 		}
32703859Sml29623 
32713859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
32723859Sml29623 						(xmac_ctl_iconfig_t *)&status);
32733859Sml29623 		if (rs != NPI_SUCCESS)
32743859Sml29623 			goto npi_fail;
32753859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
32763859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
32773859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
32783859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
32793859Sml29623 				statsp->xmac_stats.tx_pause_state++;
32803859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
32813859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
32823859Sml29623 		}
32833859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
32843859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
32853859Sml29623 						(bmac_tx_iconfig_t *)&status);
32863859Sml29623 		if (rs != NPI_SUCCESS)
32873859Sml29623 			goto npi_fail;
32883859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
32893859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
32903859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
32913859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32923859Sml29623 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
32933859Sml29623 			}
32943859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
32953859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
32963859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
32973859Sml29623 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
32983859Sml29623 			}
32993859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
33003859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
33013859Sml29623 							BTXMAC_BYTE_CNT_MASK;
33023859Sml29623 			}
33033859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
33043859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
33053859Sml29623 							BTXMAC_FRM_CNT_MASK;
33063859Sml29623 			}
33073859Sml29623 		}
33083859Sml29623 
33093859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
33103859Sml29623 						(bmac_rx_iconfig_t *)&status);
33113859Sml29623 		if (rs != NPI_SUCCESS)
33123859Sml29623 			goto npi_fail;
33133859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
33143859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
33153859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
33163859Sml29623 			}
33173859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
33183859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
33193859Sml29623 							RXMAC_FRM_CNT_MASK;
33203859Sml29623 			}
33213859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
33223859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
33233859Sml29623 							BMAC_CRC_ER_CNT_MASK;
33243859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
33253859Sml29623 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
33263859Sml29623 			}
33273859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
33283859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
33293859Sml29623 							MAC_LEN_ER_CNT_MASK;
33303859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
33313859Sml29623 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
33323859Sml29623 			}
33333859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
33343859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
33353859Sml29623 							BMAC_CD_VIO_CNT_MASK;
33363859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
33373859Sml29623 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
33383859Sml29623 			}
33393859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
33403859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
33413859Sml29623 							BRXMAC_BYTE_CNT_MASK;
33423859Sml29623 			}
33433859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
33443859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
33453859Sml29623 							BMAC_AL_ER_CNT_MASK;
33463859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
33473859Sml29623 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
33483859Sml29623 			}
33493859Sml29623 
33503859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
33513859Sml29623 						(bmac_ctl_iconfig_t *)&status);
33523859Sml29623 			if (rs != NPI_SUCCESS)
33533859Sml29623 				goto npi_fail;
33543859Sml29623 
33553859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
33563859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
33573859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
33583859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
33593859Sml29623 					statsp->bmac_stats.tx_pause_state++;
33603859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
33613859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
33623859Sml29623 			}
33633859Sml29623 		}
33643859Sml29623 
33653859Sml29623 	if (ldgp->nldvs == 1) {
33663859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
33673859Sml29623 			B_TRUE, ldgp->ldg_timer);
33683859Sml29623 	}
33693859Sml29623 
33703859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
33713859Sml29623 	return (DDI_INTR_CLAIMED);
33723859Sml29623 
33733859Sml29623 npi_fail:
33743859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
33753859Sml29623 	return (DDI_INTR_UNCLAIMED);
33763859Sml29623 }
33773859Sml29623 
33783859Sml29623 nxge_status_t
33793859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
33803859Sml29623 {
33813859Sml29623 	uint8_t		phy_port_addr;
33823859Sml29623 	nxge_status_t	status = NXGE_OK;
33833859Sml29623 	boolean_t	rx_sig_ok;
33843859Sml29623 	boolean_t	pcs_blk_lock;
33853859Sml29623 	boolean_t	link_align;
33863859Sml29623 	uint16_t	val1, val2, val3;
33873859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
33883859Sml29623 	uint16_t	val_debug;
33893859Sml29623 	uint16_t	val;
33903859Sml29623 #endif
33913859Sml29623 
33923859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
33933859Sml29623 
33943859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
33953859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
33963859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
33973859Sml29623 	if ((val_debug & ~0x200) != 0) {
33983859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
33993859Sml29623 				nxgep->mac.portnum, val_debug);
34003859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
34013859Sml29623 				&val_debug);
34023859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
34033859Sml29623 				nxgep->mac.portnum, val_debug);
34043859Sml29623 	}
34053859Sml29623 
34063859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
34073859Sml29623 					XPCS_REG_DESCWERR_COUNTER, &val);
34083859Sml29623 	if (val != 0)
34093859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
34103859Sml29623 
34113859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
34123859Sml29623 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
34133859Sml29623 	if (val != 0)
34143859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
34153859Sml29623 
34163859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
34173859Sml29623 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
34183859Sml29623 	if (val != 0)
34193859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
34203859Sml29623 #endif
34213859Sml29623 
34223859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
34233859Sml29623 
34243859Sml29623 	/* Check Device 1 Register 0xA bit0 */
34253859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
34263859Sml29623 			BCM8704_PMA_PMD_DEV_ADDR,
34273859Sml29623 			BCM8704_PMD_RECEIVE_SIG_DETECT,
34283859Sml29623 			&val1);
34293859Sml29623 	if (status != NXGE_OK)
34303859Sml29623 		goto fail;
34313859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
34323859Sml29623 
34333859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
34343859Sml29623 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
34353859Sml29623 			BCM8704_PCS_DEV_ADDR,
34363859Sml29623 			BCM8704_10GBASE_R_PCS_STATUS_REG,
34373859Sml29623 			&val2)) != NPI_SUCCESS)
34383859Sml29623 		goto fail;
34393859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
34403859Sml29623 
34413859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
34423859Sml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
34433859Sml29623 			BCM8704_PHYXS_ADDR,
34443859Sml29623 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
34453859Sml29623 			&val3);
34463859Sml29623 	if (status != NXGE_OK)
34473859Sml29623 		goto fail;
34483859Sml29623 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
34493859Sml29623 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
34503859Sml29623 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
34513859Sml29623 
34523859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
34533859Sml29623 	/* Temp workaround for link down issue */
34543859Sml29623 	if (pcs_blk_lock == B_FALSE) {
34553859Sml29623 		if (val2 != 0x4) {
34563859Sml29623 			pcs_blk_lock = B_TRUE;
34573859Sml29623 			cmn_err(CE_NOTE,
34583859Sml29623 				"!LINK DEBUG: port%d PHY Dev3 "
34593859Sml29623 				"Reg 0x20 = 0x%x\n",
34603859Sml29623 				nxgep->mac.portnum, val2);
34613859Sml29623 		}
34623859Sml29623 	}
34633859Sml29623 
34643859Sml29623 	if (link_align == B_FALSE) {
34653859Sml29623 		if (val3 != 0x140f) {
34663859Sml29623 			link_align = B_TRUE;
34673859Sml29623 			cmn_err(CE_NOTE,
34683859Sml29623 				"!LINK DEBUG: port%d PHY Dev4 "
34693859Sml29623 				"Reg 0x18 = 0x%x\n",
34703859Sml29623 				nxgep->mac.portnum, val3);
34713859Sml29623 		}
34723859Sml29623 	}
34733859Sml29623 
34743859Sml29623 	if (rx_sig_ok == B_FALSE) {
34753859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
34763859Sml29623 			rx_sig_ok = B_TRUE;
34773859Sml29623 			cmn_err(CE_NOTE,
34783859Sml29623 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
34793859Sml29623 				nxgep->mac.portnum);
34803859Sml29623 		}
34813859Sml29623 	}
34823859Sml29623 #endif
34833859Sml29623 
34843859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
34853859Sml29623 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
34863859Sml29623 
34873859Sml29623 	return (NXGE_OK);
34883859Sml29623 fail:
34893859Sml29623 	return (status);
34903859Sml29623 }
34913859Sml29623 
34923859Sml29623 nxge_status_t
34933859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
34943859Sml29623 {
34953859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
34964732Sdavemq 	    != NPI_SUCCESS)
34973859Sml29623 		return (NXGE_ERROR);
34983859Sml29623 	else
34993859Sml29623 		return (NXGE_OK);
35003859Sml29623 }
35013859Sml29623 
35023859Sml29623 nxge_status_t
35033859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
35043859Sml29623 {
35053859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
35064732Sdavemq 	    != NPI_SUCCESS)
35073859Sml29623 		return (NXGE_ERROR);
35083859Sml29623 	else
35093859Sml29623 		return (NXGE_OK);
35103859Sml29623 }
35114185Sspeer 
35124732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
35134732Sdavemq 
35144732Sdavemq static boolean_t
35154732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
35164732Sdavemq {
35174732Sdavemq 	int		i;
35184732Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
35194732Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
35204732Sdavemq 	boolean_t	found = B_FALSE;
35214732Sdavemq 
35224732Sdavemq 	switch (type) {
35234732Sdavemq 	case CLAUSE_45_TYPE:
35244732Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
3525*4782Ssbehera 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
3526*4782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
35274732Sdavemq 				found = B_TRUE;
35284732Sdavemq 				break;
35294732Sdavemq 			}
35304732Sdavemq 		}
35314732Sdavemq 		break;
35324732Sdavemq 	case CLAUSE_22_TYPE:
35334732Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
3534*4782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
3535*4782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
35364732Sdavemq 				found = B_TRUE;
35374732Sdavemq 				break;
35384732Sdavemq 			}
35394732Sdavemq 		}
35404732Sdavemq 		break;
35414732Sdavemq 	default:
35424732Sdavemq 		break;
35434732Sdavemq 	}
35444732Sdavemq 
35454732Sdavemq 	return (found);
35464732Sdavemq }
35474732Sdavemq 
35484732Sdavemq /*
35494732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
35504732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
35514732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
35524732Sdavemq  * and the Neptune type.
35534732Sdavemq  */
35544732Sdavemq 
35554732Sdavemq nxge_status_t
35564732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
35574732Sdavemq {
35584732Sdavemq 	int		i, j, k, l;
35594732Sdavemq 	uint16_t	val1 = 0;
35604732Sdavemq 	uint16_t	val2 = 0;
35614732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
35624732Sdavemq 	uint32_t	pcs_dev_id = 0;
35634732Sdavemq 	uint32_t	phy_id = 0;
3564*4782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
3565*4782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
3566*4782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
35674732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
35684732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
35694732Sdavemq 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
35704732Sdavemq 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
35714732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
35724732Sdavemq 	nxge_status_t	status = NXGE_OK;
35734732Sdavemq 	npi_status_t	npi_status = NPI_SUCCESS;
35744732Sdavemq 	npi_handle_t	handle;
35754732Sdavemq 	int		prt_id = -1;
35764732Sdavemq 
35774732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
35784732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35794732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
35804732Sdavemq 	    nxgep->niu_type));
35814732Sdavemq 
35824732Sdavemq 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
35834732Sdavemq 	j = k = l = 0;
35844732Sdavemq 	total_port_fd = total_phy_fd = 0;
35854732Sdavemq 	/*
35864732Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
35874732Sdavemq 	 * for on chip serdes usages.
35884732Sdavemq 	 */
35894732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
35904732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
35914732Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
35924732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
35934732Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
35944732Sdavemq 		pma_pmd_dev_id = val1;
35954732Sdavemq 		pma_pmd_dev_id = (pma_pmd_dev_id << 16);
35964732Sdavemq 		pma_pmd_dev_id |= val2;
35974732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
35984732Sdavemq 		    "devid[0x%llx]", i, pma_pmd_dev_id));
35994732Sdavemq 
36004732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
36014732Sdavemq 			pma_pmd_dev_fd[i] = 1;
36024732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
36034732Sdavemq 			    "PMA/PMD dev found", i));
3604*4782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
3605*4782Ssbehera 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
3606*4782Ssbehera 				    BCM_PHY_ID_MASK;
36074732Sdavemq 				j++;
36084732Sdavemq 			}
36094732Sdavemq 		} else {
36104732Sdavemq 			pma_pmd_dev_fd[i] = 0;
36114732Sdavemq 		}
36124732Sdavemq 
36134732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
36144732Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
36154732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
36164732Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
36174732Sdavemq 		pcs_dev_id = val1;
36184732Sdavemq 		pcs_dev_id = (pcs_dev_id << 16);
36194732Sdavemq 		pcs_dev_id |= val2;
36204732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
36214732Sdavemq 		    "devid[0x%llx]", i, pcs_dev_id));
36224732Sdavemq 
36234732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
36244732Sdavemq 			pcs_dev_fd[i] = 1;
36254732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
36264732Sdavemq 			    "dev found", i));
3627*4782Ssbehera 			if (k < NXGE_PORTS_NEPTUNE) {
3628*4782Ssbehera 				port_pcs_dev_id[k] = pcs_dev_id &
3629*4782Ssbehera 				    BCM_PHY_ID_MASK;
36304732Sdavemq 				k++;
36314732Sdavemq 			}
36324732Sdavemq 		} else {
36334732Sdavemq 			pcs_dev_fd[i] = 0;
36344732Sdavemq 		}
36354732Sdavemq 
36364732Sdavemq 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
36374732Sdavemq 			port_fd[i] = 1;
36384732Sdavemq 		else
36394732Sdavemq 			port_fd[i] = 0;
36404732Sdavemq 		total_port_fd += port_fd[i];
36414732Sdavemq 
36424732Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
36434732Sdavemq 		    NXGE_PHY_ID_REG_1, &val1);
36444732Sdavemq 		if (npi_status != NPI_SUCCESS) {
36454732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
36464732Sdavemq 			    "clause 22 read to reg 2 failed!!!"));
36474732Sdavemq 			goto error_exit;
36484732Sdavemq 		}
36494732Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
36504732Sdavemq 		    NXGE_PHY_ID_REG_2, &val2);
36514732Sdavemq 		if (npi_status != 0) {
36524732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
36534732Sdavemq 			    "clause 22 read to reg 3 failed!!!"));
36544732Sdavemq 			goto error_exit;
36554732Sdavemq 		}
36564732Sdavemq 		phy_id = val1;
36574732Sdavemq 		phy_id = (phy_id << 16);
36584732Sdavemq 		phy_id |= val2;
36594732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
36604732Sdavemq 		    "[0x%llx]", i, phy_id));
36614732Sdavemq 
36624732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
36634732Sdavemq 			phy_fd[i] = 1;
36644732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
36654732Sdavemq 			    "found", i));
3666*4782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
3667*4782Ssbehera 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
36684732Sdavemq 				l++;
36694732Sdavemq 			}
36704732Sdavemq 		} else {
36714732Sdavemq 			phy_fd[i] = 0;
36724732Sdavemq 		}
36734732Sdavemq 		total_phy_fd += phy_fd[i];
36744732Sdavemq 	}
36754732Sdavemq 
36764732Sdavemq 	switch (total_port_fd) {
36774732Sdavemq 	case 2:
36784732Sdavemq 		switch (total_phy_fd) {
36794732Sdavemq 		case 2:
36804732Sdavemq 			/* 2 10G, 2 1G */
3681*4782Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3682*4782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3683*4782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3684*4782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
3685*4782Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3686*4782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY))) {
36874732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
36884732Sdavemq 			} else {
36894732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36904732Sdavemq 				    "Unsupported neptune type 1"));
36914732Sdavemq 				goto error_exit;
36924732Sdavemq 			}
36934732Sdavemq 			break;
36944732Sdavemq 		case 1:
36954732Sdavemq 			/* TODO - 2 10G, 1 1G */
36964732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
36974732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
36984732Sdavemq 			goto error_exit;
36994732Sdavemq 		case 0:
37004732Sdavemq 			/* 2 10G */
3701*4782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3702*4782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3703*4782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3704*4782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
37054732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF;
37064732Sdavemq 			} else {
37074732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37084732Sdavemq 				    "Unsupported neptune type 2"));
37094732Sdavemq 				goto error_exit;
37104732Sdavemq 			}
37114732Sdavemq 			break;
37124732Sdavemq 		case 4:
37134732Sdavemq 			/* Maramba with 2 XAUI */
3714*4782Ssbehera 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3715*4782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3716*4782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3717*4782Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
3718*4782Ssbehera 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3719*4782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
3720*4782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
3721*4782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
37224732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
37234732Sdavemq 
37244732Sdavemq 				/*
37254732Sdavemq 				 * Check the first phy port address against
37264732Sdavemq 				 * the known phy start addresses to determine
37274732Sdavemq 				 * the platform type.
37284732Sdavemq 				 */
37294732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
37304732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
37314732Sdavemq 					if (phy_fd[i] == 1)
37324732Sdavemq 						break;
37334732Sdavemq 				}
37344732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
37354732Sdavemq 					hw_p->platform_type =
37364732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
37374732Sdavemq 				} else if (i ==
37384732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
37394732Sdavemq 					hw_p->platform_type =
37404732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
37414732Sdavemq 				} else {
37424732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
37434732Sdavemq 					    "Unknown port %d...Cannot "
37444732Sdavemq 					    "determine platform type", i));
37454732Sdavemq 				}
37464732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37474732Sdavemq 				    "Maramba with 2 XAUI"));
37484732Sdavemq 			} else {
37494732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37504732Sdavemq 				    "Unsupported neptune type 3"));
37514732Sdavemq 				goto error_exit;
37524732Sdavemq 			}
37534732Sdavemq 			break;
37544732Sdavemq 		default:
37554732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37564732Sdavemq 			    "Unsupported neptune type 5"));
37574732Sdavemq 			goto error_exit;
37584732Sdavemq 		}
3759*4782Ssbehera 		break;
37604732Sdavemq 	case 1:
37614732Sdavemq 		switch (total_phy_fd) {
37624732Sdavemq 		case 3:
3763*4782Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
3764*4782Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
37654732Sdavemq 				/* The 10G port is BCM8704 */
37664732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
37674732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
37684732Sdavemq 					if (port_fd[i] == 1) {
37694732Sdavemq 						prt_id = i;
37704732Sdavemq 						break;
37714732Sdavemq 					}
37724732Sdavemq 				}
37734732Sdavemq 
37744732Sdavemq 				if (nxgep->niu_type == N2_NIU)
37754732Sdavemq 					prt_id %= BCM8704_N2_PORT_ADDR_BASE;
37764732Sdavemq 				else
37774732Sdavemq 					prt_id %=
37784732Sdavemq 					    BCM8704_NEPTUNE_PORT_ADDR_BASE;
37794732Sdavemq 
37804732Sdavemq 				if (prt_id == 0) {
37814732Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
37824732Sdavemq 				} else if (prt_id == 1) {
37834732Sdavemq 					hw_p->niu_type =
37844732Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
37854732Sdavemq 				} else {
37864732Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37874732Sdavemq 					    "Unsupported neptune type 6"));
37884732Sdavemq 					goto error_exit;
37894732Sdavemq 				}
37904732Sdavemq 			} else {
37914732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37924732Sdavemq 				    "Unsupported neptune type 7"));
37934732Sdavemq 				goto error_exit;
37944732Sdavemq 			}
37954732Sdavemq 			break;
37964732Sdavemq 		case 2:
37974732Sdavemq 			/*
37984732Sdavemq 			 * TODO 2 1G, 1 10G mode.
37994732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
38004732Sdavemq 			 * 1_10G_2_1G
38014732Sdavemq 			 */
38024732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38034732Sdavemq 			    "Unsupported neptune type 8"));
38044732Sdavemq 			goto error_exit;
38054732Sdavemq 		case 1:
38064732Sdavemq 			/*
38074732Sdavemq 			 * TODO 1 1G, 1 10G mode.
38084732Sdavemq 			 * Differentiate between 1_1G_1_10G and
38094732Sdavemq 			 * 1_10G_1_1G
38104732Sdavemq 			 */
38114732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38124732Sdavemq 			    "Unsupported neptune type 9"));
38134732Sdavemq 			goto error_exit;
38144732Sdavemq 		case 0:
38154732Sdavemq 			/* TODO 1 10G mode */
38164732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38174732Sdavemq 			    "Unsupported neptune type 10"));
38184732Sdavemq 			goto error_exit;
38194732Sdavemq 		case 4:
38204732Sdavemq 			/* Maramba with 1 XAUI */
3821*4782Ssbehera 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
3822*4782Ssbehera 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
38234732Sdavemq 				/* The 10G port is BCM8704 */
38244732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
38254732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
38264732Sdavemq 					if (port_fd[i] == 1) {
38274732Sdavemq 						prt_id = i;
38284732Sdavemq 						break;
38294732Sdavemq 					}
38304732Sdavemq 				}
38314732Sdavemq 
38324732Sdavemq 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
38334732Sdavemq 				if (prt_id == 0) {
38344732Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
38354732Sdavemq 				} else if (prt_id == 1) {
38364732Sdavemq 					hw_p->niu_type =
38374732Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
38384732Sdavemq 				} else {
38394732Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38404732Sdavemq 					    "Unsupported neptune type 11"));
38414732Sdavemq 					goto error_exit;
38424732Sdavemq 				}
38434732Sdavemq 
38444732Sdavemq 				/*
38454732Sdavemq 				 * Check the first phy port address against
38464732Sdavemq 				 * the known phy start addresses to determine
38474732Sdavemq 				 * the platform type.
38484732Sdavemq 				 */
38494732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
38504732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
38514732Sdavemq 					if (phy_fd[i] == 1)
38524732Sdavemq 						break;
38534732Sdavemq 				}
38544732Sdavemq 
38554732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
38564732Sdavemq 					hw_p->platform_type =
38574732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
38584732Sdavemq 				} else if (i ==
38594732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
38604732Sdavemq 					hw_p->platform_type =
38614732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
38624732Sdavemq 				} else {
38634732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
38644732Sdavemq 					    "Unknown port %d...Cannot "
38654732Sdavemq 					    "determine platform type", i));
38664732Sdavemq 				}
38674732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38684732Sdavemq 				    "Maramba with 1 XAUI"));
38694732Sdavemq 			} else {
38704732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38714732Sdavemq 				    "Unsupported neptune type 12"));
38724732Sdavemq 				goto error_exit;
38734732Sdavemq 			}
38744732Sdavemq 			break;
38754732Sdavemq 		default:
38764732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
38774732Sdavemq 			    "Unsupported neptune type 13"));
38784732Sdavemq 			goto error_exit;
38794732Sdavemq 		}
38804732Sdavemq 		break;
38814732Sdavemq 	case 0:
38824732Sdavemq 		switch (total_phy_fd) {
38834732Sdavemq 		case 4:
3884*4782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3885*4782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
3886*4782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
3887*4782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
38884732Sdavemq 
38894732Sdavemq 				hw_p->niu_type = NEPTUNE_4_1GC;
38904732Sdavemq 
38914732Sdavemq 				/*
38924732Sdavemq 				 * Check the first phy port address against
38934732Sdavemq 				 * the known phy start addresses to determine
38944732Sdavemq 				 * the platform type.
38954732Sdavemq 				 */
38964732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
38974732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
38984732Sdavemq 					if (phy_fd[i] == 1)
38994732Sdavemq 						break;
39004732Sdavemq 				}
39014732Sdavemq 
39024732Sdavemq 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
39034732Sdavemq 					hw_p->platform_type =
39044732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
39054732Sdavemq 				}
39064732Sdavemq 			} else {
39074732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39084732Sdavemq 				    "Unsupported neptune type 14"));
39094732Sdavemq 				goto error_exit;
39104732Sdavemq 			}
39114732Sdavemq 			break;
39124732Sdavemq 		case 3:
39134732Sdavemq 			/* TODO 3 1G mode */
39144732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39154732Sdavemq 			    "Unsupported neptune type 15"));
39164732Sdavemq 			goto error_exit;
39174732Sdavemq 		case 2:
39184732Sdavemq 			/* TODO 2 1G mode */
39194732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39204732Sdavemq 			    "Unsupported neptune type 16"));
39214732Sdavemq 			goto error_exit;
39224732Sdavemq 		case 1:
39234732Sdavemq 			/* TODO 1 1G mode */
39244732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39254732Sdavemq 			    "Unsupported neptune type 17"));
39264732Sdavemq 			goto error_exit;
39274732Sdavemq 		default:
39284732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39294732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
39304732Sdavemq 			    total_phy_fd));
39314732Sdavemq 			goto error_exit;
39324732Sdavemq 		}
39334732Sdavemq 		break;
39344732Sdavemq 	default:
39354732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39364732Sdavemq 		    "Unsupported neptune type 19"));
39374732Sdavemq 		goto error_exit;
39384732Sdavemq 	}
39394732Sdavemq 
39404732Sdavemq scan_exit:
39414732Sdavemq 
39424732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
39434732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
39444732Sdavemq 	return (status);
39454732Sdavemq 
39464732Sdavemq error_exit:
39474732Sdavemq 	return (NXGE_ERROR);
39484732Sdavemq }
39494732Sdavemq 
39504185Sspeer boolean_t
39514185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
39524185Sspeer {
39534185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
39544185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
39554185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
39564185Sspeer 		return (B_FALSE);
39574185Sspeer 	else
39584185Sspeer 		return (B_TRUE);
39594185Sspeer }
39604732Sdavemq 
39614732Sdavemq static void
39624732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
39634732Sdavemq 
39644732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
39654732Sdavemq 	uint8_t xcvr_portn;
39664732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
39674732Sdavemq 
39684732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
39694732Sdavemq 
39704732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
39714732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
39724732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
39734732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
39744732Sdavemq 	}
39754732Sdavemq 	/*
39764732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
39774732Sdavemq 	 * swapped with ethernet port number. This is
39784732Sdavemq 	 * designed for better signal integrity in routing.
39794732Sdavemq 	 */
39804732Sdavemq 	switch (portn) {
39814732Sdavemq 	case 0:
39824732Sdavemq 		xcvr_portn += 3;
39834732Sdavemq 		break;
39844732Sdavemq 	case 1:
39854732Sdavemq 		xcvr_portn += 2;
39864732Sdavemq 		break;
39874732Sdavemq 	case 2:
39884732Sdavemq 		xcvr_portn += 1;
39894732Sdavemq 		break;
39904732Sdavemq 	case 3:
39914732Sdavemq 	default:
39924732Sdavemq 		break;
39934732Sdavemq 	}
39944732Sdavemq 
39954732Sdavemq 	MUTEX_ENTER(&nxge_mii_lock);
39964732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
39974732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
39984732Sdavemq 	if (rs != NPI_SUCCESS) {
39994732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40004732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
40014732Sdavemq 		    "returned error 0x[%x]", rs));
40024732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
40034732Sdavemq 		return;
40044732Sdavemq 	}
40054732Sdavemq 
40064732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
40074732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
40084732Sdavemq 	if (rs != NPI_SUCCESS) {
40094732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40104732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
40114732Sdavemq 		    "returned error 0x[%x]", rs));
40124732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
40134732Sdavemq 		return;
40144732Sdavemq 	}
40154732Sdavemq 
40164732Sdavemq 	MUTEX_EXIT(&nxge_mii_lock);
40174732Sdavemq }
4018