xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 4732:4edaffb4494b)
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;
35*4732Sdavemq 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}};
53*4732Sdavemq /*
54*4732Sdavemq  * Ethernet zero address definition.
55*4732Sdavemq  */
564185Sspeer static ether_addr_st etherzeroaddr =
574185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
58*4732Sdavemq /*
59*4732Sdavemq  * Supported chip types
60*4732Sdavemq  */
61*4732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
62*4732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
63*4732Sdavemq 
64*4732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
65*4732Sdavemq 				sizeof (uint32_t))
66*4732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
67*4732Sdavemq 				sizeof (uint32_t))
68*4732Sdavemq /*
69*4732Sdavemq  * static functions
70*4732Sdavemq  */
71*4732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
72*4732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
73*4732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
74*4732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
75*4732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
76*4732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
77*4732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
78*4732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
79*4732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
80*4732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
81*4732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
82*4732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
83*4732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
84*4732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
85*4732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
86*4732Sdavemq 
87*4732Sdavemq /*
88*4732Sdavemq  * xcvr tables for supported transceivers
89*4732Sdavemq  */
90*4732Sdavemq 
91*4732Sdavemq static nxge_xcvr_table_t nxge_n2_table = {
92*4732Sdavemq 	nxge_n2_serdes_init,
93*4732Sdavemq 	nxge_10G_xcvr_init,
94*4732Sdavemq 	nxge_10G_link_intr_stop,
95*4732Sdavemq 	nxge_10G_link_intr_start,
96*4732Sdavemq 	nxge_check_10g_link,
97*4732Sdavemq 	BCM8704_DEV_ID,
98*4732Sdavemq 	PCS_XCVR,
99*4732Sdavemq 	BCM8704_N2_PORT_ADDR_BASE
100*4732Sdavemq };
101*4732Sdavemq 
102*4732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
103*4732Sdavemq 	nxge_neptune_10G_serdes_init,
104*4732Sdavemq 	nxge_10G_xcvr_init,
105*4732Sdavemq 	nxge_10G_link_intr_stop,
106*4732Sdavemq 	nxge_10G_link_intr_start,
107*4732Sdavemq 	nxge_check_10g_link,
108*4732Sdavemq 	BCM8704_DEV_ID,
109*4732Sdavemq 	PCS_XCVR,
110*4732Sdavemq 	BCM8704_NEPTUNE_PORT_ADDR_BASE
111*4732Sdavemq };
112*4732Sdavemq 
113*4732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
114*4732Sdavemq 	NULL,
115*4732Sdavemq 	nxge_1G_xcvr_init,
116*4732Sdavemq 	nxge_1G_copper_link_intr_stop,
117*4732Sdavemq 	nxge_1G_copper_link_intr_start,
118*4732Sdavemq 	nxge_check_mii_link,
119*4732Sdavemq 	BCM5464R_PHY_ID,
120*4732Sdavemq 	INT_MII_XCVR,
121*4732Sdavemq 	BCM5464_NEPTUNE_PORT_ADDR_BASE
122*4732Sdavemq };
123*4732Sdavemq 
124*4732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
125*4732Sdavemq 	nxge_1G_serdes_init,
126*4732Sdavemq 	nxge_1G_xcvr_init,
127*4732Sdavemq 	nxge_1G_fiber_link_intr_stop,
128*4732Sdavemq 	nxge_1G_fiber_link_intr_start,
129*4732Sdavemq 	nxge_check_mii_link,
130*4732Sdavemq 	0,
131*4732Sdavemq 	PCS_XCVR,
132*4732Sdavemq 	0
133*4732Sdavemq };
134*4732Sdavemq 
135*4732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
136*4732Sdavemq 	nxge_neptune_10G_serdes_init,
137*4732Sdavemq 	NULL,
138*4732Sdavemq 	NULL,
139*4732Sdavemq 	NULL,
140*4732Sdavemq 	0,
141*4732Sdavemq 	PCS_XCVR,
142*4732Sdavemq 	0
143*4732Sdavemq };
1443859Sml29623 
1453859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t);
1463859Sml29623 
147*4732Sdavemq /* Set up the PHY specific values. */
148*4732Sdavemq 
149*4732Sdavemq nxge_status_t
150*4732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
151*4732Sdavemq {
152*4732Sdavemq 	nxge_status_t	status = NXGE_OK;
153*4732Sdavemq 	uint32_t	port_type;
154*4732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
155*4732Sdavemq 
156*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
157*4732Sdavemq 	    portn));
158*4732Sdavemq 
159*4732Sdavemq 	if (nxgep->niu_type == N2_NIU) {
160*4732Sdavemq 		nxgep->mac.portmode = PORT_10G_FIBER;
161*4732Sdavemq 		nxgep->xcvr = nxge_n2_table;
162*4732Sdavemq 		nxgep->xcvr.xcvr_addr += portn;
163*4732Sdavemq 	} else {
164*4732Sdavemq 		port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn);
165*4732Sdavemq 		port_type = port_type & (NXGE_PORT_TYPE_MASK);
166*4732Sdavemq 		switch (port_type) {
167*4732Sdavemq 		case NXGE_PORT_1G_COPPER:
168*4732Sdavemq 			nxgep->mac.portmode = PORT_1G_COPPER;
169*4732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
170*4732Sdavemq 			if (nxgep->nxge_hw_p->platform_type ==
171*4732Sdavemq 			    P_NEPTUNE_MARAMBA_P1) {
172*4732Sdavemq 				nxgep->xcvr.xcvr_addr =
173*4732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
174*4732Sdavemq 			} else if (nxgep->nxge_hw_p->platform_type ==
175*4732Sdavemq 			    P_NEPTUNE_MARAMBA_P0) {
176*4732Sdavemq 				nxgep->xcvr.xcvr_addr =
177*4732Sdavemq 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
178*4732Sdavemq 			}
179*4732Sdavemq 			/*
180*4732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
181*4732Sdavemq 			 * swapped with ethernet port number. This is
182*4732Sdavemq 			 * designed for better signal integrity in routing.
183*4732Sdavemq 			 */
184*4732Sdavemq 			switch (portn) {
185*4732Sdavemq 			case 0:
186*4732Sdavemq 				nxgep->xcvr.xcvr_addr += 3;
187*4732Sdavemq 				break;
188*4732Sdavemq 			case 1:
189*4732Sdavemq 				nxgep->xcvr.xcvr_addr += 2;
190*4732Sdavemq 				break;
191*4732Sdavemq 			case 2:
192*4732Sdavemq 				nxgep->xcvr.xcvr_addr += 1;
193*4732Sdavemq 				break;
194*4732Sdavemq 			case 3:
195*4732Sdavemq 				break;
196*4732Sdavemq 			default:
197*4732Sdavemq 				return (NXGE_ERROR);
198*4732Sdavemq 			}
199*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
200*4732Sdavemq 			break;
201*4732Sdavemq 		case NXGE_PORT_10G_COPPER:
202*4732Sdavemq 			nxgep->mac.portmode = PORT_10G_COPPER;
203*4732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
204*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
205*4732Sdavemq 			break;
206*4732Sdavemq 		case NXGE_PORT_1G_FIBRE:
207*4732Sdavemq 			nxgep->mac.portmode = PORT_1G_FIBER;
208*4732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
209*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr"));
210*4732Sdavemq 			break;
211*4732Sdavemq 		case NXGE_PORT_10G_FIBRE:
212*4732Sdavemq 			nxgep->mac.portmode = PORT_10G_FIBER;
213*4732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
214*4732Sdavemq 			if ((nxgep->nxge_hw_p->platform_type ==
215*4732Sdavemq 			    P_NEPTUNE_MARAMBA_P0) ||
216*4732Sdavemq 			    (nxgep->nxge_hw_p->platform_type ==
217*4732Sdavemq 			    P_NEPTUNE_MARAMBA_P1)) {
218*4732Sdavemq 				nxgep->xcvr.xcvr_addr =
219*4732Sdavemq 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
220*4732Sdavemq 				/*
221*4732Sdavemq 				 * Switch off LED for corresponding copper
222*4732Sdavemq 				 * port
223*4732Sdavemq 				 */
224*4732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
225*4732Sdavemq 			}
226*4732Sdavemq 			nxgep->xcvr.xcvr_addr += portn;
227*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr"));
228*4732Sdavemq 			break;
229*4732Sdavemq 		default:
230*4732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
231*4732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
232*4732Sdavemq 			return (NXGE_ERROR);
233*4732Sdavemq 		}
234*4732Sdavemq 	}
235*4732Sdavemq 
236*4732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
237*4732Sdavemq 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
238*4732Sdavemq 	nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id;
239*4732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
240*4732Sdavemq 
241*4732Sdavemq 	return (status);
242*4732Sdavemq }
243*4732Sdavemq 
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,
573*4732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
5743859Sml29623 #endif
5753859Sml29623 
576*4732Sdavemq 	if (nxgep->xcvr.serdes_init) {
577*4732Sdavemq 		statsp = nxgep->statsp;
578*4732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
579*4732Sdavemq 		if (status != NXGE_OK)
5803859Sml29623 			goto fail;
581*4732Sdavemq 		statsp->mac_stats.serdes_inits++;
5823859Sml29623 	}
5833859Sml29623 
5843859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
585*4732Sdavemq 	    portn));
5863859Sml29623 
5873859Sml29623 	return (NXGE_OK);
5883859Sml29623 
5893859Sml29623 fail:
5903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
591*4732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
592*4732Sdavemq 	    portn));
5933859Sml29623 
5943859Sml29623 	return (status);
5953859Sml29623 }
5963859Sml29623 
5973859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
5983859Sml29623 
599*4732Sdavemq 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 
724*4732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
725*4732Sdavemq 
726*4732Sdavemq static nxge_status_t
727*4732Sdavemq 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 
746*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
747*4732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
7483859Sml29623 
7493859Sml29623 	handle = nxgep->npi_handle;
750*4732Sdavemq 	switch (portn) {
751*4732Sdavemq 	case 0:
752*4732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
753*4732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
754*4732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
755*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
756*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
757*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
758*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
759*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
760*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
761*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
762*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
763*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
764*4732Sdavemq 
765*4732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
766*4732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
767*4732Sdavemq 			ESR_REG_WR(handle,
768*4732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
769*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
770*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
771*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
772*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
773*4732Sdavemq 		} else {
774*4732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
7753859Sml29623 		}
776*4732Sdavemq 		break;
777*4732Sdavemq 	case 1:
778*4732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
779*4732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
780*4732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
781*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
782*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
783*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
784*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
785*4732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
786*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
787*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
788*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
789*4732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
790*4732Sdavemq 
791*4732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
792*4732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
793*4732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
794*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
795*4732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
796*4732Sdavemq 		} else {
797*4732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
7983859Sml29623 		}
799*4732Sdavemq 		break;
800*4732Sdavemq 	default:
801*4732Sdavemq 		/* Nothing to do here */
802*4732Sdavemq 		goto done;
803*4732Sdavemq 	}
804*4732Sdavemq 
805*4732Sdavemq 	/* init TX RX channels */
806*4732Sdavemq 	for (chan = 0; chan < 4; chan++) {
807*4732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
808*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
809*4732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
8103859Sml29623 			goto fail;
811*4732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
812*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
813*4732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
8143859Sml29623 			goto fail;
8153859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
816*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
817*4732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
8183859Sml29623 			goto fail;
8193859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
820*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
821*4732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
822*4732Sdavemq 			goto fail;
823*4732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
824*4732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
825*4732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
826*4732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
827*4732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
828*4732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
829*4732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
830*4732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
831*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
832*4732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
833*4732Sdavemq 			goto fail;
834*4732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
835*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
836*4732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
837*4732Sdavemq 			goto fail;
838*4732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
839*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
840*4732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
841*4732Sdavemq 			goto fail;
842*4732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
843*4732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
844*4732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
8453859Sml29623 			goto fail;
8463859Sml29623 		}
8473859Sml29623 
848*4732Sdavemq 	/* Apply Tx core reset */
849*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
850*4732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
851*4732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
852*4732Sdavemq 		goto fail;
853*4732Sdavemq 
854*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
855*4732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
856*4732Sdavemq 	    NXGE_OK)
857*4732Sdavemq 		goto fail;
858*4732Sdavemq 
859*4732Sdavemq 	NXGE_DELAY(200);
860*4732Sdavemq 
861*4732Sdavemq 	/* Apply Rx core reset */
862*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
863*4732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
864*4732Sdavemq 	    NXGE_OK)
865*4732Sdavemq 		goto fail;
866*4732Sdavemq 
867*4732Sdavemq 	NXGE_DELAY(200);
868*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
869*4732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
870*4732Sdavemq 		goto fail;
871*4732Sdavemq 
872*4732Sdavemq 	NXGE_DELAY(200);
873*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
874*4732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
875*4732Sdavemq 	    &val16l)) != NXGE_OK)
876*4732Sdavemq 		goto fail;
877*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
878*4732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
879*4732Sdavemq 		goto fail;
880*4732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
881*4732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
882*4732Sdavemq 		    "Failed to reset port<%d> XAUI Serdes", portn));
883*4732Sdavemq 	}
884*4732Sdavemq 
885*4732Sdavemq 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
886*4732Sdavemq 
887*4732Sdavemq 	if (portn == 0) {
888*4732Sdavemq 		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)) {
895*4732Sdavemq 			goto fail;
896*4732Sdavemq 		}
897*4732Sdavemq 	} else if (portn == 1) {
898*4732Sdavemq 		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:
910*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
911*4732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
912*4732Sdavemq 
9133859Sml29623 	return (NXGE_OK);
9143859Sml29623 fail:
915*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
916*4732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
917*4732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
9183859Sml29623 
9193859Sml29623 	return (status);
9203859Sml29623 }
9213859Sml29623 
922*4732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
923*4732Sdavemq 
924*4732Sdavemq static nxge_status_t
925*4732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
9263859Sml29623 {
927*4732Sdavemq 	npi_handle_t		handle;
928*4732Sdavemq 	uint8_t			portn;
929*4732Sdavemq 	uint64_t		val;
9303859Sml29623 
9313859Sml29623 	portn = nxgep->mac.portnum;
932*4732Sdavemq 
933*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
934*4732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
935*4732Sdavemq 
936*4732Sdavemq 	handle = nxgep->npi_handle;
937*4732Sdavemq 
938*4732Sdavemq 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
939*4732Sdavemq 	val &= ~ESR_PLL_CFG_FBDIV_2;
940*4732Sdavemq 	switch (portn) {
941*4732Sdavemq 	case 0:
942*4732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_0;
943*4732Sdavemq 		break;
944*4732Sdavemq 	case 1:
945*4732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_1;
946*4732Sdavemq 		break;
947*4732Sdavemq 	case 2:
948*4732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_2;
949*4732Sdavemq 		break;
950*4732Sdavemq 	case 3:
951*4732Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_3;
952*4732Sdavemq 		break;
953*4732Sdavemq 	default:
954*4732Sdavemq 		goto fail;
9553859Sml29623 	}
9563859Sml29623 
957*4732Sdavemq 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
958*4732Sdavemq 
959*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
960*4732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
9613859Sml29623 	return (NXGE_OK);
962*4732Sdavemq fail:
963*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
964*4732Sdavemq 	    "nxge_1G_serdes_init: "
965*4732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
966*4732Sdavemq 	    portn));
967*4732Sdavemq 
968*4732Sdavemq 	return (NXGE_ERROR);
9693859Sml29623 }
9703859Sml29623 
971*4732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */
972*4732Sdavemq 
973*4732Sdavemq static nxge_status_t
974*4732Sdavemq 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
993*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
994*4732Sdavemq 	    portn));
995*4732Sdavemq 
996*4732Sdavemq 	statsp = nxgep->statsp;
997*4732Sdavemq 
998*4732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
999*4732Sdavemq 
1000*4732Sdavemq 	/* Disable Link LEDs */
1001*4732Sdavemq 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1002*4732Sdavemq 		goto fail;
1003*4732Sdavemq 
1004*4732Sdavemq 	/* Set Clause 45 */
1005*4732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
1006*4732Sdavemq 
1007*4732Sdavemq 	/* Reset the transceiver */
1008*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1009*4732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
1010*4732Sdavemq 		goto fail;
1011*4732Sdavemq 
1012*4732Sdavemq 	phyxs_ctl.bits.reset = 1;
1013*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1014*4732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
1015*4732Sdavemq 		goto fail;
1016*4732Sdavemq 
1017*4732Sdavemq 	do {
1018*4732Sdavemq 		drv_usecwait(500);
1019*4732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1020*4732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
1021*4732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
1022*4732Sdavemq 			goto fail;
1023*4732Sdavemq 		delay++;
1024*4732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
1025*4732Sdavemq 	if (delay == 100) {
1026*4732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
1027*4732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
1028*4732Sdavemq 		status = NXGE_ERROR;
1029*4732Sdavemq 		goto fail;
1030*4732Sdavemq 	}
1031*4732Sdavemq 
1032*4732Sdavemq 	/* Set to 0x7FBF */
1033*4732Sdavemq 	ctl.value = 0;
1034*4732Sdavemq 	ctl.bits.res1 = 0x3F;
1035*4732Sdavemq 	ctl.bits.optxon_lvl = 1;
1036*4732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
1037*4732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
1038*4732Sdavemq 	ctl.bits.optxflt_lvl = 1;
1039*4732Sdavemq 	ctl.bits.opprflt_lvl = 1;
1040*4732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
1041*4732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
1042*4732Sdavemq 	ctl.bits.optxrst_lvl = 1;
1043*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1044*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
1045*4732Sdavemq 	    != NXGE_OK)
1046*4732Sdavemq 		goto fail;
1047*4732Sdavemq 
1048*4732Sdavemq 	/* Set to 0x164 */
1049*4732Sdavemq 	tx_ctl.value = 0;
1050*4732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
1051*4732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
1052*4732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
1053*4732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
1054*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1055*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
1056*4732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
1057*4732Sdavemq 		goto fail;
1058*4732Sdavemq 	/*
1059*4732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
1060*4732Sdavemq 	 * back these registers twice after written.
1061*4732Sdavemq 	 */
1062*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1063*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1064*4732Sdavemq 	    != NXGE_OK)
1065*4732Sdavemq 		goto fail;
1066*4732Sdavemq 
1067*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1068*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1069*4732Sdavemq 	    != NXGE_OK)
1070*4732Sdavemq 		goto fail;
1071*4732Sdavemq 
1072*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1073*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1074*4732Sdavemq 	    != NXGE_OK)
1075*4732Sdavemq 		goto fail;
1076*4732Sdavemq 
1077*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1078*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1079*4732Sdavemq 	    != NXGE_OK)
1080*4732Sdavemq 		goto fail;
1081*4732Sdavemq 
1082*4732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
1083*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1084*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1085*4732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
1086*4732Sdavemq 		goto fail;
1087*4732Sdavemq 	op_ctr.bits.gpio_sel = 0x3;
1088*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1089*4732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1090*4732Sdavemq 	    op_ctr.value)) != NXGE_OK)
1091*4732Sdavemq 		goto fail;
1092*4732Sdavemq 
1093*4732Sdavemq 	NXGE_DELAY(1000000);
1094*4732Sdavemq 
1095*4732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
1096*4732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1097*4732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
1098*4732Sdavemq 	    != NXGE_OK)
1099*4732Sdavemq 		goto fail;
1100*4732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
1101*4732Sdavemq 		pcs_ctl.bits.loopback = 1;
1102*4732Sdavemq 	else
1103*4732Sdavemq 		pcs_ctl.bits.loopback = 0;
1104*4732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1105*4732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
1106*4732Sdavemq 	    != NXGE_OK)
1107*4732Sdavemq 		goto fail;
1108*4732Sdavemq 
1109*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
1110*4732Sdavemq 	if (status != NXGE_OK)
1111*4732Sdavemq 		goto fail;
1112*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1113*4732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
1114*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
1115*4732Sdavemq 	if (status != NXGE_OK)
1116*4732Sdavemq 		goto fail;
1117*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1118*4732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
1119*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
1120*4732Sdavemq 	if (status != NXGE_OK)
1121*4732Sdavemq 		goto fail;
1122*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1123*4732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
1124*4732Sdavemq 
1125*4732Sdavemq #ifdef	NXGE_DEBUG
1126*4732Sdavemq 	/* Diagnose link issue if link is not up */
1127*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
1128*4732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
1129*4732Sdavemq 	    &val);
1130*4732Sdavemq 	if (status != NXGE_OK)
1131*4732Sdavemq 		goto fail;
1132*4732Sdavemq 
1133*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
1134*4732Sdavemq 				BCM8704_USER_DEV3_ADDR,
1135*4732Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
1136*4732Sdavemq 				&val);
1137*4732Sdavemq 	if (status != NXGE_OK)
1138*4732Sdavemq 		goto fail;
1139*4732Sdavemq 
1140*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
1141*4732Sdavemq 				BCM8704_USER_DEV3_ADDR,
1142*4732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
1143*4732Sdavemq 				&val1);
1144*4732Sdavemq 	if (status != NXGE_OK)
1145*4732Sdavemq 		goto fail;
1146*4732Sdavemq 
1147*4732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
1148*4732Sdavemq 				BCM8704_USER_DEV3_ADDR,
1149*4732Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
1150*4732Sdavemq 				&val1);
1151*4732Sdavemq 	if (status != NXGE_OK)
1152*4732Sdavemq 		goto fail;
1153*4732Sdavemq 
1154*4732Sdavemq 	if (val != 0x3FC) {
1155*4732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
1156*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1157*4732Sdavemq 			    "Cable not connected to peer or bad"
1158*4732Sdavemq 			    " cable on port<%d>\n", portn));
1159*4732Sdavemq 		} else if (val == 0x639C) {
1160*4732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1161*4732Sdavemq 			    "Optical module (XFP) is bad or absent"
1162*4732Sdavemq 			    " on port<%d>\n", portn));
1163*4732Sdavemq 		}
1164*4732Sdavemq 	}
1165*4732Sdavemq #endif
1166*4732Sdavemq 
1167*4732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
1168*4732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
1169*4732Sdavemq 
1170*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
1171*4732Sdavemq 	    portn));
1172*4732Sdavemq 	return (NXGE_OK);
1173*4732Sdavemq 
1174*4732Sdavemq fail:
1175*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1176*4732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
1177*4732Sdavemq 	    "port<%d>", portn));
1178*4732Sdavemq 	return (status);
1179*4732Sdavemq }
1180*4732Sdavemq 
1181*4732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
1182*4732Sdavemq 
1183*4732Sdavemq static nxge_status_t
1184*4732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
1185*4732Sdavemq {
1186*4732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
1187*4732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
1188*4732Sdavemq 	nxge_status_t		status = NXGE_OK;
1189*4732Sdavemq 
1190*4732Sdavemq 	/* Set Clause 22 */
1191*4732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
1192*4732Sdavemq 
1193*4732Sdavemq 	/* Set capability flags */
1194*4732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
1195*4732Sdavemq 	statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value;
1196*4732Sdavemq 	statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
1197*4732Sdavemq 
1198*4732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
1199*4732Sdavemq 
1200*4732Sdavemq 	return (status);
1201*4732Sdavemq }
1202*4732Sdavemq 
1203*4732Sdavemq /* Initialize transceiver */
1204*4732Sdavemq 
1205*4732Sdavemq nxge_status_t
1206*4732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
1207*4732Sdavemq {
1208*4732Sdavemq 	p_nxge_stats_t		statsp;
1209*4732Sdavemq #ifdef	NXGE_DEBUG
1210*4732Sdavemq 	uint8_t			portn;
1211*4732Sdavemq #endif
1212*4732Sdavemq 
1213*4732Sdavemq 	nxge_status_t		status = NXGE_OK;
1214*4732Sdavemq #ifdef	NXGE_DEBUG
1215*4732Sdavemq 	portn = nxgep->mac.portnum;
1216*4732Sdavemq #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 
1243*4732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
1244*4732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
12453859Sml29623 		if (status != NXGE_OK)
12463859Sml29623 			goto fail;
1247*4732Sdavemq 		statsp->mac_stats.xcvr_inits++;
12483859Sml29623 	}
12493859Sml29623 
1250*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
1251*4732Sdavemq 	    portn));
12523859Sml29623 	return (NXGE_OK);
12533859Sml29623 
12543859Sml29623 fail:
12553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1256*4732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
1257*4732Sdavemq 	    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 
1727*4732Sdavemq /* 10G fiber link interrupt start routine */
1728*4732Sdavemq 
1729*4732Sdavemq static nxge_status_t
1730*4732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
1731*4732Sdavemq {
1732*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1733*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1734*4732Sdavemq 
1735*4732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
1736*4732Sdavemq 
1737*4732Sdavemq 	if (rs != NPI_SUCCESS)
1738*4732Sdavemq 		return (NXGE_ERROR | rs);
1739*4732Sdavemq 	else
1740*4732Sdavemq 		return (NXGE_OK);
1741*4732Sdavemq }
1742*4732Sdavemq 
1743*4732Sdavemq /* 10G fiber link interrupt stop routine */
1744*4732Sdavemq 
1745*4732Sdavemq static nxge_status_t
1746*4732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
1747*4732Sdavemq {
1748*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1749*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1750*4732Sdavemq 
1751*4732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
1752*4732Sdavemq 
1753*4732Sdavemq 	if (rs != NPI_SUCCESS)
1754*4732Sdavemq 		return (NXGE_ERROR | rs);
1755*4732Sdavemq 	else
1756*4732Sdavemq 		return (NXGE_OK);
1757*4732Sdavemq }
1758*4732Sdavemq 
1759*4732Sdavemq /* 1G fiber link interrupt start routine */
1760*4732Sdavemq 
1761*4732Sdavemq static nxge_status_t
1762*4732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
1763*4732Sdavemq {
1764*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1765*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1766*4732Sdavemq 
1767*4732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
1768*4732Sdavemq 	if (rs != NPI_SUCCESS)
1769*4732Sdavemq 		return (NXGE_ERROR | rs);
1770*4732Sdavemq 	else
1771*4732Sdavemq 		return (NXGE_OK);
1772*4732Sdavemq }
1773*4732Sdavemq 
1774*4732Sdavemq /* 1G fiber link interrupt stop routine */
1775*4732Sdavemq 
1776*4732Sdavemq static nxge_status_t
1777*4732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
1778*4732Sdavemq {
1779*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1780*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1781*4732Sdavemq 
1782*4732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
1783*4732Sdavemq 
1784*4732Sdavemq 	if (rs != NPI_SUCCESS)
1785*4732Sdavemq 		return (NXGE_ERROR | rs);
1786*4732Sdavemq 	else
1787*4732Sdavemq 		return (NXGE_OK);
1788*4732Sdavemq }
1789*4732Sdavemq 
1790*4732Sdavemq /* 1G copper link interrupt start routine */
1791*4732Sdavemq 
1792*4732Sdavemq static nxge_status_t
1793*4732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
1794*4732Sdavemq {
1795*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1796*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1797*4732Sdavemq 
1798*4732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
1799*4732Sdavemq 	    MII_BMSR, BMSR_LSTATUS);
1800*4732Sdavemq 
1801*4732Sdavemq 	if (rs != NPI_SUCCESS)
1802*4732Sdavemq 		return (NXGE_ERROR | rs);
1803*4732Sdavemq 	else
1804*4732Sdavemq 		return (NXGE_OK);
1805*4732Sdavemq }
1806*4732Sdavemq 
1807*4732Sdavemq /* 1G copper link interrupt stop routine */
1808*4732Sdavemq 
1809*4732Sdavemq static nxge_status_t
1810*4732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
1811*4732Sdavemq {
1812*4732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1813*4732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1814*4732Sdavemq 
1815*4732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
1816*4732Sdavemq 
1817*4732Sdavemq 	if (rs != NPI_SUCCESS)
1818*4732Sdavemq 		return (NXGE_ERROR | rs);
1819*4732Sdavemq 	else
1820*4732Sdavemq 		return (NXGE_OK);
1821*4732Sdavemq }
1822*4732Sdavemq 
1823*4732Sdavemq /* 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 {
1828*4732Sdavemq 	uint8_t		portn;
1829*4732Sdavemq 	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));
1834*4732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
1835*4732Sdavemq 		return (NXGE_OK);
1836*4732Sdavemq 
1837*4732Sdavemq 	if (enable == LINK_INTR_START)
1838*4732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
1839*4732Sdavemq 	else if (enable == LINK_INTR_STOP)
1840*4732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
1841*4732Sdavemq 	if (status != NXGE_OK)
1842*4732Sdavemq 		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 
1852*4732Sdavemq 	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 
2671*4732Sdavemq 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) {
2737*4732Sdavemq 		cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n",
2738*4732Sdavemq 		    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*/
2774*4732Sdavemq 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,
2816*4732Sdavemq 			    "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 {
2846*4732Sdavemq 	p_nxge_stats_t statsp;
2847*4732Sdavemq 	char link_stat_msg[64];
2848*4732Sdavemq 
28493859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
28503859Sml29623 
2851*4732Sdavemq 	statsp = nxgep->statsp;
2852*4732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
2853*4732Sdavemq 	    statsp->mac_stats.xcvr_portn);
2854*4732Sdavemq 
2855*4732Sdavemq 	if (nxge_no_msg == B_FALSE) {
2856*4732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2857*4732Sdavemq 	}
2858*4732Sdavemq 
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 {
2869*4732Sdavemq 	p_nxge_stats_t statsp;
2870*4732Sdavemq 	char link_stat_msg[64];
28713859Sml29623 	uint32_t val;
28723859Sml29623 
28733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
28743859Sml29623 
2875*4732Sdavemq 	statsp = nxgep->statsp;
2876*4732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
2877*4732Sdavemq 	    statsp->mac_stats.xcvr_portn,
2878*4732Sdavemq 	    statsp->mac_stats.link_speed);
2879*4732Sdavemq 
2880*4732Sdavemq 	if (statsp->mac_stats.link_T4)
2881*4732Sdavemq 		(void) strcat(link_stat_msg, "T4");
2882*4732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
2883*4732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
2884*4732Sdavemq 	else
2885*4732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
2886*4732Sdavemq 
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 
2897*4732Sdavemq 	if (nxge_no_msg == B_FALSE) {
2898*4732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2899*4732Sdavemq 	}
2900*4732Sdavemq 
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 
2987*4732Sdavemq 			if (nxgep->xcvr.check_link) {
2988*4732Sdavemq 				timerid = timeout(
2989*4732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
29904693Stm144005 				    nxgep,
29914693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
2992*4732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
2993*4732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
2994*4732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
2995*4732Sdavemq 			} 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 
3049*4732Sdavemq 	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: "
3075*4732Sdavemq 	    "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: "
3130*4732Sdavemq 	    "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,
3141*4732Sdavemq 	    "==> 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)
3496*4732Sdavemq 	    != 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)
3506*4732Sdavemq 	    != NPI_SUCCESS)
35073859Sml29623 		return (NXGE_ERROR);
35083859Sml29623 	else
35093859Sml29623 		return (NXGE_OK);
35103859Sml29623 }
35114185Sspeer 
3512*4732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
3513*4732Sdavemq 
3514*4732Sdavemq static boolean_t
3515*4732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
3516*4732Sdavemq {
3517*4732Sdavemq 	int		i;
3518*4732Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
3519*4732Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
3520*4732Sdavemq 	boolean_t	found = B_FALSE;
3521*4732Sdavemq 
3522*4732Sdavemq 	switch (type) {
3523*4732Sdavemq 	case CLAUSE_45_TYPE:
3524*4732Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
3525*4732Sdavemq 			if ((nxge_supported_cl45_ids[i] & PHY_ID_MASK) ==
3526*4732Sdavemq 			    (id & PHY_ID_MASK)) {
3527*4732Sdavemq 				found = B_TRUE;
3528*4732Sdavemq 				break;
3529*4732Sdavemq 			}
3530*4732Sdavemq 		}
3531*4732Sdavemq 		break;
3532*4732Sdavemq 	case CLAUSE_22_TYPE:
3533*4732Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
3534*4732Sdavemq 			if ((nxge_supported_cl22_ids[i] & PHY_ID_MASK) ==
3535*4732Sdavemq 			    (id & PHY_ID_MASK)) {
3536*4732Sdavemq 				found = B_TRUE;
3537*4732Sdavemq 				break;
3538*4732Sdavemq 			}
3539*4732Sdavemq 		}
3540*4732Sdavemq 		break;
3541*4732Sdavemq 	default:
3542*4732Sdavemq 		break;
3543*4732Sdavemq 	}
3544*4732Sdavemq 
3545*4732Sdavemq 	return (found);
3546*4732Sdavemq }
3547*4732Sdavemq 
3548*4732Sdavemq /*
3549*4732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
3550*4732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
3551*4732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
3552*4732Sdavemq  * and the Neptune type.
3553*4732Sdavemq  */
3554*4732Sdavemq 
3555*4732Sdavemq nxge_status_t
3556*4732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
3557*4732Sdavemq {
3558*4732Sdavemq 	int		i, j, k, l;
3559*4732Sdavemq 	uint16_t	val1 = 0;
3560*4732Sdavemq 	uint16_t	val2 = 0;
3561*4732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
3562*4732Sdavemq 	uint32_t	pcs_dev_id = 0;
3563*4732Sdavemq 	uint32_t	phy_id = 0;
3564*4732Sdavemq 	uint32_t	port_pma_pmd_dev_id[4];
3565*4732Sdavemq 	uint32_t	port_pcs_dev_id[4];
3566*4732Sdavemq 	uint32_t	port_phy_id[4];
3567*4732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
3568*4732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
3569*4732Sdavemq 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
3570*4732Sdavemq 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
3571*4732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
3572*4732Sdavemq 	nxge_status_t	status = NXGE_OK;
3573*4732Sdavemq 	npi_status_t	npi_status = NPI_SUCCESS;
3574*4732Sdavemq 	npi_handle_t	handle;
3575*4732Sdavemq 	int		prt_id = -1;
3576*4732Sdavemq 
3577*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
3578*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3579*4732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
3580*4732Sdavemq 	    nxgep->niu_type));
3581*4732Sdavemq 
3582*4732Sdavemq 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3583*4732Sdavemq 	j = k = l = 0;
3584*4732Sdavemq 	total_port_fd = total_phy_fd = 0;
3585*4732Sdavemq 	/*
3586*4732Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
3587*4732Sdavemq 	 * for on chip serdes usages.
3588*4732Sdavemq 	 */
3589*4732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
3590*4732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3591*4732Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
3592*4732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3593*4732Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
3594*4732Sdavemq 		pma_pmd_dev_id = val1;
3595*4732Sdavemq 		pma_pmd_dev_id = (pma_pmd_dev_id << 16);
3596*4732Sdavemq 		pma_pmd_dev_id |= val2;
3597*4732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
3598*4732Sdavemq 		    "devid[0x%llx]", i, pma_pmd_dev_id));
3599*4732Sdavemq 
3600*4732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
3601*4732Sdavemq 			pma_pmd_dev_fd[i] = 1;
3602*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3603*4732Sdavemq 			    "PMA/PMD dev found", i));
3604*4732Sdavemq 			if (j < 4) {
3605*4732Sdavemq 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id;
3606*4732Sdavemq 				j++;
3607*4732Sdavemq 			}
3608*4732Sdavemq 		} else {
3609*4732Sdavemq 			pma_pmd_dev_fd[i] = 0;
3610*4732Sdavemq 		}
3611*4732Sdavemq 
3612*4732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3613*4732Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
3614*4732Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3615*4732Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
3616*4732Sdavemq 		pcs_dev_id = val1;
3617*4732Sdavemq 		pcs_dev_id = (pcs_dev_id << 16);
3618*4732Sdavemq 		pcs_dev_id |= val2;
3619*4732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3620*4732Sdavemq 		    "devid[0x%llx]", i, pcs_dev_id));
3621*4732Sdavemq 
3622*4732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
3623*4732Sdavemq 			pcs_dev_fd[i] = 1;
3624*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3625*4732Sdavemq 			    "dev found", i));
3626*4732Sdavemq 			if (k < 4) {
3627*4732Sdavemq 				port_pcs_dev_id[k] = pcs_dev_id;
3628*4732Sdavemq 				k++;
3629*4732Sdavemq 			}
3630*4732Sdavemq 		} else {
3631*4732Sdavemq 			pcs_dev_fd[i] = 0;
3632*4732Sdavemq 		}
3633*4732Sdavemq 
3634*4732Sdavemq 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
3635*4732Sdavemq 			port_fd[i] = 1;
3636*4732Sdavemq 		else
3637*4732Sdavemq 			port_fd[i] = 0;
3638*4732Sdavemq 		total_port_fd += port_fd[i];
3639*4732Sdavemq 
3640*4732Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
3641*4732Sdavemq 		    NXGE_PHY_ID_REG_1, &val1);
3642*4732Sdavemq 		if (npi_status != NPI_SUCCESS) {
3643*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3644*4732Sdavemq 			    "clause 22 read to reg 2 failed!!!"));
3645*4732Sdavemq 			goto error_exit;
3646*4732Sdavemq 		}
3647*4732Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
3648*4732Sdavemq 		    NXGE_PHY_ID_REG_2, &val2);
3649*4732Sdavemq 		if (npi_status != 0) {
3650*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3651*4732Sdavemq 			    "clause 22 read to reg 3 failed!!!"));
3652*4732Sdavemq 			goto error_exit;
3653*4732Sdavemq 		}
3654*4732Sdavemq 		phy_id = val1;
3655*4732Sdavemq 		phy_id = (phy_id << 16);
3656*4732Sdavemq 		phy_id |= val2;
3657*4732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3658*4732Sdavemq 		    "[0x%llx]", i, phy_id));
3659*4732Sdavemq 
3660*4732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
3661*4732Sdavemq 			phy_fd[i] = 1;
3662*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3663*4732Sdavemq 			    "found", i));
3664*4732Sdavemq 			if (l < 4) {
3665*4732Sdavemq 				port_phy_id[l] = phy_id;
3666*4732Sdavemq 				l++;
3667*4732Sdavemq 			}
3668*4732Sdavemq 		} else {
3669*4732Sdavemq 			phy_fd[i] = 0;
3670*4732Sdavemq 		}
3671*4732Sdavemq 		total_phy_fd += phy_fd[i];
3672*4732Sdavemq 	}
3673*4732Sdavemq 
3674*4732Sdavemq 	switch (total_port_fd) {
3675*4732Sdavemq 	case 2:
3676*4732Sdavemq 		switch (total_phy_fd) {
3677*4732Sdavemq 		case 2:
3678*4732Sdavemq 			/* 2 10G, 2 1G */
3679*4732Sdavemq 			if (((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3680*4732Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3681*4732Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3682*4732Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) &&
3683*4732Sdavemq 			    (port_phy_id[0] == PHY_1G_COPPER &&
3684*4732Sdavemq 			    port_phy_id[1] == PHY_1G_COPPER)) {
3685*4732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3686*4732Sdavemq 			} else {
3687*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3688*4732Sdavemq 				    "Unsupported neptune type 1"));
3689*4732Sdavemq 				goto error_exit;
3690*4732Sdavemq 			}
3691*4732Sdavemq 			break;
3692*4732Sdavemq 		case 1:
3693*4732Sdavemq 			/* TODO - 2 10G, 1 1G */
3694*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3695*4732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
3696*4732Sdavemq 			goto error_exit;
3697*4732Sdavemq 		case 0:
3698*4732Sdavemq 			/* 2 10G */
3699*4732Sdavemq 			if ((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3700*4732Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3701*4732Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3702*4732Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) {
3703*4732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF;
3704*4732Sdavemq 			} else {
3705*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3706*4732Sdavemq 				    "Unsupported neptune type 2"));
3707*4732Sdavemq 				goto error_exit;
3708*4732Sdavemq 			}
3709*4732Sdavemq 			break;
3710*4732Sdavemq 		case 4:
3711*4732Sdavemq 			/* Maramba with 2 XAUI */
3712*4732Sdavemq 			if (((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3713*4732Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3714*4732Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3715*4732Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) &&
3716*4732Sdavemq 			    (port_phy_id[0] == PHY_1G_COPPER &&
3717*4732Sdavemq 			    port_phy_id[1] == PHY_1G_COPPER &&
3718*4732Sdavemq 			    port_phy_id[2] == PHY_1G_COPPER &&
3719*4732Sdavemq 			    port_phy_id[3] == PHY_1G_COPPER)) {
3720*4732Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3721*4732Sdavemq 
3722*4732Sdavemq 				/*
3723*4732Sdavemq 				 * Check the first phy port address against
3724*4732Sdavemq 				 * the known phy start addresses to determine
3725*4732Sdavemq 				 * the platform type.
3726*4732Sdavemq 				 */
3727*4732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3728*4732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3729*4732Sdavemq 					if (phy_fd[i] == 1)
3730*4732Sdavemq 						break;
3731*4732Sdavemq 				}
3732*4732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3733*4732Sdavemq 					hw_p->platform_type =
3734*4732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
3735*4732Sdavemq 				} else if (i ==
3736*4732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3737*4732Sdavemq 					hw_p->platform_type =
3738*4732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3739*4732Sdavemq 				} else {
3740*4732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3741*4732Sdavemq 					    "Unknown port %d...Cannot "
3742*4732Sdavemq 					    "determine platform type", i));
3743*4732Sdavemq 				}
3744*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3745*4732Sdavemq 				    "Maramba with 2 XAUI"));
3746*4732Sdavemq 			} else {
3747*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3748*4732Sdavemq 				    "Unsupported neptune type 3"));
3749*4732Sdavemq 				goto error_exit;
3750*4732Sdavemq 			}
3751*4732Sdavemq 			break;
3752*4732Sdavemq 		default:
3753*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3754*4732Sdavemq 			    "Unsupported neptune type 5"));
3755*4732Sdavemq 			goto error_exit;
3756*4732Sdavemq 		}
3757*4732Sdavemq 	case 1:
3758*4732Sdavemq 		switch (total_phy_fd) {
3759*4732Sdavemq 		case 3:
3760*4732Sdavemq 			if (((port_pcs_dev_id[0] & PHY_ID_MASK) ==
3761*4732Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK)) ||
3762*4732Sdavemq 			    ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) ==
3763*4732Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK))) {
3764*4732Sdavemq 				/* The 10G port is BCM8704 */
3765*4732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3766*4732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3767*4732Sdavemq 					if (port_fd[i] == 1) {
3768*4732Sdavemq 						prt_id = i;
3769*4732Sdavemq 						break;
3770*4732Sdavemq 					}
3771*4732Sdavemq 				}
3772*4732Sdavemq 
3773*4732Sdavemq 				if (nxgep->niu_type == N2_NIU)
3774*4732Sdavemq 					prt_id %= BCM8704_N2_PORT_ADDR_BASE;
3775*4732Sdavemq 				else
3776*4732Sdavemq 					prt_id %=
3777*4732Sdavemq 					    BCM8704_NEPTUNE_PORT_ADDR_BASE;
3778*4732Sdavemq 
3779*4732Sdavemq 				if (prt_id == 0) {
3780*4732Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3781*4732Sdavemq 				} else if (prt_id == 1) {
3782*4732Sdavemq 					hw_p->niu_type =
3783*4732Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3784*4732Sdavemq 				} else {
3785*4732Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3786*4732Sdavemq 					    "Unsupported neptune type 6"));
3787*4732Sdavemq 					goto error_exit;
3788*4732Sdavemq 				}
3789*4732Sdavemq 			} else {
3790*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3791*4732Sdavemq 				    "Unsupported neptune type 7"));
3792*4732Sdavemq 				goto error_exit;
3793*4732Sdavemq 			}
3794*4732Sdavemq 			break;
3795*4732Sdavemq 		case 2:
3796*4732Sdavemq 			/*
3797*4732Sdavemq 			 * TODO 2 1G, 1 10G mode.
3798*4732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
3799*4732Sdavemq 			 * 1_10G_2_1G
3800*4732Sdavemq 			 */
3801*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3802*4732Sdavemq 			    "Unsupported neptune type 8"));
3803*4732Sdavemq 			goto error_exit;
3804*4732Sdavemq 		case 1:
3805*4732Sdavemq 			/*
3806*4732Sdavemq 			 * TODO 1 1G, 1 10G mode.
3807*4732Sdavemq 			 * Differentiate between 1_1G_1_10G and
3808*4732Sdavemq 			 * 1_10G_1_1G
3809*4732Sdavemq 			 */
3810*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3811*4732Sdavemq 			    "Unsupported neptune type 9"));
3812*4732Sdavemq 			goto error_exit;
3813*4732Sdavemq 		case 0:
3814*4732Sdavemq 			/* TODO 1 10G mode */
3815*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3816*4732Sdavemq 			    "Unsupported neptune type 10"));
3817*4732Sdavemq 			goto error_exit;
3818*4732Sdavemq 		case 4:
3819*4732Sdavemq 			/* Maramba with 1 XAUI */
3820*4732Sdavemq 			if (((port_pcs_dev_id[0] & PHY_ID_MASK) ==
3821*4732Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK)) ||
3822*4732Sdavemq 			    ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) ==
3823*4732Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK))) {
3824*4732Sdavemq 				/* The 10G port is BCM8704 */
3825*4732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3826*4732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3827*4732Sdavemq 					if (port_fd[i] == 1) {
3828*4732Sdavemq 						prt_id = i;
3829*4732Sdavemq 						break;
3830*4732Sdavemq 					}
3831*4732Sdavemq 				}
3832*4732Sdavemq 
3833*4732Sdavemq 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
3834*4732Sdavemq 				if (prt_id == 0) {
3835*4732Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3836*4732Sdavemq 				} else if (prt_id == 1) {
3837*4732Sdavemq 					hw_p->niu_type =
3838*4732Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3839*4732Sdavemq 				} else {
3840*4732Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3841*4732Sdavemq 					    "Unsupported neptune type 11"));
3842*4732Sdavemq 					goto error_exit;
3843*4732Sdavemq 				}
3844*4732Sdavemq 
3845*4732Sdavemq 				/*
3846*4732Sdavemq 				 * Check the first phy port address against
3847*4732Sdavemq 				 * the known phy start addresses to determine
3848*4732Sdavemq 				 * the platform type.
3849*4732Sdavemq 				 */
3850*4732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3851*4732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3852*4732Sdavemq 					if (phy_fd[i] == 1)
3853*4732Sdavemq 						break;
3854*4732Sdavemq 				}
3855*4732Sdavemq 
3856*4732Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3857*4732Sdavemq 					hw_p->platform_type =
3858*4732Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
3859*4732Sdavemq 				} else if (i ==
3860*4732Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3861*4732Sdavemq 					hw_p->platform_type =
3862*4732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3863*4732Sdavemq 				} else {
3864*4732Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3865*4732Sdavemq 					    "Unknown port %d...Cannot "
3866*4732Sdavemq 					    "determine platform type", i));
3867*4732Sdavemq 				}
3868*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3869*4732Sdavemq 				    "Maramba with 1 XAUI"));
3870*4732Sdavemq 			} else {
3871*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3872*4732Sdavemq 				    "Unsupported neptune type 12"));
3873*4732Sdavemq 				goto error_exit;
3874*4732Sdavemq 			}
3875*4732Sdavemq 			break;
3876*4732Sdavemq 		default:
3877*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3878*4732Sdavemq 			    "Unsupported neptune type 13"));
3879*4732Sdavemq 			goto error_exit;
3880*4732Sdavemq 		}
3881*4732Sdavemq 		break;
3882*4732Sdavemq 	case 0:
3883*4732Sdavemq 		switch (total_phy_fd) {
3884*4732Sdavemq 		case 4:
3885*4732Sdavemq 			if (((port_phy_id[0] & PHY_ID_MASK) ==
3886*4732Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3887*4732Sdavemq 			    ((port_phy_id[1] & PHY_ID_MASK) ==
3888*4732Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3889*4732Sdavemq 			    ((port_phy_id[2] & PHY_ID_MASK) ==
3890*4732Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3891*4732Sdavemq 			    ((port_phy_id[3] & PHY_ID_MASK) ==
3892*4732Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK))) {
3893*4732Sdavemq 
3894*4732Sdavemq 				hw_p->niu_type = NEPTUNE_4_1GC;
3895*4732Sdavemq 
3896*4732Sdavemq 				/*
3897*4732Sdavemq 				 * Check the first phy port address against
3898*4732Sdavemq 				 * the known phy start addresses to determine
3899*4732Sdavemq 				 * the platform type.
3900*4732Sdavemq 				 */
3901*4732Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3902*4732Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3903*4732Sdavemq 					if (phy_fd[i] == 1)
3904*4732Sdavemq 						break;
3905*4732Sdavemq 				}
3906*4732Sdavemq 
3907*4732Sdavemq 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3908*4732Sdavemq 					hw_p->platform_type =
3909*4732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3910*4732Sdavemq 				}
3911*4732Sdavemq 			} else {
3912*4732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3913*4732Sdavemq 				    "Unsupported neptune type 14"));
3914*4732Sdavemq 				goto error_exit;
3915*4732Sdavemq 			}
3916*4732Sdavemq 			break;
3917*4732Sdavemq 		case 3:
3918*4732Sdavemq 			/* TODO 3 1G mode */
3919*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3920*4732Sdavemq 			    "Unsupported neptune type 15"));
3921*4732Sdavemq 			goto error_exit;
3922*4732Sdavemq 		case 2:
3923*4732Sdavemq 			/* TODO 2 1G mode */
3924*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3925*4732Sdavemq 			    "Unsupported neptune type 16"));
3926*4732Sdavemq 			goto error_exit;
3927*4732Sdavemq 		case 1:
3928*4732Sdavemq 			/* TODO 1 1G mode */
3929*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3930*4732Sdavemq 			    "Unsupported neptune type 17"));
3931*4732Sdavemq 			goto error_exit;
3932*4732Sdavemq 		default:
3933*4732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3934*4732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
3935*4732Sdavemq 			    total_phy_fd));
3936*4732Sdavemq 			goto error_exit;
3937*4732Sdavemq 		}
3938*4732Sdavemq 		break;
3939*4732Sdavemq 	default:
3940*4732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3941*4732Sdavemq 		    "Unsupported neptune type 19"));
3942*4732Sdavemq 		goto error_exit;
3943*4732Sdavemq 	}
3944*4732Sdavemq 
3945*4732Sdavemq scan_exit:
3946*4732Sdavemq 
3947*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
3948*4732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
3949*4732Sdavemq 	return (status);
3950*4732Sdavemq 
3951*4732Sdavemq error_exit:
3952*4732Sdavemq 	return (NXGE_ERROR);
3953*4732Sdavemq }
3954*4732Sdavemq 
39554185Sspeer boolean_t
39564185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
39574185Sspeer {
39584185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
39594185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
39604185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
39614185Sspeer 		return (B_FALSE);
39624185Sspeer 	else
39634185Sspeer 		return (B_TRUE);
39644185Sspeer }
3965*4732Sdavemq 
3966*4732Sdavemq static void
3967*4732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
3968*4732Sdavemq 
3969*4732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
3970*4732Sdavemq 	uint8_t xcvr_portn;
3971*4732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3972*4732Sdavemq 
3973*4732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
3974*4732Sdavemq 
3975*4732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
3976*4732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
3977*4732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
3978*4732Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
3979*4732Sdavemq 	}
3980*4732Sdavemq 	/*
3981*4732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
3982*4732Sdavemq 	 * swapped with ethernet port number. This is
3983*4732Sdavemq 	 * designed for better signal integrity in routing.
3984*4732Sdavemq 	 */
3985*4732Sdavemq 	switch (portn) {
3986*4732Sdavemq 	case 0:
3987*4732Sdavemq 		xcvr_portn += 3;
3988*4732Sdavemq 		break;
3989*4732Sdavemq 	case 1:
3990*4732Sdavemq 		xcvr_portn += 2;
3991*4732Sdavemq 		break;
3992*4732Sdavemq 	case 2:
3993*4732Sdavemq 		xcvr_portn += 1;
3994*4732Sdavemq 		break;
3995*4732Sdavemq 	case 3:
3996*4732Sdavemq 	default:
3997*4732Sdavemq 		break;
3998*4732Sdavemq 	}
3999*4732Sdavemq 
4000*4732Sdavemq 	MUTEX_ENTER(&nxge_mii_lock);
4001*4732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4002*4732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
4003*4732Sdavemq 	if (rs != NPI_SUCCESS) {
4004*4732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4005*4732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4006*4732Sdavemq 		    "returned error 0x[%x]", rs));
4007*4732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
4008*4732Sdavemq 		return;
4009*4732Sdavemq 	}
4010*4732Sdavemq 
4011*4732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4012*4732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
4013*4732Sdavemq 	if (rs != NPI_SUCCESS) {
4014*4732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4015*4732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4016*4732Sdavemq 		    "returned error 0x[%x]", rs));
4017*4732Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
4018*4732Sdavemq 		return;
4019*4732Sdavemq 	}
4020*4732Sdavemq 
4021*4732Sdavemq 	MUTEX_EXIT(&nxge_mii_lock);
4022*4732Sdavemq }
4023