xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 59ac0c16)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
22a3c5bd6dSspeer  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish #include <sys/nxge/nxge_impl.h>
2944961713Sgirish #include <sys/nxge/nxge_mac.h>
3044961713Sgirish 
3198ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3298ecde52Stm #define	LM_WAIT_MULTIPLIER	8
3398ecde52Stm 
3444961713Sgirish extern uint32_t nxge_no_link_notify;
35*59ac0c16Sdavemq extern boolean_t nxge_no_msg;
3644961713Sgirish extern uint32_t nxge_lb_dbg;
3744961713Sgirish extern nxge_os_mutex_t	nxge_mdio_lock;
3844961713Sgirish extern nxge_os_mutex_t	nxge_mii_lock;
3944961713Sgirish extern boolean_t nxge_jumbo_enable;
4044961713Sgirish 
4198ecde52Stm typedef enum {
4298ecde52Stm 	CHECK_LINK_RESCHEDULE,
4398ecde52Stm 	CHECK_LINK_STOP
4498ecde52Stm } check_link_state_t;
4598ecde52Stm 
4698ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
4798ecde52Stm 
4844961713Sgirish /*
4944961713Sgirish  * Ethernet broadcast address definition.
5044961713Sgirish  */
5144961713Sgirish static ether_addr_st etherbroadcastaddr =
5244961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
53*59ac0c16Sdavemq /*
54*59ac0c16Sdavemq  * Ethernet zero address definition.
55*59ac0c16Sdavemq  */
5656d930aeSspeer static ether_addr_st etherzeroaddr =
5756d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
58*59ac0c16Sdavemq /*
59*59ac0c16Sdavemq  * Supported chip types
60*59ac0c16Sdavemq  */
61*59ac0c16Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
62*59ac0c16Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
63*59ac0c16Sdavemq 
64*59ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
65*59ac0c16Sdavemq 				sizeof (uint32_t))
66*59ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
67*59ac0c16Sdavemq 				sizeof (uint32_t))
68*59ac0c16Sdavemq /*
69*59ac0c16Sdavemq  * static functions
70*59ac0c16Sdavemq  */
71*59ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
72*59ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
73*59ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
74*59ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
75*59ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
76*59ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
77*59ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
78*59ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
79*59ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
80*59ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
81*59ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
82*59ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
83*59ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
84*59ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
85*59ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
86*59ac0c16Sdavemq 
87*59ac0c16Sdavemq /*
88*59ac0c16Sdavemq  * xcvr tables for supported transceivers
89*59ac0c16Sdavemq  */
90*59ac0c16Sdavemq 
91*59ac0c16Sdavemq static nxge_xcvr_table_t nxge_n2_table = {
92*59ac0c16Sdavemq 	nxge_n2_serdes_init,
93*59ac0c16Sdavemq 	nxge_10G_xcvr_init,
94*59ac0c16Sdavemq 	nxge_10G_link_intr_stop,
95*59ac0c16Sdavemq 	nxge_10G_link_intr_start,
96*59ac0c16Sdavemq 	nxge_check_10g_link,
97*59ac0c16Sdavemq 	BCM8704_DEV_ID,
98*59ac0c16Sdavemq 	PCS_XCVR,
99*59ac0c16Sdavemq 	BCM8704_N2_PORT_ADDR_BASE
100*59ac0c16Sdavemq };
101*59ac0c16Sdavemq 
102*59ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
103*59ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
104*59ac0c16Sdavemq 	nxge_10G_xcvr_init,
105*59ac0c16Sdavemq 	nxge_10G_link_intr_stop,
106*59ac0c16Sdavemq 	nxge_10G_link_intr_start,
107*59ac0c16Sdavemq 	nxge_check_10g_link,
108*59ac0c16Sdavemq 	BCM8704_DEV_ID,
109*59ac0c16Sdavemq 	PCS_XCVR,
110*59ac0c16Sdavemq 	BCM8704_NEPTUNE_PORT_ADDR_BASE
111*59ac0c16Sdavemq };
112*59ac0c16Sdavemq 
113*59ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
114*59ac0c16Sdavemq 	NULL,
115*59ac0c16Sdavemq 	nxge_1G_xcvr_init,
116*59ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
117*59ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
118*59ac0c16Sdavemq 	nxge_check_mii_link,
119*59ac0c16Sdavemq 	BCM5464R_PHY_ID,
120*59ac0c16Sdavemq 	INT_MII_XCVR,
121*59ac0c16Sdavemq 	BCM5464_NEPTUNE_PORT_ADDR_BASE
122*59ac0c16Sdavemq };
123*59ac0c16Sdavemq 
124*59ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
125*59ac0c16Sdavemq 	nxge_1G_serdes_init,
126*59ac0c16Sdavemq 	nxge_1G_xcvr_init,
127*59ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
128*59ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
129*59ac0c16Sdavemq 	nxge_check_mii_link,
130*59ac0c16Sdavemq 	0,
131*59ac0c16Sdavemq 	PCS_XCVR,
132*59ac0c16Sdavemq 	0
133*59ac0c16Sdavemq };
134*59ac0c16Sdavemq 
135*59ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
136*59ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
137*59ac0c16Sdavemq 	NULL,
138*59ac0c16Sdavemq 	NULL,
139*59ac0c16Sdavemq 	NULL,
140*59ac0c16Sdavemq 	0,
141*59ac0c16Sdavemq 	PCS_XCVR,
142*59ac0c16Sdavemq 	0
143*59ac0c16Sdavemq };
14444961713Sgirish 
14544961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t);
14644961713Sgirish 
147*59ac0c16Sdavemq /* Set up the PHY specific values. */
148*59ac0c16Sdavemq 
149*59ac0c16Sdavemq nxge_status_t
150*59ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
151*59ac0c16Sdavemq {
152*59ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
153*59ac0c16Sdavemq 	uint32_t	port_type;
154*59ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
155*59ac0c16Sdavemq 
156*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
157*59ac0c16Sdavemq 	    portn));
158*59ac0c16Sdavemq 
159*59ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
160*59ac0c16Sdavemq 		nxgep->mac.portmode = PORT_10G_FIBER;
161*59ac0c16Sdavemq 		nxgep->xcvr = nxge_n2_table;
162*59ac0c16Sdavemq 		nxgep->xcvr.xcvr_addr += portn;
163*59ac0c16Sdavemq 	} else {
164*59ac0c16Sdavemq 		port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn);
165*59ac0c16Sdavemq 		port_type = port_type & (NXGE_PORT_TYPE_MASK);
166*59ac0c16Sdavemq 		switch (port_type) {
167*59ac0c16Sdavemq 		case NXGE_PORT_1G_COPPER:
168*59ac0c16Sdavemq 			nxgep->mac.portmode = PORT_1G_COPPER;
169*59ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
170*59ac0c16Sdavemq 			if (nxgep->nxge_hw_p->platform_type ==
171*59ac0c16Sdavemq 			    P_NEPTUNE_MARAMBA_P1) {
172*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr =
173*59ac0c16Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
174*59ac0c16Sdavemq 			} else if (nxgep->nxge_hw_p->platform_type ==
175*59ac0c16Sdavemq 			    P_NEPTUNE_MARAMBA_P0) {
176*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr =
177*59ac0c16Sdavemq 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
178*59ac0c16Sdavemq 			}
179*59ac0c16Sdavemq 			/*
180*59ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
181*59ac0c16Sdavemq 			 * swapped with ethernet port number. This is
182*59ac0c16Sdavemq 			 * designed for better signal integrity in routing.
183*59ac0c16Sdavemq 			 */
184*59ac0c16Sdavemq 			switch (portn) {
185*59ac0c16Sdavemq 			case 0:
186*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr += 3;
187*59ac0c16Sdavemq 				break;
188*59ac0c16Sdavemq 			case 1:
189*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr += 2;
190*59ac0c16Sdavemq 				break;
191*59ac0c16Sdavemq 			case 2:
192*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr += 1;
193*59ac0c16Sdavemq 				break;
194*59ac0c16Sdavemq 			case 3:
195*59ac0c16Sdavemq 				break;
196*59ac0c16Sdavemq 			default:
197*59ac0c16Sdavemq 				return (NXGE_ERROR);
198*59ac0c16Sdavemq 			}
199*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
200*59ac0c16Sdavemq 			break;
201*59ac0c16Sdavemq 		case NXGE_PORT_10G_COPPER:
202*59ac0c16Sdavemq 			nxgep->mac.portmode = PORT_10G_COPPER;
203*59ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
204*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
205*59ac0c16Sdavemq 			break;
206*59ac0c16Sdavemq 		case NXGE_PORT_1G_FIBRE:
207*59ac0c16Sdavemq 			nxgep->mac.portmode = PORT_1G_FIBER;
208*59ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
209*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr"));
210*59ac0c16Sdavemq 			break;
211*59ac0c16Sdavemq 		case NXGE_PORT_10G_FIBRE:
212*59ac0c16Sdavemq 			nxgep->mac.portmode = PORT_10G_FIBER;
213*59ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
214*59ac0c16Sdavemq 			if ((nxgep->nxge_hw_p->platform_type ==
215*59ac0c16Sdavemq 			    P_NEPTUNE_MARAMBA_P0) ||
216*59ac0c16Sdavemq 			    (nxgep->nxge_hw_p->platform_type ==
217*59ac0c16Sdavemq 			    P_NEPTUNE_MARAMBA_P1)) {
218*59ac0c16Sdavemq 				nxgep->xcvr.xcvr_addr =
219*59ac0c16Sdavemq 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
220*59ac0c16Sdavemq 				/*
221*59ac0c16Sdavemq 				 * Switch off LED for corresponding copper
222*59ac0c16Sdavemq 				 * port
223*59ac0c16Sdavemq 				 */
224*59ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
225*59ac0c16Sdavemq 			}
226*59ac0c16Sdavemq 			nxgep->xcvr.xcvr_addr += portn;
227*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr"));
228*59ac0c16Sdavemq 			break;
229*59ac0c16Sdavemq 		default:
230*59ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
231*59ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
232*59ac0c16Sdavemq 			return (NXGE_ERROR);
233*59ac0c16Sdavemq 		}
234*59ac0c16Sdavemq 	}
235*59ac0c16Sdavemq 
236*59ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
237*59ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
238*59ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id;
239*59ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
240*59ac0c16Sdavemq 
241*59ac0c16Sdavemq 	return (status);
242*59ac0c16Sdavemq }
243*59ac0c16Sdavemq 
24444961713Sgirish /* Initialize the entire MAC and physical layer */
24544961713Sgirish 
24644961713Sgirish nxge_status_t
24744961713Sgirish nxge_mac_init(p_nxge_t nxgep)
24844961713Sgirish {
24944961713Sgirish 	uint8_t			portn;
25044961713Sgirish 	nxge_status_t		status = NXGE_OK;
25144961713Sgirish 
25244961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
25344961713Sgirish 
25444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
25544961713Sgirish 
25644961713Sgirish 	nxgep->mac.portnum = portn;
25744961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
25844961713Sgirish 
25944961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
26044961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
26144961713Sgirish 
26244961713Sgirish 	/* Initialize XIF to configure a network mode */
26344961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
26444961713Sgirish 		goto fail;
26544961713Sgirish 	}
26644961713Sgirish 
26744961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
26844961713Sgirish 		goto fail;
26944961713Sgirish 	}
27044961713Sgirish 
27144961713Sgirish 	/* Initialize TX and RX MACs */
27244961713Sgirish 	/*
27344961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
27444961713Sgirish 	 */
27544961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
27644961713Sgirish 		goto fail;
27744961713Sgirish 
27844961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
27944961713Sgirish 		goto fail;
28044961713Sgirish 
28144961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
28244961713Sgirish 		goto fail;
28344961713Sgirish 
28444961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
28544961713Sgirish 		goto fail;
28644961713Sgirish 
28744961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
28844961713Sgirish 		goto fail;
28944961713Sgirish 
29044961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
29144961713Sgirish 		goto fail;
29244961713Sgirish 
29344961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
29444961713Sgirish 
29544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
29644961713Sgirish 
29744961713Sgirish 	return (NXGE_OK);
29844961713Sgirish fail:
29944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30044961713Sgirish 			"nxge_mac_init: failed to initialize MAC port<%d>",
30144961713Sgirish 			portn));
30244961713Sgirish 	return (status);
30344961713Sgirish }
30444961713Sgirish 
30544961713Sgirish /* Initialize the Ethernet Link */
30644961713Sgirish 
30744961713Sgirish nxge_status_t
30844961713Sgirish nxge_link_init(p_nxge_t nxgep)
30944961713Sgirish {
31044961713Sgirish 	nxge_status_t		status = NXGE_OK;
31144961713Sgirish #ifdef	NXGE_DEBUG
31244961713Sgirish 	uint8_t			portn;
31344961713Sgirish 
31444961713Sgirish 	portn = nxgep->mac.portnum;
31544961713Sgirish 
31644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
31744961713Sgirish #endif
31844961713Sgirish 
31944961713Sgirish 	if (nxgep->niu_type == N2_NIU) {
32044961713Sgirish 		/* Workaround to get link up in both NIU ports */
32144961713Sgirish 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
32244961713Sgirish 			goto fail;
32344961713Sgirish 	}
32444961713Sgirish 	NXGE_DELAY(200000);
32544961713Sgirish 	/* Initialize internal serdes */
32644961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
32744961713Sgirish 		goto fail;
32844961713Sgirish 	NXGE_DELAY(200000);
32944961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
33044961713Sgirish 		goto fail;
33144961713Sgirish 
33244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
33344961713Sgirish 
33444961713Sgirish 	return (NXGE_OK);
33544961713Sgirish 
33644961713Sgirish fail:
33744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
33844961713Sgirish 		"nxge_link_init: ",
33944961713Sgirish 		"failed to initialize Ethernet link on port<%d>",
34044961713Sgirish 		portn));
34144961713Sgirish 
34244961713Sgirish 	return (status);
34344961713Sgirish }
34444961713Sgirish 
34544961713Sgirish 
34644961713Sgirish /* Initialize the XIF sub-block within the MAC */
34744961713Sgirish 
34844961713Sgirish nxge_status_t
34944961713Sgirish nxge_xif_init(p_nxge_t nxgep)
35044961713Sgirish {
35144961713Sgirish 	uint32_t		xif_cfg = 0;
35244961713Sgirish 	npi_attr_t		ap;
35344961713Sgirish 	uint8_t			portn;
35444961713Sgirish 	nxge_port_t		portt;
35544961713Sgirish 	nxge_port_mode_t	portmode;
35644961713Sgirish 	p_nxge_stats_t		statsp;
35744961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
35844961713Sgirish 	npi_handle_t		handle;
35944961713Sgirish 
36044961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
36144961713Sgirish 
36244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
36344961713Sgirish 
36444961713Sgirish 	handle = nxgep->npi_handle;
36544961713Sgirish 	portmode = nxgep->mac.portmode;
36644961713Sgirish 	portt = nxgep->mac.porttype;
36744961713Sgirish 	statsp = nxgep->statsp;
36844961713Sgirish 
36944961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
37044961713Sgirish 
37144961713Sgirish 		/* Setup XIF Configuration for XMAC */
37244961713Sgirish 
37344961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
37444961713Sgirish 					(portmode == PORT_10G_COPPER))
37544961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
37644961713Sgirish 
37744961713Sgirish 		if (portmode == PORT_1G_COPPER) {
37844961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
37944961713Sgirish 		}
38044961713Sgirish 
38144961713Sgirish 		/* Set MAC Internal Loopback if necessary */
38244961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
38344961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
38444961713Sgirish 
38544961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
38644961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
38744961713Sgirish 
38844961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
38944961713Sgirish 
39044961713Sgirish 		if (portmode == PORT_10G_FIBER) {
39144961713Sgirish 			if (statsp->mac_stats.link_up) {
39244961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
39344961713Sgirish 			} else {
39444961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
39544961713Sgirish 			}
39644961713Sgirish 		}
39744961713Sgirish 
39844961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
39944961713Sgirish 		if (rs != NPI_SUCCESS)
40044961713Sgirish 			goto fail;
40144961713Sgirish 
40244961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
40344961713Sgirish 
40444961713Sgirish 		/* Set Port Mode */
40544961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
40644961713Sgirish 					(portmode == PORT_10G_COPPER)) {
40744961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
40844961713Sgirish 						MAC_XGMII_MODE, rs);
40944961713Sgirish 			if (rs != NPI_SUCCESS)
41044961713Sgirish 				goto fail;
41144961713Sgirish 			if (statsp->mac_stats.link_up) {
41244961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
41344961713Sgirish 					goto fail;
41444961713Sgirish 			} else {
41544961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
41644961713Sgirish 					goto fail;
41744961713Sgirish 			}
41844961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
41944961713Sgirish 						(portmode == PORT_1G_COPPER)) {
42044961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
42144961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
42244961713Sgirish 							MAC_GMII_MODE, rs);
42344961713Sgirish 			} else {
42444961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
42544961713Sgirish 							MAC_MII_MODE, rs);
42644961713Sgirish 			}
42744961713Sgirish 			if (rs != NPI_SUCCESS)
42844961713Sgirish 				goto fail;
42944961713Sgirish 		} else {
43044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43144961713Sgirish 					"nxge_xif_init: Unknown port mode (%d)"
43244961713Sgirish 					" for port<%d>", portmode, portn));
43344961713Sgirish 			goto fail;
43444961713Sgirish 		}
43544961713Sgirish 
43644961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
43744961713Sgirish 
43844961713Sgirish 		/* Setup XIF Configuration for BMAC */
43944961713Sgirish 
44044961713Sgirish 		if (portmode == PORT_1G_COPPER) {
44144961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
44244961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
44344961713Sgirish 		}
44444961713Sgirish 
44544961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
44644961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
44744961713Sgirish 
44844961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
44944961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
45044961713Sgirish 
45144961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
45244961713Sgirish 
45344961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
45444961713Sgirish 		if (rs != NPI_SUCCESS)
45544961713Sgirish 			goto fail;
45644961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
45744961713Sgirish 	}
45844961713Sgirish 
45944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
46044961713Sgirish 	return (NXGE_OK);
46144961713Sgirish fail:
46244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
46344961713Sgirish 			"nxge_xif_init: Failed to initialize XIF port<%d>",
46444961713Sgirish 			portn));
46544961713Sgirish 	return (NXGE_ERROR | rs);
46644961713Sgirish }
46744961713Sgirish 
46844961713Sgirish /* Initialize the PCS sub-block in the MAC */
46944961713Sgirish 
47044961713Sgirish nxge_status_t
47144961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
47244961713Sgirish {
47344961713Sgirish 	pcs_cfg_t		pcs_cfg;
47444961713Sgirish 	uint32_t		val;
47544961713Sgirish 	uint8_t			portn;
47644961713Sgirish 	nxge_port_mode_t	portmode;
47744961713Sgirish 	npi_handle_t		handle;
47844961713Sgirish 	p_nxge_stats_t		statsp;
47944961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
48044961713Sgirish 
48144961713Sgirish 	handle = nxgep->npi_handle;
48244961713Sgirish 	portmode = nxgep->mac.portmode;
48344961713Sgirish 	portn = nxgep->mac.portnum;
48444961713Sgirish 	statsp = nxgep->statsp;
48544961713Sgirish 
48644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
48744961713Sgirish 
48844961713Sgirish 	if (portmode == PORT_1G_FIBER) {
48944961713Sgirish 		/* Initialize port's PCS */
49044961713Sgirish 		pcs_cfg.value = 0;
49144961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
49244961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
49344961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
49444961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
49544961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
49644961713Sgirish 			goto fail;
49744961713Sgirish 
49844961713Sgirish 	} else if ((portmode == PORT_10G_FIBER) ||
49944961713Sgirish 						(portmode == PORT_10G_COPPER)) {
50044961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
50144961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
50244961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
50344961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
50444961713Sgirish 
50544961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
50644961713Sgirish 			goto fail;
50744961713Sgirish 
50844961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
50944961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
51044961713Sgirish 						XPCS_REG_CONTROL1, &val))
51144961713Sgirish 						!= NPI_SUCCESS)
51244961713Sgirish 			goto fail;
51344961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
51444961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
51544961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
51644961713Sgirish 		else
51744961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
51844961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
51944961713Sgirish 						XPCS_REG_CONTROL1, val))
52044961713Sgirish 						!= NPI_SUCCESS)
52144961713Sgirish 			goto fail;
52244961713Sgirish 
52344961713Sgirish 		/* Clear descw errors */
52444961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
52544961713Sgirish 						XPCS_REG_DESCWERR_COUNTER, 0))
52644961713Sgirish 						!= NPI_SUCCESS)
52744961713Sgirish 			goto fail;
52844961713Sgirish 		/* Clear symbol errors */
52944961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
53044961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
53144961713Sgirish 					!= NPI_SUCCESS)
53244961713Sgirish 			goto fail;
53344961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
53444961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
53544961713Sgirish 					!= NPI_SUCCESS)
53644961713Sgirish 			goto fail;
53744961713Sgirish 
53844961713Sgirish 	} else if (portmode == PORT_1G_COPPER) {
53944961713Sgirish 		if (portn < 4) {
54044961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
54144961713Sgirish 					PCS_DATAPATH_MODE_MII);
54244961713Sgirish 		}
54344961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
54444961713Sgirish 			goto fail;
54544961713Sgirish 
54644961713Sgirish 	} else {
54744961713Sgirish 		goto fail;
54844961713Sgirish 	}
54944961713Sgirish pass:
55044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
55144961713Sgirish 	return (NXGE_OK);
55244961713Sgirish fail:
55344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
55444961713Sgirish 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
55544961713Sgirish 			portn));
55644961713Sgirish 	return (NXGE_ERROR | rs);
55744961713Sgirish }
55844961713Sgirish 
55944961713Sgirish /* Initialize the Internal Serdes */
56044961713Sgirish 
56144961713Sgirish nxge_status_t
56244961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
56344961713Sgirish {
56444961713Sgirish 	p_nxge_stats_t		statsp;
56544961713Sgirish #ifdef	NXGE_DEBUG
56644961713Sgirish 	uint8_t			portn;
56744961713Sgirish #endif
56844961713Sgirish 	nxge_status_t		status = NXGE_OK;
56944961713Sgirish 
57044961713Sgirish #ifdef	NXGE_DEBUG
57144961713Sgirish 	portn = nxgep->mac.portnum;
57244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
573*59ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
57444961713Sgirish #endif
57544961713Sgirish 
576*59ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
577*59ac0c16Sdavemq 		statsp = nxgep->statsp;
578*59ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
579*59ac0c16Sdavemq 		if (status != NXGE_OK)
58044961713Sgirish 			goto fail;
581*59ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
58244961713Sgirish 	}
58344961713Sgirish 
58444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
585*59ac0c16Sdavemq 	    portn));
58644961713Sgirish 
58744961713Sgirish 	return (NXGE_OK);
58844961713Sgirish 
58944961713Sgirish fail:
59044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
591*59ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
592*59ac0c16Sdavemq 	    portn));
59344961713Sgirish 
59444961713Sgirish 	return (status);
59544961713Sgirish }
59644961713Sgirish 
59744961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
59844961713Sgirish 
599*59ac0c16Sdavemq static nxge_status_t
60044961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
60144961713Sgirish {
60244961713Sgirish 	uint8_t portn;
60344961713Sgirish 	int chan;
60444961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
60544961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
60644961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
60744961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
60844961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
60944961713Sgirish 	esr_ti_testcfg_t test_cfg;
61044961713Sgirish 	nxge_status_t status = NXGE_OK;
61144961713Sgirish 
61244961713Sgirish 	portn = nxgep->mac.portnum;
61344961713Sgirish 
61444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
61544961713Sgirish 			portn));
61644961713Sgirish 
61744961713Sgirish 	tx_cfg_l.value = 0;
61844961713Sgirish 	tx_cfg_h.value = 0;
61944961713Sgirish 	rx_cfg_l.value = 0;
62044961713Sgirish 	rx_cfg_h.value = 0;
62144961713Sgirish 	pll_cfg_l.value = 0;
62244961713Sgirish 	test_cfg.value = 0;
62344961713Sgirish 
62444961713Sgirish 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
62544961713Sgirish 		/* 0x0E01 */
62644961713Sgirish 		tx_cfg_l.bits.entx = 1;
62744961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
62844961713Sgirish 
62944961713Sgirish 		/* 0x9101 */
63044961713Sgirish 		rx_cfg_l.bits.enrx = 1;
63144961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
63244961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
63344961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
63444961713Sgirish 
63544961713Sgirish 		/* 0x0008 */
63644961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
63744961713Sgirish 
63844961713Sgirish 		/* Set loopback mode if necessary */
63944961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
64044961713Sgirish 			tx_cfg_l.bits.entest = 1;
64144961713Sgirish 			rx_cfg_l.bits.entest = 1;
64244961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
64344961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
64444961713Sgirish 				ESR_N2_DEV_ADDR,
64544961713Sgirish 				ESR_N2_TEST_CFG_REG, test_cfg.value))
64644961713Sgirish 				!= NXGE_OK)
64744961713Sgirish 			goto fail;
64844961713Sgirish 		}
64944961713Sgirish 
65044961713Sgirish 		/* Use default PLL value */
65144961713Sgirish 
65244961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
65344961713Sgirish 
65444961713Sgirish 		/* 0x0E21 */
65544961713Sgirish 		tx_cfg_l.bits.entx = 1;
65644961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
65744961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
65844961713Sgirish 
65944961713Sgirish 		/* 0x9121 */
66044961713Sgirish 		rx_cfg_l.bits.enrx = 1;
66144961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
66244961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
66344961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
66444961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
66544961713Sgirish 
66644961713Sgirish 		/* 0x8 */
66744961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
66844961713Sgirish 
66944961713Sgirish 		/* MPY = 0x100 */
67044961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
67144961713Sgirish 
67244961713Sgirish 		/* Set PLL */
67344961713Sgirish 		pll_cfg_l.bits.enpll = 1;
67444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
67544961713Sgirish 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
67644961713Sgirish 				!= NXGE_OK)
67744961713Sgirish 			goto fail;
67844961713Sgirish 	} else {
67944961713Sgirish 		goto fail;
68044961713Sgirish 	}
68144961713Sgirish 
68244961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
68344961713Sgirish 
68444961713Sgirish 	NXGE_DELAY(20);
68544961713Sgirish 
68644961713Sgirish 	/* init TX channels */
68744961713Sgirish 	for (chan = 0; chan < 4; chan++) {
68844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
68944961713Sgirish 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
69044961713Sgirish 				!= NXGE_OK)
69144961713Sgirish 			goto fail;
69244961713Sgirish 
69344961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
69444961713Sgirish 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
69544961713Sgirish 				!= NXGE_OK)
69644961713Sgirish 			goto fail;
69744961713Sgirish 	}
69844961713Sgirish 
69944961713Sgirish 	/* init RX channels */
70044961713Sgirish 	for (chan = 0; chan < 4; chan++) {
70144961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
70244961713Sgirish 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
70344961713Sgirish 				!= NXGE_OK)
70444961713Sgirish 			goto fail;
70544961713Sgirish 
70644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
70744961713Sgirish 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
70844961713Sgirish 				!= NXGE_OK)
70944961713Sgirish 			goto fail;
71044961713Sgirish 	}
71144961713Sgirish 
71244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
71344961713Sgirish 			portn));
71444961713Sgirish 
71544961713Sgirish 	return (NXGE_OK);
71644961713Sgirish fail:
71744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71844961713Sgirish 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
71944961713Sgirish 				portn));
72044961713Sgirish 
72144961713Sgirish 	return (status);
72244961713Sgirish }
72344961713Sgirish 
724*59ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
72544961713Sgirish 
726*59ac0c16Sdavemq static nxge_status_t
727*59ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
72844961713Sgirish {
72944961713Sgirish 	npi_handle_t		handle;
73044961713Sgirish 	uint8_t			portn;
73144961713Sgirish 	int			chan;
73244961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
73344961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
73444961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
73544961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
73644961713Sgirish 	uint64_t		val;
73744961713Sgirish 	uint16_t		val16l;
73844961713Sgirish 	uint16_t		val16h;
73944961713Sgirish 	nxge_status_t		status = NXGE_OK;
74044961713Sgirish 
74144961713Sgirish 	portn = nxgep->mac.portnum;
74244961713Sgirish 
74344961713Sgirish 	if ((portn != 0) && (portn != 1))
74444961713Sgirish 		return (NXGE_OK);
74544961713Sgirish 
746*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
747*59ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
74844961713Sgirish 
74944961713Sgirish 	handle = nxgep->npi_handle;
750*59ac0c16Sdavemq 	switch (portn) {
751*59ac0c16Sdavemq 	case 0:
752*59ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
753*59ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
754*59ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
755*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
756*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
757*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
758*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
759*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
760*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
761*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
762*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
763*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
764*59ac0c16Sdavemq 
765*59ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
766*59ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
767*59ac0c16Sdavemq 			ESR_REG_WR(handle,
768*59ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
769*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
770*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
771*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
772*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
773*59ac0c16Sdavemq 		} else {
774*59ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
77544961713Sgirish 		}
776*59ac0c16Sdavemq 		break;
777*59ac0c16Sdavemq 	case 1:
778*59ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
779*59ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
780*59ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
781*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
782*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
783*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
784*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
785*59ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
786*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
787*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
788*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
789*59ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
790*59ac0c16Sdavemq 
791*59ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
792*59ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
793*59ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
794*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
795*59ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
796*59ac0c16Sdavemq 		} else {
797*59ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
79844961713Sgirish 		}
799*59ac0c16Sdavemq 		break;
800*59ac0c16Sdavemq 	default:
801*59ac0c16Sdavemq 		/* Nothing to do here */
802*59ac0c16Sdavemq 		goto done;
803*59ac0c16Sdavemq 	}
80444961713Sgirish 
805*59ac0c16Sdavemq 	/* init TX RX channels */
806*59ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
807*59ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
808*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
809*59ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
81044961713Sgirish 			goto fail;
811*59ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
812*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
813*59ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
81444961713Sgirish 			goto fail;
815*59ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
816*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
817*59ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
818*59ac0c16Sdavemq 			goto fail;
819*59ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
820*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
821*59ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
822*59ac0c16Sdavemq 			goto fail;
823*59ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
824*59ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
825*59ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
826*59ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
827*59ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
828*59ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
829*59ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
83044961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
831*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
832*59ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
83344961713Sgirish 			goto fail;
83444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
835*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
836*59ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
83744961713Sgirish 			goto fail;
838*59ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
839*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
840*59ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
84144961713Sgirish 			goto fail;
842*59ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
843*59ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
844*59ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
84544961713Sgirish 			goto fail;
84644961713Sgirish 		}
84744961713Sgirish 
848*59ac0c16Sdavemq 	/* Apply Tx core reset */
849*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
850*59ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
851*59ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
852*59ac0c16Sdavemq 		goto fail;
853*59ac0c16Sdavemq 
854*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
855*59ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
856*59ac0c16Sdavemq 	    NXGE_OK)
857*59ac0c16Sdavemq 		goto fail;
858*59ac0c16Sdavemq 
859*59ac0c16Sdavemq 	NXGE_DELAY(200);
860*59ac0c16Sdavemq 
861*59ac0c16Sdavemq 	/* Apply Rx core reset */
862*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
863*59ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
864*59ac0c16Sdavemq 	    NXGE_OK)
865*59ac0c16Sdavemq 		goto fail;
866*59ac0c16Sdavemq 
867*59ac0c16Sdavemq 	NXGE_DELAY(200);
868*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
869*59ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
870*59ac0c16Sdavemq 		goto fail;
871*59ac0c16Sdavemq 
872*59ac0c16Sdavemq 	NXGE_DELAY(200);
873*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
874*59ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
875*59ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
876*59ac0c16Sdavemq 		goto fail;
877*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
878*59ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
879*59ac0c16Sdavemq 		goto fail;
880*59ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
881*59ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
882*59ac0c16Sdavemq 		    "Failed to reset port<%d> XAUI Serdes", portn));
883*59ac0c16Sdavemq 	}
884*59ac0c16Sdavemq 
885*59ac0c16Sdavemq 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
88644961713Sgirish 
887*59ac0c16Sdavemq 	if (portn == 0) {
888*59ac0c16Sdavemq 		if ((val & ESR_SIG_P0_BITS_MASK) !=
88944961713Sgirish 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
89044961713Sgirish 					ESR_SIG_XSERDES_RDY_P0 |
89144961713Sgirish 					ESR_SIG_XDETECT_P0_CH3 |
89244961713Sgirish 					ESR_SIG_XDETECT_P0_CH2 |
89344961713Sgirish 					ESR_SIG_XDETECT_P0_CH1 |
89444961713Sgirish 					ESR_SIG_XDETECT_P0_CH0)) {
895*59ac0c16Sdavemq 			goto fail;
896*59ac0c16Sdavemq 		}
897*59ac0c16Sdavemq 	} else if (portn == 1) {
898*59ac0c16Sdavemq 		if ((val & ESR_SIG_P1_BITS_MASK) !=
89944961713Sgirish 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
90044961713Sgirish 					ESR_SIG_XSERDES_RDY_P1 |
90144961713Sgirish 					ESR_SIG_XDETECT_P1_CH3 |
90244961713Sgirish 					ESR_SIG_XDETECT_P1_CH2 |
90344961713Sgirish 					ESR_SIG_XDETECT_P1_CH1 |
90444961713Sgirish 					ESR_SIG_XDETECT_P1_CH0)) {
90544961713Sgirish 			goto fail;
90644961713Sgirish 		}
90744961713Sgirish 	}
90844961713Sgirish 
90944961713Sgirish done:
910*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
911*59ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
912*59ac0c16Sdavemq 
91344961713Sgirish 	return (NXGE_OK);
91444961713Sgirish fail:
915*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
916*59ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
917*59ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
91844961713Sgirish 
91944961713Sgirish 	return (status);
92044961713Sgirish }
92144961713Sgirish 
922*59ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
92344961713Sgirish 
924*59ac0c16Sdavemq static nxge_status_t
925*59ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
92644961713Sgirish {
927*59ac0c16Sdavemq 	npi_handle_t		handle;
928*59ac0c16Sdavemq 	uint8_t			portn;
929*59ac0c16Sdavemq 	uint64_t		val;
93044961713Sgirish 
93144961713Sgirish 	portn = nxgep->mac.portnum;
93244961713Sgirish 
933*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
934*59ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
93544961713Sgirish 
936*59ac0c16Sdavemq 	handle = nxgep->npi_handle;
93744961713Sgirish 
938*59ac0c16Sdavemq 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
939*59ac0c16Sdavemq 	val &= ~ESR_PLL_CFG_FBDIV_2;
940*59ac0c16Sdavemq 	switch (portn) {
941*59ac0c16Sdavemq 	case 0:
942*59ac0c16Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_0;
943*59ac0c16Sdavemq 		break;
944*59ac0c16Sdavemq 	case 1:
945*59ac0c16Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_1;
946*59ac0c16Sdavemq 		break;
947*59ac0c16Sdavemq 	case 2:
948*59ac0c16Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_2;
949*59ac0c16Sdavemq 		break;
950*59ac0c16Sdavemq 	case 3:
951*59ac0c16Sdavemq 		val |= ESR_PLL_CFG_HALF_RATE_3;
952*59ac0c16Sdavemq 		break;
953*59ac0c16Sdavemq 	default:
954*59ac0c16Sdavemq 		goto fail;
95544961713Sgirish 	}
95644961713Sgirish 
957*59ac0c16Sdavemq 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
958*59ac0c16Sdavemq 
959*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
960*59ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
96144961713Sgirish 	return (NXGE_OK);
962*59ac0c16Sdavemq fail:
963*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
964*59ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
965*59ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
966*59ac0c16Sdavemq 	    portn));
967*59ac0c16Sdavemq 
968*59ac0c16Sdavemq 	return (NXGE_ERROR);
96944961713Sgirish }
97044961713Sgirish 
971*59ac0c16Sdavemq /* Initialize the 10G (BCM8704) Transceiver */
97244961713Sgirish 
973*59ac0c16Sdavemq static nxge_status_t
974*59ac0c16Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep)
97544961713Sgirish {
97644961713Sgirish 	p_nxge_stats_t		statsp;
97744961713Sgirish 	uint16_t		val;
97844961713Sgirish #ifdef	NXGE_DEBUG
97914ea4bb7Ssd 	uint8_t			portn;
98044961713Sgirish 	uint16_t		val1;
98144961713Sgirish #endif
98244961713Sgirish 	uint8_t			phy_port_addr;
98344961713Sgirish 	pmd_tx_control_t	tx_ctl;
98444961713Sgirish 	control_t		ctl;
98544961713Sgirish 	phyxs_control_t		phyxs_ctl;
98644961713Sgirish 	pcs_control_t		pcs_ctl;
98744961713Sgirish 	uint32_t		delay = 0;
98844961713Sgirish 	optics_dcntr_t		op_ctr;
98944961713Sgirish 	nxge_status_t		status = NXGE_OK;
99014ea4bb7Ssd #ifdef	NXGE_DEBUG
99144961713Sgirish 	portn = nxgep->mac.portnum;
99214ea4bb7Ssd #endif
993*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
994*59ac0c16Sdavemq 	    portn));
99544961713Sgirish 
99644961713Sgirish 	statsp = nxgep->statsp;
99744961713Sgirish 
998*59ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
999*59ac0c16Sdavemq 
1000*59ac0c16Sdavemq 	/* Disable Link LEDs */
1001*59ac0c16Sdavemq 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1002*59ac0c16Sdavemq 		goto fail;
1003*59ac0c16Sdavemq 
1004*59ac0c16Sdavemq 	/* Set Clause 45 */
1005*59ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
1006*59ac0c16Sdavemq 
1007*59ac0c16Sdavemq 	/* Reset the transceiver */
1008*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1009*59ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
1010*59ac0c16Sdavemq 		goto fail;
1011*59ac0c16Sdavemq 
1012*59ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
1013*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1014*59ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
1015*59ac0c16Sdavemq 		goto fail;
1016*59ac0c16Sdavemq 
1017*59ac0c16Sdavemq 	do {
1018*59ac0c16Sdavemq 		drv_usecwait(500);
1019*59ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1020*59ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
1021*59ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
1022*59ac0c16Sdavemq 			goto fail;
1023*59ac0c16Sdavemq 		delay++;
1024*59ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
1025*59ac0c16Sdavemq 	if (delay == 100) {
1026*59ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
1027*59ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
1028*59ac0c16Sdavemq 		status = NXGE_ERROR;
1029*59ac0c16Sdavemq 		goto fail;
1030*59ac0c16Sdavemq 	}
103144961713Sgirish 
1032*59ac0c16Sdavemq 	/* Set to 0x7FBF */
1033*59ac0c16Sdavemq 	ctl.value = 0;
1034*59ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
1035*59ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
1036*59ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
1037*59ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
1038*59ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
1039*59ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
1040*59ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
1041*59ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
1042*59ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
1043*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1044*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
1045*59ac0c16Sdavemq 	    != NXGE_OK)
1046*59ac0c16Sdavemq 		goto fail;
1047*59ac0c16Sdavemq 
1048*59ac0c16Sdavemq 	/* Set to 0x164 */
1049*59ac0c16Sdavemq 	tx_ctl.value = 0;
1050*59ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
1051*59ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
1052*59ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
1053*59ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
1054*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1055*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
1056*59ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
1057*59ac0c16Sdavemq 		goto fail;
105844961713Sgirish 	/*
1059*59ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
1060*59ac0c16Sdavemq 	 * back these registers twice after written.
106144961713Sgirish 	 */
1062*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1063*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1064*59ac0c16Sdavemq 	    != NXGE_OK)
1065*59ac0c16Sdavemq 		goto fail;
106644961713Sgirish 
1067*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1068*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1069*59ac0c16Sdavemq 	    != NXGE_OK)
1070*59ac0c16Sdavemq 		goto fail;
107144961713Sgirish 
1072*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1073*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1074*59ac0c16Sdavemq 	    != NXGE_OK)
1075*59ac0c16Sdavemq 		goto fail;
107644961713Sgirish 
1077*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1078*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1079*59ac0c16Sdavemq 	    != NXGE_OK)
1080*59ac0c16Sdavemq 		goto fail;
108144961713Sgirish 
1082*59ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
1083*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1084*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1085*59ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
1086*59ac0c16Sdavemq 		goto fail;
1087*59ac0c16Sdavemq 	op_ctr.bits.gpio_sel = 0x3;
1088*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1089*59ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1090*59ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
1091*59ac0c16Sdavemq 		goto fail;
109244961713Sgirish 
1093*59ac0c16Sdavemq 	NXGE_DELAY(1000000);
109444961713Sgirish 
1095*59ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
1096*59ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1097*59ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
1098*59ac0c16Sdavemq 	    != NXGE_OK)
1099*59ac0c16Sdavemq 		goto fail;
1100*59ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
1101*59ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
1102*59ac0c16Sdavemq 	else
1103*59ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
1104*59ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1105*59ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
1106*59ac0c16Sdavemq 	    != NXGE_OK)
1107*59ac0c16Sdavemq 		goto fail;
110844961713Sgirish 
1109*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
1110*59ac0c16Sdavemq 	if (status != NXGE_OK)
1111*59ac0c16Sdavemq 		goto fail;
1112*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1113*59ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
1114*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
1115*59ac0c16Sdavemq 	if (status != NXGE_OK)
1116*59ac0c16Sdavemq 		goto fail;
1117*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1118*59ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
1119*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
1120*59ac0c16Sdavemq 	if (status != NXGE_OK)
1121*59ac0c16Sdavemq 		goto fail;
1122*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1123*59ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
112444961713Sgirish 
1125*59ac0c16Sdavemq #ifdef	NXGE_DEBUG
1126*59ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
1127*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
1128*59ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
1129*59ac0c16Sdavemq 	    &val);
1130*59ac0c16Sdavemq 	if (status != NXGE_OK)
1131*59ac0c16Sdavemq 		goto fail;
113244961713Sgirish 
1133*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
113444961713Sgirish 				BCM8704_USER_DEV3_ADDR,
1135*59ac0c16Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
1136*59ac0c16Sdavemq 				&val);
1137*59ac0c16Sdavemq 	if (status != NXGE_OK)
1138*59ac0c16Sdavemq 		goto fail;
113944961713Sgirish 
1140*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
114144961713Sgirish 				BCM8704_USER_DEV3_ADDR,
1142*59ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
1143*59ac0c16Sdavemq 				&val1);
1144*59ac0c16Sdavemq 	if (status != NXGE_OK)
1145*59ac0c16Sdavemq 		goto fail;
114644961713Sgirish 
1147*59ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
114844961713Sgirish 				BCM8704_USER_DEV3_ADDR,
1149*59ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
1150*59ac0c16Sdavemq 				&val1);
1151*59ac0c16Sdavemq 	if (status != NXGE_OK)
1152*59ac0c16Sdavemq 		goto fail;
115344961713Sgirish 
1154*59ac0c16Sdavemq 	if (val != 0x3FC) {
1155*59ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
1156*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1157*59ac0c16Sdavemq 			    "Cable not connected to peer or bad"
1158*59ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
1159*59ac0c16Sdavemq 		} else if (val == 0x639C) {
1160*59ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1161*59ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
1162*59ac0c16Sdavemq 			    " on port<%d>\n", portn));
1163*59ac0c16Sdavemq 		}
1164*59ac0c16Sdavemq 	}
1165*59ac0c16Sdavemq #endif
116644961713Sgirish 
1167*59ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
1168*59ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
116944961713Sgirish 
1170*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
1171*59ac0c16Sdavemq 	    portn));
1172*59ac0c16Sdavemq 	return (NXGE_OK);
117344961713Sgirish 
1174*59ac0c16Sdavemq fail:
1175*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1176*59ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
1177*59ac0c16Sdavemq 	    "port<%d>", portn));
1178*59ac0c16Sdavemq 	return (status);
1179*59ac0c16Sdavemq }
118044961713Sgirish 
1181*59ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
118244961713Sgirish 
1183*59ac0c16Sdavemq static nxge_status_t
1184*59ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
1185*59ac0c16Sdavemq {
1186*59ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
1187*59ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
1188*59ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
118944961713Sgirish 
1190*59ac0c16Sdavemq 	/* Set Clause 22 */
1191*59ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
119244961713Sgirish 
1193*59ac0c16Sdavemq 	/* Set capability flags */
1194*59ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
1195*59ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value;
1196*59ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
119744961713Sgirish 
1198*59ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
119944961713Sgirish 
1200*59ac0c16Sdavemq 	return (status);
1201*59ac0c16Sdavemq }
1202*59ac0c16Sdavemq 
1203*59ac0c16Sdavemq /* Initialize transceiver */
1204*59ac0c16Sdavemq 
1205*59ac0c16Sdavemq nxge_status_t
1206*59ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
1207*59ac0c16Sdavemq {
1208*59ac0c16Sdavemq 	p_nxge_stats_t		statsp;
1209*59ac0c16Sdavemq #ifdef	NXGE_DEBUG
1210*59ac0c16Sdavemq 	uint8_t			portn;
121144961713Sgirish #endif
121244961713Sgirish 
1213*59ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
1214*59ac0c16Sdavemq #ifdef	NXGE_DEBUG
1215*59ac0c16Sdavemq 	portn = nxgep->mac.portnum;
1216*59ac0c16Sdavemq #endif
1217*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
1218*59ac0c16Sdavemq 	statsp = nxgep->statsp;
121944961713Sgirish 
1220*59ac0c16Sdavemq 	/*
1221*59ac0c16Sdavemq 	 * Initialize the xcvr statistics.
1222*59ac0c16Sdavemq 	 */
1223*59ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
1224*59ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
1225*59ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
1226*59ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
1227*59ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
1228*59ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
1229*59ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
1230*59ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
1231*59ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
1232*59ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
1233*59ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
1234*59ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
1235*59ac0c16Sdavemq 
1236*59ac0c16Sdavemq 	/*
1237*59ac0c16Sdavemq 	 * Initialize the link statistics.
1238*59ac0c16Sdavemq 	 */
1239*59ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
1240*59ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
1241*59ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
124244961713Sgirish 
1243*59ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
1244*59ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
1245*59ac0c16Sdavemq 		if (status != NXGE_OK)
124644961713Sgirish 			goto fail;
1247*59ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
124844961713Sgirish 	}
124944961713Sgirish 
1250*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
1251*59ac0c16Sdavemq 	    portn));
125244961713Sgirish 	return (NXGE_OK);
125344961713Sgirish 
125444961713Sgirish fail:
125544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1256*59ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
1257*59ac0c16Sdavemq 	    portn));
125844961713Sgirish 	return (status);
125944961713Sgirish }
126044961713Sgirish 
126144961713Sgirish 
126244961713Sgirish /* Initialize the TxMAC sub-block */
126344961713Sgirish 
126444961713Sgirish nxge_status_t
126544961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
126644961713Sgirish {
126744961713Sgirish 	npi_attr_t		ap;
126844961713Sgirish 	uint8_t			portn;
126944961713Sgirish 	nxge_port_mode_t	portmode;
127044961713Sgirish 	nxge_port_t		portt;
127144961713Sgirish 	npi_handle_t		handle;
127244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
127344961713Sgirish 
127444961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
127544961713Sgirish 	portt    = nxgep->mac.porttype;
127644961713Sgirish 	handle   = nxgep->npi_handle;
127744961713Sgirish 	portmode = nxgep->mac.portmode;
127844961713Sgirish 
127944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
128044961713Sgirish 			portn));
128144961713Sgirish 
128244961713Sgirish 	/* Set Max and Min Frame Size */
128314ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
128444961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
128544961713Sgirish 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
128644961713Sgirish 	} else {
128744961713Sgirish 		SET_MAC_ATTR2(handle, ap, portn,
128844961713Sgirish 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
128944961713Sgirish 	}
129044961713Sgirish 
129144961713Sgirish 	if (rs != NPI_SUCCESS)
129244961713Sgirish 		goto fail;
129314ea4bb7Ssd 	if (nxgep->param_arr[param_accept_jumbo].value ||
129414ea4bb7Ssd 		nxgep->mac.is_jumbo == B_TRUE)
129544961713Sgirish 		nxgep->mac.maxframesize = 0x2400;
129644961713Sgirish 	else
129744961713Sgirish 		nxgep->mac.maxframesize = 0x5EE + 4;
129844961713Sgirish 	nxgep->mac.minframesize = 64;
129944961713Sgirish 
130044961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
130144961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
130244961713Sgirish 				0)) != NPI_SUCCESS)
130344961713Sgirish 			goto fail;
130444961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
130544961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
130644961713Sgirish 					(portmode == PORT_10G_COPPER)) {
130744961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
130844961713Sgirish 					XGMII_IPG_12_15, rs);
130944961713Sgirish 			if (rs != NPI_SUCCESS)
131044961713Sgirish 				goto fail;
131144961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
131244961713Sgirish 		} else {
131344961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
131444961713Sgirish 					MII_GMII_IPG_12, rs);
131544961713Sgirish 			if (rs != NPI_SUCCESS)
131644961713Sgirish 				goto fail;
131744961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
131844961713Sgirish 		}
131944961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
132044961713Sgirish 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
132144961713Sgirish 			goto fail;
132244961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
132344961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
132444961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
132544961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
132644961713Sgirish 
132744961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
132844961713Sgirish 							!= NPI_SUCCESS)
132944961713Sgirish 			goto fail;
133044961713Sgirish 
133144961713Sgirish 	} else {
133244961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
133344961713Sgirish 				0)) != NPI_SUCCESS)
133444961713Sgirish 			goto fail;
133544961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
133644961713Sgirish 
133744961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
133844961713Sgirish 				rs);
133944961713Sgirish 		if (rs != NPI_SUCCESS)
134044961713Sgirish 			goto fail;
134144961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
134244961713Sgirish 
134344961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
134444961713Sgirish 		if (rs != NPI_SUCCESS)
134544961713Sgirish 			goto fail;
134644961713Sgirish 		nxgep->mac.pa_size = 0x7;
134744961713Sgirish 
134844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
134944961713Sgirish 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
135044961713Sgirish 			goto fail;
135144961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
135244961713Sgirish 	}
135344961713Sgirish 
135444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
135544961713Sgirish 			portn));
135644961713Sgirish 
135744961713Sgirish 	return (NXGE_OK);
135844961713Sgirish fail:
135944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
136044961713Sgirish 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
136144961713Sgirish 					portn));
136244961713Sgirish 
136344961713Sgirish 	return (NXGE_ERROR | rs);
136444961713Sgirish }
136544961713Sgirish 
136644961713Sgirish /* Initialize the RxMAC sub-block */
136744961713Sgirish 
136844961713Sgirish nxge_status_t
136944961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
137044961713Sgirish {
137144961713Sgirish 	npi_attr_t		ap;
137244961713Sgirish 	uint32_t		i;
137344961713Sgirish 	uint16_t		hashtab_e;
137444961713Sgirish 	p_hash_filter_t		hash_filter;
137544961713Sgirish 	nxge_port_t		portt;
137644961713Sgirish 	uint8_t			portn;
137744961713Sgirish 	npi_handle_t		handle;
137844961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
137944961713Sgirish 	uint16_t 		*addr16p;
138044961713Sgirish 	uint16_t 		addr0, addr1, addr2;
138144961713Sgirish 	xmac_rx_config_t	xconfig;
138244961713Sgirish 	bmac_rx_config_t	bconfig;
138344961713Sgirish 
138444961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
138544961713Sgirish 
138644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
138744961713Sgirish 			portn));
138844961713Sgirish 	handle = nxgep->npi_handle;
138944961713Sgirish 	portt = nxgep->mac.porttype;
139044961713Sgirish 
139144961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
139244961713Sgirish 	addr0 = ntohs(addr16p[2]);
139344961713Sgirish 	addr1 = ntohs(addr16p[1]);
139444961713Sgirish 	addr2 = ntohs(addr16p[0]);
139544961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
139644961713Sgirish 		rs);
139744961713Sgirish 
139844961713Sgirish 	if (rs != NPI_SUCCESS)
139944961713Sgirish 		goto fail;
140044961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
140144961713Sgirish 	if (rs != NPI_SUCCESS)
140244961713Sgirish 		goto fail;
140344961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
140444961713Sgirish 	if (rs != NPI_SUCCESS)
140544961713Sgirish 		goto fail;
140644961713Sgirish 
140744961713Sgirish 	/*
140844961713Sgirish 	 * Load the multicast hash filter bits.
140944961713Sgirish 	 */
141044961713Sgirish 	hash_filter = nxgep->hash_filter;
141144961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
141244961713Sgirish 		if (hash_filter != NULL) {
141344961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
141444961713Sgirish 				(NMCFILTER_REGS - 1) - i];
141544961713Sgirish 		} else {
141644961713Sgirish 			hashtab_e = 0;
141744961713Sgirish 		}
141844961713Sgirish 
141944961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
142044961713Sgirish 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
142144961713Sgirish 			goto fail;
142244961713Sgirish 	}
142344961713Sgirish 
142444961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
142544961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
142644961713Sgirish 				0)) != NPI_SUCCESS)
142744961713Sgirish 			goto fail;
142844961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
142944961713Sgirish 
143044961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
143144961713Sgirish 
143244961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
1433a3c5bd6dSspeer 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
1434a3c5bd6dSspeer 			~CFG_XMAC_RX_STRIP_CRC;
143544961713Sgirish 
143644961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
143744961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
143844961713Sgirish 
143944961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
144044961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
144144961713Sgirish 
144244961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
144344961713Sgirish 
144444961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
144544961713Sgirish 					xconfig)) != NPI_SUCCESS)
144644961713Sgirish 			goto fail;
144744961713Sgirish 		nxgep->mac.rx_config = xconfig;
144844961713Sgirish 
144944961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
145044961713Sgirish 
145144961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
145244961713Sgirish 							!= NPI_SUCCESS)
145344961713Sgirish 			goto fail;
145444961713Sgirish 	} else {
145544961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
145644961713Sgirish 
145744961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
145844961713Sgirish 					0) != NPI_SUCCESS)
145944961713Sgirish 			goto fail;
146044961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
146144961713Sgirish 
1462a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
1463a3c5bd6dSspeer 			~CFG_BMAC_RX_STRIP_CRC;
146444961713Sgirish 
146544961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
146644961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
146744961713Sgirish 
146844961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
146944961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
147044961713Sgirish 
147144961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
147244961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
147344961713Sgirish 					bconfig)) != NPI_SUCCESS)
147444961713Sgirish 			goto fail;
147544961713Sgirish 		nxgep->mac.rx_config = bconfig;
147644961713Sgirish 
147744961713Sgirish 		/* Always enable comparison of mac unique address */
147844961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
147944961713Sgirish 					!= NPI_SUCCESS)
148044961713Sgirish 			goto fail;
148144961713Sgirish 	}
148244961713Sgirish 
148344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
148444961713Sgirish 			portn));
148544961713Sgirish 
148644961713Sgirish 	return (NXGE_OK);
148744961713Sgirish 
148844961713Sgirish fail:
148944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
149044961713Sgirish 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
149144961713Sgirish 				portn));
149244961713Sgirish 
149344961713Sgirish 	return (NXGE_ERROR | rs);
149444961713Sgirish }
149544961713Sgirish 
149644961713Sgirish /* Enable TXMAC */
149744961713Sgirish 
149844961713Sgirish nxge_status_t
149944961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
150044961713Sgirish {
150144961713Sgirish 	npi_handle_t	handle;
150244961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
150344961713Sgirish 	nxge_status_t	status = NXGE_OK;
150444961713Sgirish 
150544961713Sgirish 	handle = nxgep->npi_handle;
150644961713Sgirish 
150744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
150844961713Sgirish 			nxgep->mac.portnum));
150944961713Sgirish 
151044961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
151144961713Sgirish 		goto fail;
151244961713Sgirish 
151344961713Sgirish 	/* based on speed */
151444961713Sgirish 	nxgep->msg_min = ETHERMIN;
151544961713Sgirish 
151644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
151744961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
151844961713Sgirish 						CFG_XMAC_TX)) != NPI_SUCCESS)
151944961713Sgirish 			goto fail;
152044961713Sgirish 	} else {
152144961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
152244961713Sgirish 						CFG_BMAC_TX)) != NPI_SUCCESS)
152344961713Sgirish 			goto fail;
152444961713Sgirish 	}
152544961713Sgirish 
152644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
152744961713Sgirish 			nxgep->mac.portnum));
152844961713Sgirish 
152944961713Sgirish 	return (NXGE_OK);
153044961713Sgirish fail:
153144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
153244961713Sgirish 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
153344961713Sgirish 			nxgep->mac.portnum));
153444961713Sgirish 	if (rs != NPI_SUCCESS)
153544961713Sgirish 		return (NXGE_ERROR | rs);
153644961713Sgirish 	else
153744961713Sgirish 		return (status);
153844961713Sgirish }
153944961713Sgirish 
154044961713Sgirish /* Disable TXMAC */
154144961713Sgirish 
154244961713Sgirish nxge_status_t
154344961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
154444961713Sgirish {
154544961713Sgirish 	npi_handle_t	handle;
154644961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
154744961713Sgirish 
154844961713Sgirish 	handle = nxgep->npi_handle;
154944961713Sgirish 
155044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
155144961713Sgirish 			nxgep->mac.portnum));
155244961713Sgirish 
155344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
155444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
155544961713Sgirish 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
155644961713Sgirish 			goto fail;
155744961713Sgirish 	} else {
155844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
155944961713Sgirish 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
156044961713Sgirish 			goto fail;
156144961713Sgirish 	}
156244961713Sgirish 
156344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
156444961713Sgirish 			nxgep->mac.portnum));
156544961713Sgirish 	return (NXGE_OK);
156644961713Sgirish fail:
156744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
156844961713Sgirish 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
156944961713Sgirish 			nxgep->mac.portnum));
157044961713Sgirish 	return (NXGE_ERROR | rs);
157144961713Sgirish }
157244961713Sgirish 
157344961713Sgirish /* Enable RXMAC */
157444961713Sgirish 
157544961713Sgirish nxge_status_t
157644961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
157744961713Sgirish {
157844961713Sgirish 	npi_handle_t	handle;
157944961713Sgirish 	uint8_t 	portn;
158044961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
158144961713Sgirish 	nxge_status_t	status = NXGE_OK;
158244961713Sgirish 
158344961713Sgirish 	handle = nxgep->npi_handle;
158444961713Sgirish 	portn = nxgep->mac.portnum;
158544961713Sgirish 
158644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
158744961713Sgirish 			portn));
158844961713Sgirish 
158944961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
159044961713Sgirish 		goto fail;
159144961713Sgirish 
159244961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
159344961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
159444961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
159544961713Sgirish 			goto fail;
159644961713Sgirish 	} else {
159744961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
159844961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
159944961713Sgirish 			goto fail;
160044961713Sgirish 	}
160144961713Sgirish 
160244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
160344961713Sgirish 			portn));
160444961713Sgirish 
160544961713Sgirish 	return (NXGE_OK);
160644961713Sgirish fail:
160744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
160844961713Sgirish 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
160944961713Sgirish 			portn));
161044961713Sgirish 
161144961713Sgirish 	if (rs != NPI_SUCCESS)
161244961713Sgirish 		return (NXGE_ERROR | rs);
161344961713Sgirish 	else
161444961713Sgirish 		return (status);
161544961713Sgirish }
161644961713Sgirish 
161744961713Sgirish /* Disable RXMAC */
161844961713Sgirish 
161944961713Sgirish nxge_status_t
162044961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
162144961713Sgirish {
162244961713Sgirish 	npi_handle_t	handle;
162344961713Sgirish 	uint8_t		portn;
162444961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
162544961713Sgirish 
162644961713Sgirish 	handle = nxgep->npi_handle;
162744961713Sgirish 	portn = nxgep->mac.portnum;
162844961713Sgirish 
162944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
163044961713Sgirish 			portn));
163144961713Sgirish 
163244961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
163344961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
163444961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
163544961713Sgirish 			goto fail;
163644961713Sgirish 	} else {
163744961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
163844961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
163944961713Sgirish 			goto fail;
164044961713Sgirish 	}
164144961713Sgirish 
164244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
164344961713Sgirish 			portn));
164444961713Sgirish 	return (NXGE_OK);
164544961713Sgirish fail:
164644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
164744961713Sgirish 			"nxgep_rx_mac_disable: ",
164844961713Sgirish 			"Failed to disable port<%d> RxMAC",
164944961713Sgirish 			portn));
165044961713Sgirish 
165144961713Sgirish 	return (NXGE_ERROR | rs);
165244961713Sgirish }
165344961713Sgirish 
165444961713Sgirish /* Reset TXMAC */
165544961713Sgirish 
165644961713Sgirish nxge_status_t
165744961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
165844961713Sgirish {
165944961713Sgirish 	npi_handle_t	handle;
166044961713Sgirish 	uint8_t		portn;
166144961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
166244961713Sgirish 
166344961713Sgirish 	handle = nxgep->npi_handle;
166444961713Sgirish 	portn = nxgep->mac.portnum;
166544961713Sgirish 
166644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
166744961713Sgirish 			portn));
166844961713Sgirish 
166944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
167044961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
167144961713Sgirish 		    != NPI_SUCCESS)
167244961713Sgirish 			goto fail;
167344961713Sgirish 	} else {
167444961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
167544961713Sgirish 					!= NPI_SUCCESS)
167644961713Sgirish 			goto fail;
167744961713Sgirish 	}
167844961713Sgirish 
167944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
168044961713Sgirish 			portn));
168144961713Sgirish 
168244961713Sgirish 	return (NXGE_OK);
168344961713Sgirish fail:
168444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
168544961713Sgirish 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
168644961713Sgirish 			portn));
168744961713Sgirish 
168844961713Sgirish 	return (NXGE_ERROR | rs);
168944961713Sgirish }
169044961713Sgirish 
169144961713Sgirish /* Reset RXMAC */
169244961713Sgirish 
169344961713Sgirish nxge_status_t
169444961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
169544961713Sgirish {
169644961713Sgirish 	npi_handle_t	handle;
169744961713Sgirish 	uint8_t		portn;
169844961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
169944961713Sgirish 
170044961713Sgirish 	handle = nxgep->npi_handle;
170144961713Sgirish 	portn = nxgep->mac.portnum;
170244961713Sgirish 
170344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
170444961713Sgirish 			portn));
170544961713Sgirish 
170644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
170744961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
170844961713Sgirish 		    != NPI_SUCCESS)
170944961713Sgirish 		goto fail;
171044961713Sgirish 	} else {
171144961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
171244961713Sgirish 					!= NPI_SUCCESS)
171344961713Sgirish 		goto fail;
171444961713Sgirish 	}
171544961713Sgirish 
171644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
171744961713Sgirish 			portn));
171844961713Sgirish 
1719*59ac0c16Sdavemq 	return (NXGE_OK);
1720*59ac0c16Sdavemq fail:
1721*59ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1722*59ac0c16Sdavemq 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
1723*59ac0c16Sdavemq 			portn));
1724*59ac0c16Sdavemq 	return (NXGE_ERROR | rs);
1725*59ac0c16Sdavemq }
1726*59ac0c16Sdavemq 
1727*59ac0c16Sdavemq /* 10G fiber link interrupt start routine */
1728*59ac0c16Sdavemq 
1729*59ac0c16Sdavemq static nxge_status_t
1730*59ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
1731*59ac0c16Sdavemq {
1732*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1733*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1734*59ac0c16Sdavemq 
1735*59ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
1736*59ac0c16Sdavemq 
1737*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1738*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1739*59ac0c16Sdavemq 	else
1740*59ac0c16Sdavemq 		return (NXGE_OK);
1741*59ac0c16Sdavemq }
1742*59ac0c16Sdavemq 
1743*59ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
1744*59ac0c16Sdavemq 
1745*59ac0c16Sdavemq static nxge_status_t
1746*59ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
1747*59ac0c16Sdavemq {
1748*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1749*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1750*59ac0c16Sdavemq 
1751*59ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
1752*59ac0c16Sdavemq 
1753*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1754*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1755*59ac0c16Sdavemq 	else
1756*59ac0c16Sdavemq 		return (NXGE_OK);
1757*59ac0c16Sdavemq }
1758*59ac0c16Sdavemq 
1759*59ac0c16Sdavemq /* 1G fiber link interrupt start routine */
1760*59ac0c16Sdavemq 
1761*59ac0c16Sdavemq static nxge_status_t
1762*59ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
1763*59ac0c16Sdavemq {
1764*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1765*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1766*59ac0c16Sdavemq 
1767*59ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
1768*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1769*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1770*59ac0c16Sdavemq 	else
1771*59ac0c16Sdavemq 		return (NXGE_OK);
1772*59ac0c16Sdavemq }
1773*59ac0c16Sdavemq 
1774*59ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
1775*59ac0c16Sdavemq 
1776*59ac0c16Sdavemq static nxge_status_t
1777*59ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
1778*59ac0c16Sdavemq {
1779*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1780*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1781*59ac0c16Sdavemq 
1782*59ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
1783*59ac0c16Sdavemq 
1784*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1785*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1786*59ac0c16Sdavemq 	else
1787*59ac0c16Sdavemq 		return (NXGE_OK);
1788*59ac0c16Sdavemq }
1789*59ac0c16Sdavemq 
1790*59ac0c16Sdavemq /* 1G copper link interrupt start routine */
1791*59ac0c16Sdavemq 
1792*59ac0c16Sdavemq static nxge_status_t
1793*59ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
1794*59ac0c16Sdavemq {
1795*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1796*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1797*59ac0c16Sdavemq 
1798*59ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
1799*59ac0c16Sdavemq 	    MII_BMSR, BMSR_LSTATUS);
1800*59ac0c16Sdavemq 
1801*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1802*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1803*59ac0c16Sdavemq 	else
1804*59ac0c16Sdavemq 		return (NXGE_OK);
180544961713Sgirish }
180644961713Sgirish 
1807*59ac0c16Sdavemq /* 1G copper link interrupt stop routine */
1808*59ac0c16Sdavemq 
1809*59ac0c16Sdavemq static nxge_status_t
1810*59ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
1811*59ac0c16Sdavemq {
1812*59ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
1813*59ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
1814*59ac0c16Sdavemq 
1815*59ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
1816*59ac0c16Sdavemq 
1817*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
1818*59ac0c16Sdavemq 		return (NXGE_ERROR | rs);
1819*59ac0c16Sdavemq 	else
1820*59ac0c16Sdavemq 		return (NXGE_OK);
1821*59ac0c16Sdavemq }
182244961713Sgirish 
1823*59ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
182444961713Sgirish 
182544961713Sgirish nxge_status_t
182644961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
182744961713Sgirish {
1828*59ac0c16Sdavemq 	uint8_t		portn;
1829*59ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
183044961713Sgirish 
183144961713Sgirish 	portn = nxgep->mac.portnum;
183244961713Sgirish 
183344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
1834*59ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
1835*59ac0c16Sdavemq 		return (NXGE_OK);
183644961713Sgirish 
1837*59ac0c16Sdavemq 	if (enable == LINK_INTR_START)
1838*59ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
1839*59ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
1840*59ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
1841*59ac0c16Sdavemq 	if (status != NXGE_OK)
1842*59ac0c16Sdavemq 		goto fail;
184344961713Sgirish 
184444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
184544961713Sgirish 
184644961713Sgirish 	return (NXGE_OK);
184744961713Sgirish fail:
184844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
184944961713Sgirish 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
185044961713Sgirish 			portn));
185144961713Sgirish 
1852*59ac0c16Sdavemq 	return (status);
185344961713Sgirish }
185444961713Sgirish 
185544961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
185644961713Sgirish 
185744961713Sgirish nxge_status_t
185844961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
185944961713Sgirish {
186044961713Sgirish 	p_nxge_param_t	param_arr;
186144961713Sgirish 	p_nxge_stats_t	statsp;
186244961713Sgirish 	uint8_t		xcvr_portn;
186344961713Sgirish 	p_mii_regs_t	mii_regs;
186444961713Sgirish 	mii_bmcr_t	bmcr;
186544961713Sgirish 	mii_bmsr_t	bmsr;
186644961713Sgirish 	mii_anar_t	anar;
186744961713Sgirish 	mii_gcr_t	gcr;
186844961713Sgirish 	mii_esr_t	esr;
186944961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
187044961713Sgirish 	int		status = NXGE_OK;
187144961713Sgirish 
187244961713Sgirish 	uint_t delay;
187344961713Sgirish 
187444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
187544961713Sgirish 
187644961713Sgirish 	param_arr = nxgep->param_arr;
187744961713Sgirish 	statsp = nxgep->statsp;
187844961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
187944961713Sgirish 
188044961713Sgirish 	mii_regs = NULL;
188144961713Sgirish 
188244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
188344961713Sgirish 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
188444961713Sgirish 
188544961713Sgirish 	/*
188644961713Sgirish 	 * Reset the transceiver.
188744961713Sgirish 	 */
188844961713Sgirish 	delay = 0;
188944961713Sgirish 	bmcr.value = 0;
189044961713Sgirish 	bmcr.bits.reset = 1;
189144961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
189244961713Sgirish 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
189344961713Sgirish 		goto fail;
189444961713Sgirish 	do {
189544961713Sgirish 		drv_usecwait(500);
189644961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
189744961713Sgirish 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
189844961713Sgirish 				!= NXGE_OK)
189944961713Sgirish 			goto fail;
190044961713Sgirish 		delay++;
190144961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
190244961713Sgirish 	if (delay == 1000) {
190344961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
190444961713Sgirish 		goto fail;
190544961713Sgirish 	}
190644961713Sgirish 
190744961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
190844961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
190944961713Sgirish 			&bmsr.value)) != NXGE_OK)
191044961713Sgirish 		goto fail;
191144961713Sgirish 
191244961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
191344961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
191444961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
191544961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
191644961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
191744961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
191844961713Sgirish 
191944961713Sgirish 	/*
192058324dfcSspeer 	 * Initialize the xcvr statistics.
192144961713Sgirish 	 */
192244961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
192344961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
192444961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
192544961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
192644961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
192744961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
192844961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
192944961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
193044961713Sgirish 
193144961713Sgirish 	/*
193244961713Sgirish 	 * Initialise the xcvr advertised capability statistics.
193344961713Sgirish 	 */
193444961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
193544961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
193644961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
193744961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
193844961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
193944961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
194044961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
194144961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
194244961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
194344961713Sgirish 					param_arr[param_anar_asmpause].value;
194444961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
194544961713Sgirish 
194644961713Sgirish 
194744961713Sgirish 	/*
194844961713Sgirish 	 * Check for extended status just in case we're
194944961713Sgirish 	 * running a Gigibit phy.
195044961713Sgirish 	 */
195144961713Sgirish 	if (bmsr.bits.extend_status) {
195244961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
195344961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
195444961713Sgirish 				!= NXGE_OK)
195544961713Sgirish 			goto fail;
195644961713Sgirish 		param_arr[param_anar_1000fdx].value &=
195744961713Sgirish 					esr.bits.link_1000fdx;
195844961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
195944961713Sgirish 
196044961713Sgirish 		statsp->mac_stats.cap_1000fdx =
196144961713Sgirish 			(esr.bits.link_1000Xfdx ||
196244961713Sgirish 				esr.bits.link_1000fdx);
196344961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
196444961713Sgirish 	} else {
196544961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
196644961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
196744961713Sgirish 	}
196844961713Sgirish 
196944961713Sgirish 	/*
197044961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
197144961713Sgirish 	 */
197244961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
197344961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
197444961713Sgirish 
197544961713Sgirish 	/*
197644961713Sgirish 	 * Initialise the link statistics.
197744961713Sgirish 	 */
197844961713Sgirish 	statsp->mac_stats.link_T4 = 0;
197944961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
198044961713Sgirish 	statsp->mac_stats.link_pause = 0;
198144961713Sgirish 	statsp->mac_stats.link_speed = 0;
198244961713Sgirish 	statsp->mac_stats.link_duplex = 0;
198344961713Sgirish 	statsp->mac_stats.link_up = 0;
198444961713Sgirish 
198544961713Sgirish 	/*
198644961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
198744961713Sgirish 	 */
198844961713Sgirish 	bmcr.value = 0;
198944961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
199044961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
199144961713Sgirish 		goto fail;
199244961713Sgirish 
199344961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
199444961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
199544961713Sgirish 		bmcr.bits.loopback = 1;
199644961713Sgirish 		bmcr.bits.enable_autoneg = 0;
199744961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
199844961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
199944961713Sgirish 		bmcr.bits.duplex_mode = 1;
200044961713Sgirish 		param_arr[param_autoneg].value = 0;
200144961713Sgirish 	} else {
200244961713Sgirish 		bmcr.bits.loopback = 0;
200344961713Sgirish 	}
200444961713Sgirish 
200544961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
200644961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
200744961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
200844961713Sgirish 		param_arr[param_autoneg].value = 0;
200944961713Sgirish 		bcm5464r_aux.value = 0;
201044961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
201144961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
201244961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
201344961713Sgirish 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
201444961713Sgirish 				!= NXGE_OK)
201544961713Sgirish 			goto fail;
201644961713Sgirish 	}
201744961713Sgirish 
201844961713Sgirish 	if (param_arr[param_autoneg].value) {
201944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
202044961713Sgirish 				"Restarting Auto-negotiation."));
202144961713Sgirish 		/*
202244961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
202344961713Sgirish 		 */
202444961713Sgirish 		anar.value = 0;
202544961713Sgirish 		anar.bits.selector = 1;
202644961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
202744961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
202844961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
202944961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
203044961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
203144961713Sgirish 		anar.bits.cap_asmpause = 0;
203244961713Sgirish 		anar.bits.cap_pause = 0;
203344961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
203444961713Sgirish 			param_arr[param_anar_100fdx].value ||
203544961713Sgirish 			param_arr[param_anar_10fdx].value) {
203644961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
203744961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
203844961713Sgirish 		}
203944961713Sgirish 
204044961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
204144961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
204244961713Sgirish 				!= NXGE_OK)
204344961713Sgirish 			goto fail;
204444961713Sgirish 		if (bmsr.bits.extend_status) {
204544961713Sgirish 			gcr.value = 0;
204644961713Sgirish 			gcr.bits.ms_mode_en =
204744961713Sgirish 				param_arr[param_master_cfg_enable].value;
204844961713Sgirish 			gcr.bits.master =
204944961713Sgirish 				param_arr[param_master_cfg_value].value;
205044961713Sgirish 			gcr.bits.link_1000fdx =
205144961713Sgirish 				param_arr[param_anar_1000fdx].value;
205244961713Sgirish 			gcr.bits.link_1000hdx =
205344961713Sgirish 				param_arr[param_anar_1000hdx].value;
205444961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
205544961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
205644961713Sgirish 				!= NXGE_OK)
205744961713Sgirish 				goto fail;
205844961713Sgirish 		}
205944961713Sgirish 
206044961713Sgirish 		bmcr.bits.enable_autoneg = 1;
206144961713Sgirish 		bmcr.bits.restart_autoneg = 1;
206244961713Sgirish 
206344961713Sgirish 	} else {
206444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
206544961713Sgirish 		bmcr.bits.speed_1000_sel =
206644961713Sgirish 			param_arr[param_anar_1000fdx].value |
206744961713Sgirish 				param_arr[param_anar_1000hdx].value;
206844961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
206944961713Sgirish 			(param_arr[param_anar_100fdx].value |
207044961713Sgirish 				param_arr[param_anar_100hdx].value);
207144961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
207244961713Sgirish 			statsp->mac_stats.link_speed = 1000;
207344961713Sgirish 			gcr.value = 0;
207444961713Sgirish 			gcr.bits.ms_mode_en =
207544961713Sgirish 				param_arr[param_master_cfg_enable].value;
207644961713Sgirish 			gcr.bits.master =
207744961713Sgirish 				param_arr[param_master_cfg_value].value;
207844961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
207944961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr),
208044961713Sgirish 				gcr.value))
208144961713Sgirish 				!= NXGE_OK)
208244961713Sgirish 				goto fail;
208344961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
208444961713Sgirish 				bmcr.bits.duplex_mode = 1;
208544961713Sgirish 				statsp->mac_stats.link_duplex = 2;
208644961713Sgirish 			} else
208744961713Sgirish 				statsp->mac_stats.link_duplex = 1;
208844961713Sgirish 		} else if (bmcr.bits.speed_sel) {
208944961713Sgirish 			statsp->mac_stats.link_speed = 100;
209044961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
209144961713Sgirish 				bmcr.bits.duplex_mode = 1;
209244961713Sgirish 				statsp->mac_stats.link_duplex = 2;
209344961713Sgirish 			} else
209444961713Sgirish 				statsp->mac_stats.link_duplex = 1;
209544961713Sgirish 		} else {
209644961713Sgirish 			statsp->mac_stats.link_speed = 10;
209744961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
209844961713Sgirish 				bmcr.bits.duplex_mode = 1;
209944961713Sgirish 				statsp->mac_stats.link_duplex = 2;
210044961713Sgirish 			} else
210144961713Sgirish 				statsp->mac_stats.link_duplex = 1;
210244961713Sgirish 		}
210344961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
210444961713Sgirish 			statsp->mac_stats.link_asmpause =
210544961713Sgirish 						statsp->mac_stats.cap_asmpause;
210644961713Sgirish 			statsp->mac_stats.link_pause =
210744961713Sgirish 						statsp->mac_stats.cap_pause;
210844961713Sgirish 		}
210944961713Sgirish 
211044961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
211144961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
211244961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
211344961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
211444961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
211544961713Sgirish 				gcr.value = 0;
211644961713Sgirish 				gcr.bits.ms_mode_en = 1;
211744961713Sgirish 				gcr.bits.master = 1;
211844961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
211944961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gcr),
212044961713Sgirish 					gcr.value))
212144961713Sgirish 					!= NXGE_OK)
212244961713Sgirish 					goto fail;
212344961713Sgirish 				bmcr.value = 0;
212444961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
212544961713Sgirish 				statsp->mac_stats.link_speed = 1000;
212644961713Sgirish 			} else if (statsp->port_stats.lb_mode
212744961713Sgirish 			    == nxge_lb_ext100) {
212844961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
212944961713Sgirish 				bmcr.value = 0;
213044961713Sgirish 				bmcr.bits.speed_sel = 1;
213144961713Sgirish 				bmcr.bits.duplex_mode = 1;
213244961713Sgirish 				statsp->mac_stats.link_speed = 100;
213344961713Sgirish 			} else if (statsp->port_stats.lb_mode
213444961713Sgirish 			    == nxge_lb_ext10) {
213544961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
213644961713Sgirish 				bmcr.value = 0;
213744961713Sgirish 				bmcr.bits.duplex_mode = 1;
213844961713Sgirish 				statsp->mac_stats.link_speed = 10;
213944961713Sgirish 			}
214044961713Sgirish 		}
214144961713Sgirish 	}
214244961713Sgirish 
214344961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
214444961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
214544961713Sgirish 			bmcr.value)) != NXGE_OK)
214644961713Sgirish 		goto fail;
214744961713Sgirish 
214844961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
214944961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
215044961713Sgirish 		goto fail;
215144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
215244961713Sgirish 
215344961713Sgirish 	/*
215444961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
215544961713Sgirish 	 */
215644961713Sgirish 	nxgep->soft_bmsr.value = 0;
215744961713Sgirish 
215844961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
215944961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
216044961713Sgirish 			&nxgep->bmsr.value)) != NXGE_OK)
216144961713Sgirish 		goto fail;
216244961713Sgirish 
216344961713Sgirish 	statsp->mac_stats.xcvr_inits++;
216444961713Sgirish 	nxgep->bmsr.value = 0;
216544961713Sgirish 
216644961713Sgirish fail:
216744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
216844961713Sgirish 			"<== nxge_mii_xcvr_init status 0x%x", status));
216944961713Sgirish 	return (status);
217044961713Sgirish }
217144961713Sgirish 
217244961713Sgirish /* Read from a MII compliant register */
217344961713Sgirish 
217444961713Sgirish nxge_status_t
217544961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
217644961713Sgirish 		uint16_t *value)
217744961713Sgirish {
217844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
217944961713Sgirish 
218044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
218144961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
218244961713Sgirish 
218344961713Sgirish 	MUTEX_ENTER(&nxge_mii_lock);
218444961713Sgirish 
218544961713Sgirish 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
218644961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
218744961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
218844961713Sgirish 			goto fail;
218944961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
219044961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
219144961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
219244961713Sgirish 			goto fail;
219344961713Sgirish 	} else
219444961713Sgirish 		goto fail;
219544961713Sgirish 
219644961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
219744961713Sgirish 
219844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
219944961713Sgirish 			"xcvr_reg<%d> value=0x%x",
220044961713Sgirish 			xcvr_portn, xcvr_reg, *value));
220144961713Sgirish 	return (NXGE_OK);
220244961713Sgirish fail:
220344961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
220444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
220544961713Sgirish 			"nxge_mii_read: Failed to read mii on xcvr %d",
220644961713Sgirish 			xcvr_portn));
220744961713Sgirish 
220844961713Sgirish 	return (NXGE_ERROR | rs);
220944961713Sgirish }
221044961713Sgirish 
221144961713Sgirish /* Write to a MII compliant Register */
221244961713Sgirish 
221344961713Sgirish nxge_status_t
221444961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
221544961713Sgirish 		uint16_t value)
221644961713Sgirish {
221744961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
221844961713Sgirish 
221944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
222044961713Sgirish 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
222144961713Sgirish 			value));
222244961713Sgirish 
222344961713Sgirish 	MUTEX_ENTER(&nxge_mii_lock);
222444961713Sgirish 
222544961713Sgirish 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
222644961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
222744961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
222844961713Sgirish 			goto fail;
222944961713Sgirish 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
223044961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
223144961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
223244961713Sgirish 			goto fail;
223344961713Sgirish 	} else
223444961713Sgirish 		goto fail;
223544961713Sgirish 
223644961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
223744961713Sgirish 
223844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
223944961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
224044961713Sgirish 	return (NXGE_OK);
224144961713Sgirish fail:
224244961713Sgirish 	MUTEX_EXIT(&nxge_mii_lock);
224344961713Sgirish 
224444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
224544961713Sgirish 			"nxge_mii_write: Failed to write mii on xcvr %d",
224644961713Sgirish 			xcvr_portn));
224744961713Sgirish 
224844961713Sgirish 	return (NXGE_ERROR | rs);
224944961713Sgirish }
225044961713Sgirish 
225144961713Sgirish /* Perform read from Clause45 serdes / transceiver device */
225244961713Sgirish 
225344961713Sgirish nxge_status_t
225444961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
225544961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
225644961713Sgirish {
225744961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
225844961713Sgirish 
225944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
226044961713Sgirish 			xcvr_portn));
226144961713Sgirish 
226244961713Sgirish 	MUTEX_ENTER(&nxge_mdio_lock);
226344961713Sgirish 
226444961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
226544961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
226644961713Sgirish 		goto fail;
226744961713Sgirish 
226844961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
226944961713Sgirish 
227044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
227144961713Sgirish 			xcvr_portn));
227244961713Sgirish 	return (NXGE_OK);
227344961713Sgirish fail:
227444961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
227544961713Sgirish 
227644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
227744961713Sgirish 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
227844961713Sgirish 			xcvr_portn));
227944961713Sgirish 
228044961713Sgirish 	return (NXGE_ERROR | rs);
228144961713Sgirish }
228244961713Sgirish 
228344961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
228444961713Sgirish 
228544961713Sgirish nxge_status_t
228644961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
228744961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
228844961713Sgirish {
228944961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
229044961713Sgirish 
229144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
229244961713Sgirish 			xcvr_portn));
229344961713Sgirish 
229444961713Sgirish 	MUTEX_ENTER(&nxge_mdio_lock);
229544961713Sgirish 
229644961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
229744961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
229844961713Sgirish 		goto fail;
229944961713Sgirish 
230044961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
230144961713Sgirish 
230244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
230344961713Sgirish 			xcvr_portn));
230444961713Sgirish 	return (NXGE_OK);
230544961713Sgirish fail:
230644961713Sgirish 	MUTEX_EXIT(&nxge_mdio_lock);
230744961713Sgirish 
230844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
230944961713Sgirish 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
231044961713Sgirish 			xcvr_portn));
231144961713Sgirish 
231244961713Sgirish 	return (NXGE_ERROR | rs);
231344961713Sgirish }
231444961713Sgirish 
231544961713Sgirish 
231644961713Sgirish /* Check MII to see if there is any link status change */
231744961713Sgirish 
231844961713Sgirish nxge_status_t
2319a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
2320a3c5bd6dSspeer 		nxge_link_state_t *link_up)
232144961713Sgirish {
232244961713Sgirish 	p_nxge_param_t	param_arr;
232344961713Sgirish 	p_nxge_stats_t	statsp;
232444961713Sgirish 	p_mii_regs_t	mii_regs;
232544961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
232644961713Sgirish 	mii_anar_t	anar;
232744961713Sgirish 	mii_anlpar_t	anlpar;
232844961713Sgirish 	mii_anar_t	an_common;
232944961713Sgirish 	mii_aner_t	aner;
233044961713Sgirish 	mii_gsr_t	gsr;
233144961713Sgirish 	nxge_status_t	status = NXGE_OK;
233244961713Sgirish 
233344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
233444961713Sgirish 
233544961713Sgirish 	mii_regs = NULL;
233644961713Sgirish 	param_arr = nxgep->param_arr;
233744961713Sgirish 	statsp = nxgep->statsp;
233844961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
2339a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
234044961713Sgirish 
234144961713Sgirish 	if (bmsr_ints.bits.link_status) {
234244961713Sgirish 		if (bmsr.bits.link_status) {
234344961713Sgirish 			soft_bmsr->bits.link_status = 1;
234444961713Sgirish 		} else {
234544961713Sgirish 			statsp->mac_stats.link_up = 0;
234644961713Sgirish 			soft_bmsr->bits.link_status = 0;
234744961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
234844961713Sgirish 					"Link down cable problem"));
2349a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
235044961713Sgirish 		}
235144961713Sgirish 	}
235244961713Sgirish 
235344961713Sgirish 	if (param_arr[param_autoneg].value) {
235444961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
235544961713Sgirish 			if (bmsr.bits.auto_neg_complete)
235644961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
235744961713Sgirish 			else
235844961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
235944961713Sgirish 		}
236044961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
236144961713Sgirish 			statsp->mac_stats.link_T4 = 0;
236244961713Sgirish 			statsp->mac_stats.link_speed = 0;
236344961713Sgirish 			statsp->mac_stats.link_duplex = 0;
236444961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
236544961713Sgirish 			statsp->mac_stats.link_pause = 0;
236644961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
236744961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
236844961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
236944961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
237044961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
237144961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
237244961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
237344961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
237444961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
237544961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
237644961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
237744961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
237844961713Sgirish 		}
237944961713Sgirish 	} else
238044961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
238144961713Sgirish 
238244961713Sgirish 	if ((bmsr_ints.bits.link_status ||
238344961713Sgirish 		bmsr_ints.bits.auto_neg_complete) &&
238444961713Sgirish 		soft_bmsr->bits.link_status &&
238544961713Sgirish 		soft_bmsr->bits.auto_neg_complete) {
238644961713Sgirish 		statsp->mac_stats.link_up = 1;
238744961713Sgirish 		if (param_arr[param_autoneg].value) {
238844961713Sgirish 			if ((status = nxge_mii_read(nxgep,
238944961713Sgirish 				statsp->mac_stats.xcvr_portn,
239044961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anar),
239144961713Sgirish 					&anar.value)) != NXGE_OK)
239244961713Sgirish 				goto fail;
239344961713Sgirish 			if ((status = nxge_mii_read(nxgep,
239444961713Sgirish 				statsp->mac_stats.xcvr_portn,
239544961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
239644961713Sgirish 					&anlpar.value)) != NXGE_OK)
239744961713Sgirish 				goto fail;
239844961713Sgirish 			if ((status = nxge_mii_read(nxgep,
239944961713Sgirish 				statsp->mac_stats.xcvr_portn,
240044961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->aner),
240144961713Sgirish 					&aner.value)) != NXGE_OK)
240244961713Sgirish 				goto fail;
240344961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
240444961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
240544961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
240644961713Sgirish 							anlpar.bits.cap_100fdx;
240744961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
240844961713Sgirish 							anlpar.bits.cap_100hdx;
240944961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
241044961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
241144961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
241244961713Sgirish 						anlpar.bits.cap_asmpause;
241344961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
241444961713Sgirish 			an_common.value = anar.value & anlpar.value;
241544961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
241644961713Sgirish 				param_arr[param_anar_1000hdx].value) {
241744961713Sgirish 				if ((status = nxge_mii_read(nxgep,
241844961713Sgirish 					statsp->mac_stats.xcvr_portn,
241944961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gsr),
242044961713Sgirish 						&gsr.value))
242144961713Sgirish 						!= NXGE_OK)
242244961713Sgirish 					goto fail;
242344961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
242444961713Sgirish 					gsr.bits.link_1000fdx;
242544961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
242644961713Sgirish 					gsr.bits.link_1000hdx;
242744961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
242844961713Sgirish 					gsr.bits.link_1000fdx) {
242944961713Sgirish 					statsp->mac_stats.link_speed = 1000;
243044961713Sgirish 					statsp->mac_stats.link_duplex = 2;
243144961713Sgirish 				} else if (
243244961713Sgirish 					param_arr[param_anar_1000hdx].value &&
243344961713Sgirish 						gsr.bits.link_1000hdx) {
243444961713Sgirish 					statsp->mac_stats.link_speed = 1000;
243544961713Sgirish 					statsp->mac_stats.link_duplex = 1;
243644961713Sgirish 				}
243744961713Sgirish 			}
243844961713Sgirish 			if ((an_common.value != 0) &&
243944961713Sgirish 					!(statsp->mac_stats.link_speed)) {
244044961713Sgirish 				if (an_common.bits.cap_100T4) {
244144961713Sgirish 					statsp->mac_stats.link_T4 = 1;
244244961713Sgirish 					statsp->mac_stats.link_speed = 100;
244344961713Sgirish 					statsp->mac_stats.link_duplex = 1;
244444961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
244544961713Sgirish 					statsp->mac_stats.link_speed = 100;
244644961713Sgirish 					statsp->mac_stats.link_duplex = 2;
244744961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
244844961713Sgirish 					statsp->mac_stats.link_speed = 100;
244944961713Sgirish 					statsp->mac_stats.link_duplex = 1;
245044961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
245144961713Sgirish 					statsp->mac_stats.link_speed = 10;
245244961713Sgirish 					statsp->mac_stats.link_duplex = 2;
245344961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
245444961713Sgirish 					statsp->mac_stats.link_speed = 10;
245544961713Sgirish 					statsp->mac_stats.link_duplex = 1;
245644961713Sgirish 				} else {
245744961713Sgirish 					goto fail;
245844961713Sgirish 				}
245944961713Sgirish 			}
246044961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
246144961713Sgirish 				statsp->mac_stats.link_asmpause =
246244961713Sgirish 					an_common.bits.cap_asmpause;
246344961713Sgirish 				if (statsp->mac_stats.link_asmpause)
246444961713Sgirish 				if ((statsp->mac_stats.cap_pause == 0) &&
246544961713Sgirish 						(statsp->mac_stats.lp_cap_pause
246644961713Sgirish 						== 1))
246744961713Sgirish 						statsp->mac_stats.link_pause
246844961713Sgirish 						= 0;
246944961713Sgirish 					else
247044961713Sgirish 						statsp->mac_stats.link_pause
247144961713Sgirish 						= 1;
247244961713Sgirish 				else
247344961713Sgirish 					statsp->mac_stats.link_pause =
247444961713Sgirish 						an_common.bits.cap_pause;
247544961713Sgirish 			}
247644961713Sgirish 		}
2477a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
2478a3c5bd6dSspeer 	}
2479a3c5bd6dSspeer 
2480a3c5bd6dSspeer 	if (nxgep->link_notify) {
2481a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
2482a3c5bd6dSspeer 				LINK_IS_DOWN);
2483a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
248444961713Sgirish 	}
248544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
248644961713Sgirish 	return (NXGE_OK);
248744961713Sgirish fail:
248844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
248944961713Sgirish 			"nxge_mii_check: Unable to check MII"));
249044961713Sgirish 	return (status);
249144961713Sgirish }
249244961713Sgirish 
249344961713Sgirish /* Add a multicast address entry into the HW hash table */
249444961713Sgirish 
249544961713Sgirish nxge_status_t
249644961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
249744961713Sgirish {
249844961713Sgirish 	uint32_t mchash;
249944961713Sgirish 	p_hash_filter_t hash_filter;
250044961713Sgirish 	uint16_t hash_bit;
250144961713Sgirish 	boolean_t rx_init = B_FALSE;
250244961713Sgirish 	uint_t j;
250344961713Sgirish 	nxge_status_t status = NXGE_OK;
250444961713Sgirish 
250544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
250644961713Sgirish 
250744961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
250844961713Sgirish 	mchash = crc32_mchash(addrp);
250944961713Sgirish 	if (nxgep->hash_filter == NULL) {
251044961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
251144961713Sgirish 			"Allocating hash filter storage."));
251244961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
251344961713Sgirish 					KM_SLEEP);
251444961713Sgirish 	}
251544961713Sgirish 	hash_filter = nxgep->hash_filter;
251644961713Sgirish 	j = mchash / HASH_REG_WIDTH;
251744961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
251844961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
251944961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
252044961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
252144961713Sgirish 		hash_filter->hash_ref_cnt++;
252244961713Sgirish 		rx_init = B_TRUE;
252344961713Sgirish 	}
252444961713Sgirish 	if (rx_init) {
252544961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
252644961713Sgirish 			goto fail;
252744961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
252844961713Sgirish 			goto fail;
252944961713Sgirish 	}
253044961713Sgirish 
253144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
253244961713Sgirish 
253344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
253444961713Sgirish 
253544961713Sgirish 	return (NXGE_OK);
253644961713Sgirish fail:
253744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
253844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
253944961713Sgirish 					"Unable to add multicast address"));
254044961713Sgirish 	return (status);
254144961713Sgirish }
254244961713Sgirish 
254344961713Sgirish /* Remove a multicast address entry from the HW hash table */
254444961713Sgirish 
254544961713Sgirish nxge_status_t
254644961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
254744961713Sgirish {
254844961713Sgirish 	uint32_t mchash;
254944961713Sgirish 	p_hash_filter_t hash_filter;
255044961713Sgirish 	uint16_t hash_bit;
255144961713Sgirish 	boolean_t rx_init = B_FALSE;
255244961713Sgirish 	uint_t j;
255344961713Sgirish 	nxge_status_t status = NXGE_OK;
255444961713Sgirish 
255544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
255644961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
255744961713Sgirish 	mchash = crc32_mchash(addrp);
255844961713Sgirish 	if (nxgep->hash_filter == NULL) {
255944961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
256044961713Sgirish 			"Hash filter already de_allocated."));
256144961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
256244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
256344961713Sgirish 		return (NXGE_OK);
256444961713Sgirish 	}
256544961713Sgirish 	hash_filter = nxgep->hash_filter;
256644961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
256744961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
256844961713Sgirish 		j = mchash / HASH_REG_WIDTH;
256944961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
257044961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
257144961713Sgirish 		hash_filter->hash_ref_cnt--;
257244961713Sgirish 		rx_init = B_TRUE;
257344961713Sgirish 	}
257444961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
257544961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
257644961713Sgirish 			"De-allocating hash filter storage."));
257744961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
257844961713Sgirish 		nxgep->hash_filter = NULL;
257944961713Sgirish 	}
258044961713Sgirish 
258144961713Sgirish 	if (rx_init) {
258244961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
258344961713Sgirish 			goto fail;
258444961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
258544961713Sgirish 			goto fail;
258644961713Sgirish 	}
258744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
258844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
258944961713Sgirish 
259044961713Sgirish 	return (NXGE_OK);
259144961713Sgirish fail:
259244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
259344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
259444961713Sgirish 			"Unable to remove multicast address"));
259544961713Sgirish 
259644961713Sgirish 	return (status);
259744961713Sgirish }
259844961713Sgirish 
259944961713Sgirish /* Set MAC address into MAC address HW registers */
260044961713Sgirish 
260144961713Sgirish nxge_status_t
260244961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
260344961713Sgirish {
260444961713Sgirish 	nxge_status_t status = NXGE_OK;
260544961713Sgirish 
260644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
260744961713Sgirish 
260844961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
260944961713Sgirish 	/*
261044961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
261144961713Sgirish 	 */
261244961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
261344961713Sgirish 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
261444961713Sgirish 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
261544961713Sgirish 		goto nxge_set_mac_addr_exit;
261644961713Sgirish 	}
261744961713Sgirish 	nxgep->ouraddr = *addrp;
261844961713Sgirish 	/*
261944961713Sgirish 	 * Set new interface local address and re-init device.
262044961713Sgirish 	 * This is destructive to any other streams attached
262144961713Sgirish 	 * to this device.
262244961713Sgirish 	 */
262344961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
262444961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
262544961713Sgirish 		goto fail;
262644961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
262744961713Sgirish 		goto fail;
262844961713Sgirish 
262944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
263044961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
263144961713Sgirish 	goto nxge_set_mac_addr_end;
263244961713Sgirish nxge_set_mac_addr_exit:
263344961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
263444961713Sgirish nxge_set_mac_addr_end:
263544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
263644961713Sgirish 
263744961713Sgirish 	return (NXGE_OK);
263844961713Sgirish fail:
263944961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
264044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
264144961713Sgirish 			"Unable to set mac address"));
264244961713Sgirish 	return (status);
264344961713Sgirish }
264444961713Sgirish 
264598ecde52Stm static
264698ecde52Stm check_link_state_t
264798ecde52Stm nxge_check_link_stop(
264898ecde52Stm 	nxge_t *nxge)
264998ecde52Stm {
265098ecde52Stm 	/* If the poll has been cancelled, return STOP. */
265198ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
265298ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
265398ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
265498ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
265598ecde52Stm 		cv_broadcast(&nxge->poll_cv);
265698ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
265798ecde52Stm 
265898ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
265998ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
266098ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
266198ecde52Stm 		    nxge->mac.portnum));
266298ecde52Stm 		return (CHECK_LINK_STOP);
266398ecde52Stm 	}
266498ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
266598ecde52Stm 
266698ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
266798ecde52Stm }
266898ecde52Stm 
266944961713Sgirish /* Check status of MII (MIF or PCS) link */
267044961713Sgirish 
2671*59ac0c16Sdavemq static nxge_status_t
267244961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
267344961713Sgirish {
267444961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
267544961713Sgirish 	mii_anlpar_t anlpar;
267644961713Sgirish 	mii_gsr_t gsr;
267744961713Sgirish 	p_mii_regs_t mii_regs;
267844961713Sgirish 	nxge_status_t status = NXGE_OK;
267944961713Sgirish 	uint8_t portn;
2680a3c5bd6dSspeer 	nxge_link_state_t link_up;
268144961713Sgirish 
268298ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
268398ecde52Stm 		return (NXGE_ERROR);
268498ecde52Stm 
268598ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
268698ecde52Stm 		return (NXGE_OK);
268798ecde52Stm 
268844961713Sgirish 	portn = nxgep->mac.portnum;
268944961713Sgirish 
269044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
269198ecde52Stm 	    portn));
269244961713Sgirish 
269344961713Sgirish 	mii_regs = NULL;
269444961713Sgirish 
269544961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
269644961713Sgirish 
269744961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
269844961713Sgirish 		goto nxge_check_mii_link_exit;
269944961713Sgirish 
270044961713Sgirish 	if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
270144961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
270244961713Sgirish 		&bmsr_data.value)) != NXGE_OK)
270344961713Sgirish 		goto fail;
270444961713Sgirish 
270544961713Sgirish 	if (nxgep->param_arr[param_autoneg].value) {
270644961713Sgirish 		if ((status = nxge_mii_read(nxgep,
270744961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn,
270844961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->gsr),
270944961713Sgirish 			&gsr.value)) != NXGE_OK)
271044961713Sgirish 			goto fail;
271144961713Sgirish 		if ((status = nxge_mii_read(nxgep,
271244961713Sgirish 			nxgep->statsp->mac_stats.xcvr_portn,
271344961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anlpar),
271444961713Sgirish 			&anlpar.value)) != NXGE_OK)
271544961713Sgirish 			goto fail;
271644961713Sgirish 		if (nxgep->statsp->mac_stats.link_up &&
271744961713Sgirish 			((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
271844961713Sgirish 				gsr.bits.link_1000fdx) ||
271944961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
272044961713Sgirish 				gsr.bits.link_1000hdx) ||
272144961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100T4 ^
272244961713Sgirish 				anlpar.bits.cap_100T4) ||
272344961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100fdx ^
272444961713Sgirish 				anlpar.bits.cap_100fdx) ||
272544961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_100hdx ^
272644961713Sgirish 				anlpar.bits.cap_100hdx) ||
272744961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_10fdx ^
272844961713Sgirish 				anlpar.bits.cap_10fdx) ||
272944961713Sgirish 			(nxgep->statsp->mac_stats.lp_cap_10hdx ^
273044961713Sgirish 				anlpar.bits.cap_10hdx))) {
273144961713Sgirish 			bmsr_data.bits.link_status = 0;
273244961713Sgirish 		}
273344961713Sgirish 	}
273444961713Sgirish 
273544961713Sgirish 	/* Workaround for link down issue */
273644961713Sgirish 	if (bmsr_data.value == 0) {
2737*59ac0c16Sdavemq 		cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n",
2738*59ac0c16Sdavemq 		    nxgep->instance);
273944961713Sgirish 		goto nxge_check_mii_link_exit;
274044961713Sgirish 	}
274144961713Sgirish 
274244961713Sgirish 	bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
274344961713Sgirish 	nxgep->bmsr.value = bmsr_data.value;
2744a3c5bd6dSspeer 	if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up))
274598ecde52Stm 	    != NXGE_OK)
274644961713Sgirish 		goto fail;
274744961713Sgirish 
274844961713Sgirish nxge_check_mii_link_exit:
274944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
2750a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
2751a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
2752a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
2753a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
2754a3c5bd6dSspeer 	}
275544961713Sgirish 
275644961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
275744961713Sgirish 
275844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
275998ecde52Stm 	    portn));
276044961713Sgirish 	return (NXGE_OK);
276144961713Sgirish 
276244961713Sgirish fail:
276344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
276444961713Sgirish 
276544961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
276644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
276798ecde52Stm 	    "nxge_check_mii_link: Failed to check link port<%d>",
276898ecde52Stm 	    portn));
276944961713Sgirish 	return (status);
277044961713Sgirish }
277144961713Sgirish 
277244961713Sgirish 
277344961713Sgirish /*ARGSUSED*/
2774*59ac0c16Sdavemq static nxge_status_t
277544961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
277644961713Sgirish {
277744961713Sgirish 	uint8_t		portn;
277814ea4bb7Ssd 
277944961713Sgirish 	nxge_status_t	status = NXGE_OK;
278044961713Sgirish 	boolean_t	link_up;
278144961713Sgirish 
278298ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
278398ecde52Stm 		return (NXGE_ERROR);
278498ecde52Stm 
278598ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
278698ecde52Stm 		return (NXGE_OK);
278798ecde52Stm 
278844961713Sgirish 	portn = nxgep->mac.portnum;
278944961713Sgirish 
279044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
279198ecde52Stm 	    portn));
279244961713Sgirish 
279344961713Sgirish 	status = nxge_check_bcm8704_link(nxgep, &link_up);
279444961713Sgirish 
279544961713Sgirish 	if (status != NXGE_OK)
279644961713Sgirish 		goto fail;
279744961713Sgirish 
279844961713Sgirish 	if (link_up) {
2799a3c5bd6dSspeer 		if (nxgep->link_notify ||
2800a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 0) {
280144961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
280244961713Sgirish 				goto fail;
280344961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
280444961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
280544961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
280644961713Sgirish 
280744961713Sgirish 			nxge_link_is_up(nxgep);
2808a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
280944961713Sgirish 		}
281044961713Sgirish 	} else {
2811a3c5bd6dSspeer 		if (nxgep->link_notify ||
2812a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 1) {
281344961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
281444961713Sgirish 				goto fail;
281544961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2816*59ac0c16Sdavemq 			    "Link down cable problem"));
281744961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
281844961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
281944961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
282044961713Sgirish 
282144961713Sgirish 			nxge_link_is_down(nxgep);
2822a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
282344961713Sgirish 		}
282444961713Sgirish 	}
282544961713Sgirish 
282644961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
282744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
282898ecde52Stm 	    portn));
282944961713Sgirish 	return (NXGE_OK);
283044961713Sgirish 
283144961713Sgirish fail:
283298ecde52Stm 	(void) nxge_check_link_stop(nxgep);
283398ecde52Stm 
283444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
283598ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
283698ecde52Stm 	    portn));
283744961713Sgirish 	return (status);
283844961713Sgirish }
283944961713Sgirish 
284044961713Sgirish 
284144961713Sgirish /* Declare link down */
284244961713Sgirish 
284344961713Sgirish void
284444961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
284544961713Sgirish {
2846*59ac0c16Sdavemq 	p_nxge_stats_t statsp;
2847*59ac0c16Sdavemq 	char link_stat_msg[64];
2848*59ac0c16Sdavemq 
284944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
285044961713Sgirish 
2851*59ac0c16Sdavemq 	statsp = nxgep->statsp;
2852*59ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
2853*59ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
2854*59ac0c16Sdavemq 
2855*59ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
2856*59ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2857*59ac0c16Sdavemq 	}
2858*59ac0c16Sdavemq 
285944961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
286044961713Sgirish 
286144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
286244961713Sgirish }
286344961713Sgirish 
286444961713Sgirish /* Declare link up */
286544961713Sgirish 
286644961713Sgirish void
286744961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
286844961713Sgirish {
2869*59ac0c16Sdavemq 	p_nxge_stats_t statsp;
2870*59ac0c16Sdavemq 	char link_stat_msg[64];
287144961713Sgirish 	uint32_t val;
287244961713Sgirish 
287344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
287444961713Sgirish 
2875*59ac0c16Sdavemq 	statsp = nxgep->statsp;
2876*59ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
2877*59ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
2878*59ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
2879*59ac0c16Sdavemq 
2880*59ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
2881*59ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
2882*59ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
2883*59ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
2884*59ac0c16Sdavemq 	else
2885*59ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
2886*59ac0c16Sdavemq 
288744961713Sgirish 	(void) nxge_xif_init(nxgep);
288844961713Sgirish 
288944961713Sgirish 	/* Clean up symbol errors incurred during link transition */
289044961713Sgirish 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
289144961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
289244961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
289344961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
289444961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
289544961713Sgirish 	}
289644961713Sgirish 
2897*59ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
2898*59ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2899*59ac0c16Sdavemq 	}
2900*59ac0c16Sdavemq 
290144961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
290244961713Sgirish 
290344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
290444961713Sgirish }
290544961713Sgirish 
290644961713Sgirish /*
290744961713Sgirish  * Calculate the bit in the multicast address filter
290844961713Sgirish  * that selects the given * address.
290944961713Sgirish  * Note: For GEM, the last 8-bits are used.
291044961713Sgirish  */
291144961713Sgirish uint32_t
291244961713Sgirish crc32_mchash(p_ether_addr_t addr)
291344961713Sgirish {
291444961713Sgirish 	uint8_t *cp;
291544961713Sgirish 	uint32_t crc;
291644961713Sgirish 	uint32_t c;
291744961713Sgirish 	int byte;
291844961713Sgirish 	int bit;
291944961713Sgirish 
292044961713Sgirish 	cp = (uint8_t *)addr;
292144961713Sgirish 	crc = (uint32_t)0xffffffff;
292244961713Sgirish 	for (byte = 0; byte < 6; byte++) {
292344961713Sgirish 		c = (uint32_t)cp[byte];
292444961713Sgirish 		for (bit = 0; bit < 8; bit++) {
292544961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
292644961713Sgirish 				crc = (crc >> 1)^0xedb88320;
292744961713Sgirish 			else
292844961713Sgirish 				crc = (crc >> 1);
292944961713Sgirish 			c >>= 1;
293044961713Sgirish 		}
293144961713Sgirish 	}
293244961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
293344961713Sgirish }
293444961713Sgirish 
293544961713Sgirish /* Reset serdes */
293644961713Sgirish 
293744961713Sgirish nxge_status_t
293844961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
293944961713Sgirish {
294044961713Sgirish 	npi_handle_t		handle;
294144961713Sgirish 
294244961713Sgirish 	handle = nxgep->npi_handle;
294344961713Sgirish 
294444961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
294544961713Sgirish 	drv_usecwait(500);
294644961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
294744961713Sgirish 
294844961713Sgirish 	return (NXGE_OK);
294944961713Sgirish }
295044961713Sgirish 
295144961713Sgirish /* Monitor link status using interrupt or polling */
295244961713Sgirish 
295344961713Sgirish nxge_status_t
295444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
295544961713Sgirish {
295644961713Sgirish 	nxge_status_t status = NXGE_OK;
295744961713Sgirish 
295844961713Sgirish 	/*
295998ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
296098ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
296144961713Sgirish 	 */
296244961713Sgirish 	if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
296344961713Sgirish 		return (NXGE_OK);
296444961713Sgirish 
296544961713Sgirish 	if (nxgep->statsp == NULL) {
296644961713Sgirish 		/* stats has not been allocated. */
296744961713Sgirish 		return (NXGE_OK);
296844961713Sgirish 	}
296944961713Sgirish 	/* Don't check link if we're not in internal loopback mode */
297044961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
297144961713Sgirish 		return (NXGE_OK);
297244961713Sgirish 
297344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
297498ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
297598ecde52Stm 	    nxgep->mac.portnum, enable));
297644961713Sgirish 	if (enable == LINK_MONITOR_START) {
297744961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
297844961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
297998ecde52Stm 			    != NXGE_OK)
298044961713Sgirish 				goto fail;
298144961713Sgirish 		} else {
298298ecde52Stm 			timeout_id_t timerid;
298398ecde52Stm 
298498ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
298598ecde52Stm 				return (NXGE_OK);
298698ecde52Stm 
2987*59ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
2988*59ac0c16Sdavemq 				timerid = timeout(
2989*59ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
299098ecde52Stm 				    nxgep,
299198ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
2992*59ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
2993*59ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
2994*59ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
2995*59ac0c16Sdavemq 			} else {
299698ecde52Stm 				return (NXGE_ERROR);
299744961713Sgirish 			}
299844961713Sgirish 		}
299944961713Sgirish 	} else {
300044961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
300144961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
300298ecde52Stm 			    != NXGE_OK)
300344961713Sgirish 				goto fail;
300444961713Sgirish 		} else {
300598ecde52Stm 			clock_t rv;
300698ecde52Stm 
300798ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
300898ecde52Stm 
300998ecde52Stm 			/* If <timerid> == 0, the link monitor has */
301098ecde52Stm 			/* never been started, or just now stopped. */
301198ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
301298ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
301398ecde52Stm 				return (NXGE_OK);
301498ecde52Stm 			}
301598ecde52Stm 
301698ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
301798ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
301898ecde52Stm 			    &nxgep->poll_lock,
301998ecde52Stm 			    ddi_get_lbolt() +
302098ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
302198ecde52Stm 			    LINK_MONITOR_PERIOD));
302298ecde52Stm 			if (rv == -1) {
302398ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
302498ecde52Stm 				    "==> stopping port %d: "
302598ecde52Stm 				    "cv_timedwait(%d) timed out",
302698ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
302798ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
302844961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
302944961713Sgirish 			}
303098ecde52Stm 
303198ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
303244961713Sgirish 		}
303344961713Sgirish 	}
303444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
303598ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
303698ecde52Stm 	    nxgep->mac.portnum, enable));
303744961713Sgirish 	return (NXGE_OK);
303844961713Sgirish fail:
303944961713Sgirish 	return (status);
304044961713Sgirish }
304144961713Sgirish 
304244961713Sgirish /* Set promiscous mode */
304344961713Sgirish 
304444961713Sgirish nxge_status_t
304544961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
304644961713Sgirish {
304744961713Sgirish 	nxge_status_t status = NXGE_OK;
304844961713Sgirish 
3049*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
305044961713Sgirish 
305144961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
305244961713Sgirish 
305344961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
305444961713Sgirish 
305544961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
305644961713Sgirish 		goto fail;
305744961713Sgirish 	}
305844961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
305944961713Sgirish 		goto fail;
306044961713Sgirish 	}
306144961713Sgirish 
306244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
306344961713Sgirish 
306444961713Sgirish 	if (on)
306544961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
306644961713Sgirish 	else
306744961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
306844961713Sgirish 
306944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
307044961713Sgirish 
307144961713Sgirish 	return (NXGE_OK);
307244961713Sgirish fail:
307344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
307444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
3075*59ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
307644961713Sgirish 
307744961713Sgirish 	return (status);
307844961713Sgirish }
307944961713Sgirish 
308044961713Sgirish /*ARGSUSED*/
308144961713Sgirish uint_t
308244961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
308344961713Sgirish {
308444961713Sgirish #ifdef	NXGE_DEBUG
308544961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
308644961713Sgirish #endif
308744961713Sgirish #if NXGE_MIF
308844961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
308944961713Sgirish 	uint32_t		status;
309044961713Sgirish 	npi_handle_t		handle;
309144961713Sgirish 	uint8_t			portn;
309244961713Sgirish 	p_nxge_stats_t		statsp;
309344961713Sgirish #endif
309444961713Sgirish 
309544961713Sgirish #ifdef	NXGE_MIF
309644961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
309744961713Sgirish 		nxgep = ldvp->nxgep;
309844961713Sgirish 	}
309944961713Sgirish 	nxgep = ldvp->nxgep;
310044961713Sgirish #endif
310144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
310244961713Sgirish 
310344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
310444961713Sgirish 	return (DDI_INTR_CLAIMED);
310544961713Sgirish 
310644961713Sgirish mif_intr_fail:
310744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
310844961713Sgirish 	return (DDI_INTR_UNCLAIMED);
310944961713Sgirish }
311044961713Sgirish 
311144961713Sgirish /*ARGSUSED*/
311244961713Sgirish uint_t
311344961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
311444961713Sgirish {
311544961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
311644961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
311744961713Sgirish 	p_nxge_ldg_t		ldgp;
311844961713Sgirish 	uint32_t		status;
311944961713Sgirish 	npi_handle_t		handle;
312044961713Sgirish 	uint8_t			portn;
312144961713Sgirish 	p_nxge_stats_t		statsp;
312244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
312344961713Sgirish 
312444961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
312544961713Sgirish 		nxgep = ldvp->nxgep;
312644961713Sgirish 	}
312744961713Sgirish 
312844961713Sgirish 	ldgp = ldvp->ldgp;
312944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
3130*59ac0c16Sdavemq 	    "group %d", ldgp->ldg));
313144961713Sgirish 
313244961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
313344961713Sgirish 	/*
313444961713Sgirish 	 * This interrupt handler is for a specific
313544961713Sgirish 	 * mac port.
313644961713Sgirish 	 */
313744961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
313844961713Sgirish 	portn = nxgep->mac.portnum;
313944961713Sgirish 
314044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3141*59ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
314244961713Sgirish 
314344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
314444961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
314544961713Sgirish 					(xmac_tx_iconfig_t *)&status);
314644961713Sgirish 		if (rs != NPI_SUCCESS)
314744961713Sgirish 			goto npi_fail;
314844961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
314944961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
315044961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
315144961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
315244961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
315344961713Sgirish 			}
315444961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
315544961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
315644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
315744961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
315844961713Sgirish 			}
315944961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
316044961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
316144961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
316244961713Sgirish 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
316344961713Sgirish 			}
316444961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
316544961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
316644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
316744961713Sgirish 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
316844961713Sgirish 			}
316944961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
317044961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
317144961713Sgirish 							XTXMAC_BYTE_CNT_MASK;
317244961713Sgirish 			}
317344961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
317444961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
317544961713Sgirish 							XTXMAC_FRM_CNT_MASK;
317644961713Sgirish 			}
317744961713Sgirish 		}
317844961713Sgirish 
317944961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
318044961713Sgirish 					(xmac_rx_iconfig_t *)&status);
318144961713Sgirish 		if (rs != NPI_SUCCESS)
318244961713Sgirish 			goto npi_fail;
318344961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
318444961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
318544961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
318644961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
318744961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
318844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
318944961713Sgirish 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
319044961713Sgirish 			}
319144961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
319244961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
319344961713Sgirish 							XRXMAC_CRC_ER_CNT_MASK;
319444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
319544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
319644961713Sgirish 			}
319744961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
319844961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
319944961713Sgirish 							MAC_LEN_ER_CNT_MASK;
320044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
320144961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
320244961713Sgirish 			}
320344961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
320444961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
320544961713Sgirish 							XRXMAC_CD_VIO_CNT_MASK;
320644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
320744961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
320844961713Sgirish 			}
320944961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
321044961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
321144961713Sgirish 							XRXMAC_BT_CNT_MASK;
321244961713Sgirish 			}
321344961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
321444961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
321544961713Sgirish 							XRXMAC_HIST_CNT1_MASK;
321644961713Sgirish 			}
321744961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
321844961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
321944961713Sgirish 							XRXMAC_HIST_CNT2_MASK;
322044961713Sgirish 			}
322144961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
322244961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
322344961713Sgirish 							XRXMAC_HIST_CNT3_MASK;
322444961713Sgirish 			}
322544961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
322644961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
322744961713Sgirish 							XRXMAC_HIST_CNT4_MASK;
322844961713Sgirish 			}
322944961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
323044961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
323144961713Sgirish 							XRXMAC_HIST_CNT5_MASK;
323244961713Sgirish 			}
323344961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
323444961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
323544961713Sgirish 							XRXMAC_HIST_CNT6_MASK;
323644961713Sgirish 			}
323744961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
323844961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
323944961713Sgirish 							XRXMAC_BC_FRM_CNT_MASK;
324044961713Sgirish 			}
324144961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
324244961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
324344961713Sgirish 							XRXMAC_MC_FRM_CNT_MASK;
324444961713Sgirish 			}
324544961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
324644961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
324744961713Sgirish 							XRXMAC_FRAG_CNT_MASK;
324844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
324944961713Sgirish 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
325044961713Sgirish 			}
325144961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
325244961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
325344961713Sgirish 							XRXMAC_AL_ER_CNT_MASK;
325444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
325544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
325644961713Sgirish 			}
325744961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
325844961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
325944961713Sgirish 							XMAC_LINK_FLT_CNT_MASK;
326044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
326144961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
326244961713Sgirish 			}
326344961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
326444961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
326544961713Sgirish 			}
326644961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
326744961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
326844961713Sgirish 			}
326944961713Sgirish 		}
327044961713Sgirish 
327144961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
327244961713Sgirish 						(xmac_ctl_iconfig_t *)&status);
327344961713Sgirish 		if (rs != NPI_SUCCESS)
327444961713Sgirish 			goto npi_fail;
327544961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
327644961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
327744961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
327844961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
327944961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
328044961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
328144961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
328244961713Sgirish 		}
328344961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
328444961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
328544961713Sgirish 						(bmac_tx_iconfig_t *)&status);
328644961713Sgirish 		if (rs != NPI_SUCCESS)
328744961713Sgirish 			goto npi_fail;
328844961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
328944961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
329044961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
329144961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
329244961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
329344961713Sgirish 			}
329444961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
329544961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
329644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
329744961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
329844961713Sgirish 			}
329944961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
330044961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
330144961713Sgirish 							BTXMAC_BYTE_CNT_MASK;
330244961713Sgirish 			}
330344961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
330444961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
330544961713Sgirish 							BTXMAC_FRM_CNT_MASK;
330644961713Sgirish 			}
330744961713Sgirish 		}
330844961713Sgirish 
330944961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
331044961713Sgirish 						(bmac_rx_iconfig_t *)&status);
331144961713Sgirish 		if (rs != NPI_SUCCESS)
331244961713Sgirish 			goto npi_fail;
331344961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
331444961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
331544961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
331644961713Sgirish 			}
331744961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
331844961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
331944961713Sgirish 							RXMAC_FRM_CNT_MASK;
332044961713Sgirish 			}
332144961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
332244961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
332344961713Sgirish 							BMAC_CRC_ER_CNT_MASK;
332444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
332544961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
332644961713Sgirish 			}
332744961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
332844961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
332944961713Sgirish 							MAC_LEN_ER_CNT_MASK;
333044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
333144961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
333244961713Sgirish 			}
333344961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
333444961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
333544961713Sgirish 							BMAC_CD_VIO_CNT_MASK;
333644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
333744961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
333844961713Sgirish 			}
333944961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
334044961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
334144961713Sgirish 							BRXMAC_BYTE_CNT_MASK;
334244961713Sgirish 			}
334344961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
334444961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
334544961713Sgirish 							BMAC_AL_ER_CNT_MASK;
334644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
334744961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
334844961713Sgirish 			}
334944961713Sgirish 
335044961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
335144961713Sgirish 						(bmac_ctl_iconfig_t *)&status);
335244961713Sgirish 			if (rs != NPI_SUCCESS)
335344961713Sgirish 				goto npi_fail;
335444961713Sgirish 
335544961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
335644961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
335744961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
335844961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
335944961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
336044961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
336144961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
336244961713Sgirish 			}
336344961713Sgirish 		}
336444961713Sgirish 
336544961713Sgirish 	if (ldgp->nldvs == 1) {
336644961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
336744961713Sgirish 			B_TRUE, ldgp->ldg_timer);
336844961713Sgirish 	}
336944961713Sgirish 
337044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
337144961713Sgirish 	return (DDI_INTR_CLAIMED);
337244961713Sgirish 
337344961713Sgirish npi_fail:
337444961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
337544961713Sgirish 	return (DDI_INTR_UNCLAIMED);
337644961713Sgirish }
337744961713Sgirish 
337844961713Sgirish nxge_status_t
337944961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
338044961713Sgirish {
338144961713Sgirish 	uint8_t		phy_port_addr;
338244961713Sgirish 	nxge_status_t	status = NXGE_OK;
338344961713Sgirish 	boolean_t	rx_sig_ok;
338444961713Sgirish 	boolean_t	pcs_blk_lock;
338544961713Sgirish 	boolean_t	link_align;
338644961713Sgirish 	uint16_t	val1, val2, val3;
338744961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
338844961713Sgirish 	uint16_t	val_debug;
338944961713Sgirish 	uint16_t	val;
339044961713Sgirish #endif
339144961713Sgirish 
339244961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
339344961713Sgirish 
339444961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
339544961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
339644961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
339744961713Sgirish 	if ((val_debug & ~0x200) != 0) {
339844961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
339944961713Sgirish 				nxgep->mac.portnum, val_debug);
340044961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
340144961713Sgirish 				&val_debug);
340244961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
340344961713Sgirish 				nxgep->mac.portnum, val_debug);
340444961713Sgirish 	}
340544961713Sgirish 
340644961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
340744961713Sgirish 					XPCS_REG_DESCWERR_COUNTER, &val);
340844961713Sgirish 	if (val != 0)
340944961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
341044961713Sgirish 
341144961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
341244961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
341344961713Sgirish 	if (val != 0)
341444961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
341544961713Sgirish 
341644961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
341744961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
341844961713Sgirish 	if (val != 0)
341944961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
342044961713Sgirish #endif
342144961713Sgirish 
342244961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
342344961713Sgirish 
342444961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
342544961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
342644961713Sgirish 			BCM8704_PMA_PMD_DEV_ADDR,
342744961713Sgirish 			BCM8704_PMD_RECEIVE_SIG_DETECT,
342844961713Sgirish 			&val1);
342944961713Sgirish 	if (status != NXGE_OK)
343044961713Sgirish 		goto fail;
343144961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
343244961713Sgirish 
343344961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
343444961713Sgirish 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
343544961713Sgirish 			BCM8704_PCS_DEV_ADDR,
343644961713Sgirish 			BCM8704_10GBASE_R_PCS_STATUS_REG,
343744961713Sgirish 			&val2)) != NPI_SUCCESS)
343844961713Sgirish 		goto fail;
343944961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
344044961713Sgirish 
344144961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
344244961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
344344961713Sgirish 			BCM8704_PHYXS_ADDR,
344444961713Sgirish 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
344544961713Sgirish 			&val3);
344644961713Sgirish 	if (status != NXGE_OK)
344744961713Sgirish 		goto fail;
344844961713Sgirish 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
344944961713Sgirish 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
345044961713Sgirish 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
345144961713Sgirish 
345244961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
345344961713Sgirish 	/* Temp workaround for link down issue */
345444961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
345544961713Sgirish 		if (val2 != 0x4) {
345644961713Sgirish 			pcs_blk_lock = B_TRUE;
345744961713Sgirish 			cmn_err(CE_NOTE,
345844961713Sgirish 				"!LINK DEBUG: port%d PHY Dev3 "
345944961713Sgirish 				"Reg 0x20 = 0x%x\n",
346044961713Sgirish 				nxgep->mac.portnum, val2);
346144961713Sgirish 		}
346244961713Sgirish 	}
346344961713Sgirish 
346444961713Sgirish 	if (link_align == B_FALSE) {
346544961713Sgirish 		if (val3 != 0x140f) {
346644961713Sgirish 			link_align = B_TRUE;
346744961713Sgirish 			cmn_err(CE_NOTE,
346844961713Sgirish 				"!LINK DEBUG: port%d PHY Dev4 "
346944961713Sgirish 				"Reg 0x18 = 0x%x\n",
347044961713Sgirish 				nxgep->mac.portnum, val3);
347144961713Sgirish 		}
347244961713Sgirish 	}
347344961713Sgirish 
347444961713Sgirish 	if (rx_sig_ok == B_FALSE) {
347544961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
347644961713Sgirish 			rx_sig_ok = B_TRUE;
347744961713Sgirish 			cmn_err(CE_NOTE,
347844961713Sgirish 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
347944961713Sgirish 				nxgep->mac.portnum);
348044961713Sgirish 		}
348144961713Sgirish 	}
348244961713Sgirish #endif
348344961713Sgirish 
348444961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
348544961713Sgirish 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
348644961713Sgirish 
348744961713Sgirish 	return (NXGE_OK);
348844961713Sgirish fail:
348944961713Sgirish 	return (status);
349044961713Sgirish }
349144961713Sgirish 
3492*59ac0c16Sdavemq nxge_status_t
3493*59ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
3494*59ac0c16Sdavemq {
3495*59ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
3496*59ac0c16Sdavemq 	    != NPI_SUCCESS)
3497*59ac0c16Sdavemq 		return (NXGE_ERROR);
3498*59ac0c16Sdavemq 	else
3499*59ac0c16Sdavemq 		return (NXGE_OK);
3500*59ac0c16Sdavemq }
350144961713Sgirish 
350244961713Sgirish nxge_status_t
3503*59ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
350444961713Sgirish {
3505*59ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
3506*59ac0c16Sdavemq 	    != NPI_SUCCESS)
3507*59ac0c16Sdavemq 		return (NXGE_ERROR);
3508*59ac0c16Sdavemq 	else
3509*59ac0c16Sdavemq 		return (NXGE_OK);
3510*59ac0c16Sdavemq }
351144961713Sgirish 
3512*59ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
3513*59ac0c16Sdavemq 
3514*59ac0c16Sdavemq static boolean_t
3515*59ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
3516*59ac0c16Sdavemq {
3517*59ac0c16Sdavemq 	int		i;
3518*59ac0c16Sdavemq 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
3519*59ac0c16Sdavemq 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
3520*59ac0c16Sdavemq 	boolean_t	found = B_FALSE;
3521*59ac0c16Sdavemq 
3522*59ac0c16Sdavemq 	switch (type) {
3523*59ac0c16Sdavemq 	case CLAUSE_45_TYPE:
3524*59ac0c16Sdavemq 		for (i = 0; i < cl45_arr_len; i++) {
3525*59ac0c16Sdavemq 			if ((nxge_supported_cl45_ids[i] & PHY_ID_MASK) ==
3526*59ac0c16Sdavemq 			    (id & PHY_ID_MASK)) {
3527*59ac0c16Sdavemq 				found = B_TRUE;
3528*59ac0c16Sdavemq 				break;
3529*59ac0c16Sdavemq 			}
3530*59ac0c16Sdavemq 		}
3531*59ac0c16Sdavemq 		break;
3532*59ac0c16Sdavemq 	case CLAUSE_22_TYPE:
3533*59ac0c16Sdavemq 		for (i = 0; i < cl22_arr_len; i++) {
3534*59ac0c16Sdavemq 			if ((nxge_supported_cl22_ids[i] & PHY_ID_MASK) ==
3535*59ac0c16Sdavemq 			    (id & PHY_ID_MASK)) {
3536*59ac0c16Sdavemq 				found = B_TRUE;
3537*59ac0c16Sdavemq 				break;
353856d930aeSspeer 			}
353944961713Sgirish 		}
3540*59ac0c16Sdavemq 		break;
3541*59ac0c16Sdavemq 	default:
3542*59ac0c16Sdavemq 		break;
354356d930aeSspeer 	}
354456d930aeSspeer 
3545*59ac0c16Sdavemq 	return (found);
3546*59ac0c16Sdavemq }
3547*59ac0c16Sdavemq 
3548*59ac0c16Sdavemq /*
3549*59ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
3550*59ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
3551*59ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
3552*59ac0c16Sdavemq  * and the Neptune type.
3553*59ac0c16Sdavemq  */
3554*59ac0c16Sdavemq 
3555*59ac0c16Sdavemq nxge_status_t
3556*59ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
3557*59ac0c16Sdavemq {
3558*59ac0c16Sdavemq 	int		i, j, k, l;
3559*59ac0c16Sdavemq 	uint16_t	val1 = 0;
3560*59ac0c16Sdavemq 	uint16_t	val2 = 0;
3561*59ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
3562*59ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
3563*59ac0c16Sdavemq 	uint32_t	phy_id = 0;
3564*59ac0c16Sdavemq 	uint32_t	port_pma_pmd_dev_id[4];
3565*59ac0c16Sdavemq 	uint32_t	port_pcs_dev_id[4];
3566*59ac0c16Sdavemq 	uint32_t	port_phy_id[4];
3567*59ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
3568*59ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
3569*59ac0c16Sdavemq 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
3570*59ac0c16Sdavemq 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
3571*59ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
3572*59ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
3573*59ac0c16Sdavemq 	npi_status_t	npi_status = NPI_SUCCESS;
3574*59ac0c16Sdavemq 	npi_handle_t	handle;
3575*59ac0c16Sdavemq 	int		prt_id = -1;
357656d930aeSspeer 
3577*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
357856d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3579*59ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
3580*59ac0c16Sdavemq 	    nxgep->niu_type));
3581*59ac0c16Sdavemq 
3582*59ac0c16Sdavemq 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3583*59ac0c16Sdavemq 	j = k = l = 0;
3584*59ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
358556d930aeSspeer 	/*
3586*59ac0c16Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
3587*59ac0c16Sdavemq 	 * for on chip serdes usages.
358856d930aeSspeer 	 */
3589*59ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
3590*59ac0c16Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3591*59ac0c16Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
3592*59ac0c16Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3593*59ac0c16Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
3594*59ac0c16Sdavemq 		pma_pmd_dev_id = val1;
3595*59ac0c16Sdavemq 		pma_pmd_dev_id = (pma_pmd_dev_id << 16);
3596*59ac0c16Sdavemq 		pma_pmd_dev_id |= val2;
3597*59ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
3598*59ac0c16Sdavemq 		    "devid[0x%llx]", i, pma_pmd_dev_id));
3599*59ac0c16Sdavemq 
3600*59ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
3601*59ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
3602*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3603*59ac0c16Sdavemq 			    "PMA/PMD dev found", i));
3604*59ac0c16Sdavemq 			if (j < 4) {
3605*59ac0c16Sdavemq 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id;
3606*59ac0c16Sdavemq 				j++;
3607*59ac0c16Sdavemq 			}
3608*59ac0c16Sdavemq 		} else {
3609*59ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
3610*59ac0c16Sdavemq 		}
3611*59ac0c16Sdavemq 
3612*59ac0c16Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3613*59ac0c16Sdavemq 		    NXGE_DEV_ID_REG_1, &val1);
3614*59ac0c16Sdavemq 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3615*59ac0c16Sdavemq 		    NXGE_DEV_ID_REG_2, &val2);
3616*59ac0c16Sdavemq 		pcs_dev_id = val1;
3617*59ac0c16Sdavemq 		pcs_dev_id = (pcs_dev_id << 16);
3618*59ac0c16Sdavemq 		pcs_dev_id |= val2;
3619*59ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3620*59ac0c16Sdavemq 		    "devid[0x%llx]", i, pcs_dev_id));
3621*59ac0c16Sdavemq 
3622*59ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
3623*59ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
3624*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3625*59ac0c16Sdavemq 			    "dev found", i));
3626*59ac0c16Sdavemq 			if (k < 4) {
3627*59ac0c16Sdavemq 				port_pcs_dev_id[k] = pcs_dev_id;
3628*59ac0c16Sdavemq 				k++;
3629*59ac0c16Sdavemq 			}
3630*59ac0c16Sdavemq 		} else {
3631*59ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
3632*59ac0c16Sdavemq 		}
3633*59ac0c16Sdavemq 
3634*59ac0c16Sdavemq 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
3635*59ac0c16Sdavemq 			port_fd[i] = 1;
3636*59ac0c16Sdavemq 		else
3637*59ac0c16Sdavemq 			port_fd[i] = 0;
3638*59ac0c16Sdavemq 		total_port_fd += port_fd[i];
3639*59ac0c16Sdavemq 
3640*59ac0c16Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
3641*59ac0c16Sdavemq 		    NXGE_PHY_ID_REG_1, &val1);
3642*59ac0c16Sdavemq 		if (npi_status != NPI_SUCCESS) {
3643*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3644*59ac0c16Sdavemq 			    "clause 22 read to reg 2 failed!!!"));
3645*59ac0c16Sdavemq 			goto error_exit;
3646*59ac0c16Sdavemq 		}
3647*59ac0c16Sdavemq 		npi_status = npi_mac_mif_mii_read(handle, i,
3648*59ac0c16Sdavemq 		    NXGE_PHY_ID_REG_2, &val2);
3649*59ac0c16Sdavemq 		if (npi_status != 0) {
3650*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3651*59ac0c16Sdavemq 			    "clause 22 read to reg 3 failed!!!"));
3652*59ac0c16Sdavemq 			goto error_exit;
3653*59ac0c16Sdavemq 		}
3654*59ac0c16Sdavemq 		phy_id = val1;
3655*59ac0c16Sdavemq 		phy_id = (phy_id << 16);
3656*59ac0c16Sdavemq 		phy_id |= val2;
3657*59ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3658*59ac0c16Sdavemq 		    "[0x%llx]", i, phy_id));
3659*59ac0c16Sdavemq 
3660*59ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
3661*59ac0c16Sdavemq 			phy_fd[i] = 1;
3662*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3663*59ac0c16Sdavemq 			    "found", i));
3664*59ac0c16Sdavemq 			if (l < 4) {
3665*59ac0c16Sdavemq 				port_phy_id[l] = phy_id;
3666*59ac0c16Sdavemq 				l++;
3667*59ac0c16Sdavemq 			}
3668*59ac0c16Sdavemq 		} else {
3669*59ac0c16Sdavemq 			phy_fd[i] = 0;
3670*59ac0c16Sdavemq 		}
3671*59ac0c16Sdavemq 		total_phy_fd += phy_fd[i];
3672*59ac0c16Sdavemq 	}
3673*59ac0c16Sdavemq 
3674*59ac0c16Sdavemq 	switch (total_port_fd) {
3675*59ac0c16Sdavemq 	case 2:
3676*59ac0c16Sdavemq 		switch (total_phy_fd) {
3677*59ac0c16Sdavemq 		case 2:
3678*59ac0c16Sdavemq 			/* 2 10G, 2 1G */
3679*59ac0c16Sdavemq 			if (((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3680*59ac0c16Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3681*59ac0c16Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3682*59ac0c16Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) &&
3683*59ac0c16Sdavemq 			    (port_phy_id[0] == PHY_1G_COPPER &&
3684*59ac0c16Sdavemq 			    port_phy_id[1] == PHY_1G_COPPER)) {
3685*59ac0c16Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3686*59ac0c16Sdavemq 			} else {
3687*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3688*59ac0c16Sdavemq 				    "Unsupported neptune type 1"));
3689*59ac0c16Sdavemq 				goto error_exit;
3690*59ac0c16Sdavemq 			}
3691*59ac0c16Sdavemq 			break;
3692*59ac0c16Sdavemq 		case 1:
3693*59ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
3694*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3695*59ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
3696*59ac0c16Sdavemq 			goto error_exit;
3697*59ac0c16Sdavemq 		case 0:
3698*59ac0c16Sdavemq 			/* 2 10G */
3699*59ac0c16Sdavemq 			if ((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3700*59ac0c16Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3701*59ac0c16Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3702*59ac0c16Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) {
3703*59ac0c16Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF;
3704*59ac0c16Sdavemq 			} else {
3705*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3706*59ac0c16Sdavemq 				    "Unsupported neptune type 2"));
3707*59ac0c16Sdavemq 				goto error_exit;
3708*59ac0c16Sdavemq 			}
3709*59ac0c16Sdavemq 			break;
3710*59ac0c16Sdavemq 		case 4:
3711*59ac0c16Sdavemq 			/* Maramba with 2 XAUI */
3712*59ac0c16Sdavemq 			if (((port_pcs_dev_id[0] == PHY_10G_FIBRE &&
3713*59ac0c16Sdavemq 			    port_pcs_dev_id[1] == PHY_10G_FIBRE) ||
3714*59ac0c16Sdavemq 			    (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE &&
3715*59ac0c16Sdavemq 			    port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) &&
3716*59ac0c16Sdavemq 			    (port_phy_id[0] == PHY_1G_COPPER &&
3717*59ac0c16Sdavemq 			    port_phy_id[1] == PHY_1G_COPPER &&
3718*59ac0c16Sdavemq 			    port_phy_id[2] == PHY_1G_COPPER &&
3719*59ac0c16Sdavemq 			    port_phy_id[3] == PHY_1G_COPPER)) {
3720*59ac0c16Sdavemq 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3721*59ac0c16Sdavemq 
3722*59ac0c16Sdavemq 				/*
3723*59ac0c16Sdavemq 				 * Check the first phy port address against
3724*59ac0c16Sdavemq 				 * the known phy start addresses to determine
3725*59ac0c16Sdavemq 				 * the platform type.
3726*59ac0c16Sdavemq 				 */
3727*59ac0c16Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3728*59ac0c16Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3729*59ac0c16Sdavemq 					if (phy_fd[i] == 1)
3730*59ac0c16Sdavemq 						break;
3731*59ac0c16Sdavemq 				}
3732*59ac0c16Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3733*59ac0c16Sdavemq 					hw_p->platform_type =
3734*59ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
3735*59ac0c16Sdavemq 				} else if (i ==
3736*59ac0c16Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3737*59ac0c16Sdavemq 					hw_p->platform_type =
3738*59ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3739*59ac0c16Sdavemq 				} else {
3740*59ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3741*59ac0c16Sdavemq 					    "Unknown port %d...Cannot "
3742*59ac0c16Sdavemq 					    "determine platform type", i));
3743*59ac0c16Sdavemq 				}
3744*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3745*59ac0c16Sdavemq 				    "Maramba with 2 XAUI"));
3746*59ac0c16Sdavemq 			} else {
3747*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3748*59ac0c16Sdavemq 				    "Unsupported neptune type 3"));
3749*59ac0c16Sdavemq 				goto error_exit;
3750*59ac0c16Sdavemq 			}
3751*59ac0c16Sdavemq 			break;
3752*59ac0c16Sdavemq 		default:
3753*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3754*59ac0c16Sdavemq 			    "Unsupported neptune type 5"));
3755*59ac0c16Sdavemq 			goto error_exit;
3756*59ac0c16Sdavemq 		}
3757*59ac0c16Sdavemq 	case 1:
3758*59ac0c16Sdavemq 		switch (total_phy_fd) {
3759*59ac0c16Sdavemq 		case 3:
3760*59ac0c16Sdavemq 			if (((port_pcs_dev_id[0] & PHY_ID_MASK) ==
3761*59ac0c16Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK)) ||
3762*59ac0c16Sdavemq 			    ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) ==
3763*59ac0c16Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK))) {
3764*59ac0c16Sdavemq 				/* The 10G port is BCM8704 */
3765*59ac0c16Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3766*59ac0c16Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3767*59ac0c16Sdavemq 					if (port_fd[i] == 1) {
3768*59ac0c16Sdavemq 						prt_id = i;
3769*59ac0c16Sdavemq 						break;
3770*59ac0c16Sdavemq 					}
3771*59ac0c16Sdavemq 				}
3772*59ac0c16Sdavemq 
3773*59ac0c16Sdavemq 				if (nxgep->niu_type == N2_NIU)
3774*59ac0c16Sdavemq 					prt_id %= BCM8704_N2_PORT_ADDR_BASE;
3775*59ac0c16Sdavemq 				else
3776*59ac0c16Sdavemq 					prt_id %=
3777*59ac0c16Sdavemq 					    BCM8704_NEPTUNE_PORT_ADDR_BASE;
3778*59ac0c16Sdavemq 
3779*59ac0c16Sdavemq 				if (prt_id == 0) {
3780*59ac0c16Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3781*59ac0c16Sdavemq 				} else if (prt_id == 1) {
3782*59ac0c16Sdavemq 					hw_p->niu_type =
3783*59ac0c16Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3784*59ac0c16Sdavemq 				} else {
3785*59ac0c16Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3786*59ac0c16Sdavemq 					    "Unsupported neptune type 6"));
3787*59ac0c16Sdavemq 					goto error_exit;
3788*59ac0c16Sdavemq 				}
3789*59ac0c16Sdavemq 			} else {
3790*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3791*59ac0c16Sdavemq 				    "Unsupported neptune type 7"));
3792*59ac0c16Sdavemq 				goto error_exit;
3793*59ac0c16Sdavemq 			}
3794*59ac0c16Sdavemq 			break;
3795*59ac0c16Sdavemq 		case 2:
3796*59ac0c16Sdavemq 			/*
3797*59ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
3798*59ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
3799*59ac0c16Sdavemq 			 * 1_10G_2_1G
3800*59ac0c16Sdavemq 			 */
3801*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3802*59ac0c16Sdavemq 			    "Unsupported neptune type 8"));
3803*59ac0c16Sdavemq 			goto error_exit;
3804*59ac0c16Sdavemq 		case 1:
3805*59ac0c16Sdavemq 			/*
3806*59ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
3807*59ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
3808*59ac0c16Sdavemq 			 * 1_10G_1_1G
3809*59ac0c16Sdavemq 			 */
3810*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3811*59ac0c16Sdavemq 			    "Unsupported neptune type 9"));
3812*59ac0c16Sdavemq 			goto error_exit;
3813*59ac0c16Sdavemq 		case 0:
3814*59ac0c16Sdavemq 			/* TODO 1 10G mode */
3815*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3816*59ac0c16Sdavemq 			    "Unsupported neptune type 10"));
3817*59ac0c16Sdavemq 			goto error_exit;
3818*59ac0c16Sdavemq 		case 4:
3819*59ac0c16Sdavemq 			/* Maramba with 1 XAUI */
3820*59ac0c16Sdavemq 			if (((port_pcs_dev_id[0] & PHY_ID_MASK) ==
3821*59ac0c16Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK)) ||
3822*59ac0c16Sdavemq 			    ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) ==
3823*59ac0c16Sdavemq 			    (BCM8704_DEV_ID & PHY_ID_MASK))) {
3824*59ac0c16Sdavemq 				/* The 10G port is BCM8704 */
3825*59ac0c16Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3826*59ac0c16Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3827*59ac0c16Sdavemq 					if (port_fd[i] == 1) {
3828*59ac0c16Sdavemq 						prt_id = i;
3829*59ac0c16Sdavemq 						break;
3830*59ac0c16Sdavemq 					}
3831*59ac0c16Sdavemq 				}
3832*59ac0c16Sdavemq 
3833*59ac0c16Sdavemq 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
3834*59ac0c16Sdavemq 				if (prt_id == 0) {
3835*59ac0c16Sdavemq 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3836*59ac0c16Sdavemq 				} else if (prt_id == 1) {
3837*59ac0c16Sdavemq 					hw_p->niu_type =
3838*59ac0c16Sdavemq 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3839*59ac0c16Sdavemq 				} else {
3840*59ac0c16Sdavemq 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3841*59ac0c16Sdavemq 					    "Unsupported neptune type 11"));
3842*59ac0c16Sdavemq 					goto error_exit;
3843*59ac0c16Sdavemq 				}
3844*59ac0c16Sdavemq 
3845*59ac0c16Sdavemq 				/*
3846*59ac0c16Sdavemq 				 * Check the first phy port address against
3847*59ac0c16Sdavemq 				 * the known phy start addresses to determine
3848*59ac0c16Sdavemq 				 * the platform type.
3849*59ac0c16Sdavemq 				 */
3850*59ac0c16Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3851*59ac0c16Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3852*59ac0c16Sdavemq 					if (phy_fd[i] == 1)
3853*59ac0c16Sdavemq 						break;
3854*59ac0c16Sdavemq 				}
3855*59ac0c16Sdavemq 
3856*59ac0c16Sdavemq 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3857*59ac0c16Sdavemq 					hw_p->platform_type =
3858*59ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
3859*59ac0c16Sdavemq 				} else if (i ==
3860*59ac0c16Sdavemq 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3861*59ac0c16Sdavemq 					hw_p->platform_type =
3862*59ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3863*59ac0c16Sdavemq 				} else {
3864*59ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3865*59ac0c16Sdavemq 					    "Unknown port %d...Cannot "
3866*59ac0c16Sdavemq 					    "determine platform type", i));
3867*59ac0c16Sdavemq 				}
3868*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3869*59ac0c16Sdavemq 				    "Maramba with 1 XAUI"));
3870*59ac0c16Sdavemq 			} else {
3871*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3872*59ac0c16Sdavemq 				    "Unsupported neptune type 12"));
3873*59ac0c16Sdavemq 				goto error_exit;
3874*59ac0c16Sdavemq 			}
3875*59ac0c16Sdavemq 			break;
3876*59ac0c16Sdavemq 		default:
3877*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3878*59ac0c16Sdavemq 			    "Unsupported neptune type 13"));
3879*59ac0c16Sdavemq 			goto error_exit;
3880*59ac0c16Sdavemq 		}
3881*59ac0c16Sdavemq 		break;
3882*59ac0c16Sdavemq 	case 0:
3883*59ac0c16Sdavemq 		switch (total_phy_fd) {
3884*59ac0c16Sdavemq 		case 4:
3885*59ac0c16Sdavemq 			if (((port_phy_id[0] & PHY_ID_MASK) ==
3886*59ac0c16Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3887*59ac0c16Sdavemq 			    ((port_phy_id[1] & PHY_ID_MASK) ==
3888*59ac0c16Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3889*59ac0c16Sdavemq 			    ((port_phy_id[2] & PHY_ID_MASK) ==
3890*59ac0c16Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK)) &&
3891*59ac0c16Sdavemq 			    ((port_phy_id[3] & PHY_ID_MASK) ==
3892*59ac0c16Sdavemq 			    (BCM5464R_PHY_ID & PHY_ID_MASK))) {
3893*59ac0c16Sdavemq 
3894*59ac0c16Sdavemq 				hw_p->niu_type = NEPTUNE_4_1GC;
3895*59ac0c16Sdavemq 
3896*59ac0c16Sdavemq 				/*
3897*59ac0c16Sdavemq 				 * Check the first phy port address against
3898*59ac0c16Sdavemq 				 * the known phy start addresses to determine
3899*59ac0c16Sdavemq 				 * the platform type.
3900*59ac0c16Sdavemq 				 */
3901*59ac0c16Sdavemq 				for (i = NXGE_EXT_PHY_PORT_ST;
3902*59ac0c16Sdavemq 				    i < NXGE_MAX_PHY_PORTS; i++) {
3903*59ac0c16Sdavemq 					if (phy_fd[i] == 1)
3904*59ac0c16Sdavemq 						break;
3905*59ac0c16Sdavemq 				}
3906*59ac0c16Sdavemq 
3907*59ac0c16Sdavemq 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3908*59ac0c16Sdavemq 					hw_p->platform_type =
3909*59ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
3910*59ac0c16Sdavemq 				}
3911*59ac0c16Sdavemq 			} else {
3912*59ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3913*59ac0c16Sdavemq 				    "Unsupported neptune type 14"));
3914*59ac0c16Sdavemq 				goto error_exit;
3915*59ac0c16Sdavemq 			}
3916*59ac0c16Sdavemq 			break;
3917*59ac0c16Sdavemq 		case 3:
3918*59ac0c16Sdavemq 			/* TODO 3 1G mode */
3919*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3920*59ac0c16Sdavemq 			    "Unsupported neptune type 15"));
3921*59ac0c16Sdavemq 			goto error_exit;
3922*59ac0c16Sdavemq 		case 2:
3923*59ac0c16Sdavemq 			/* TODO 2 1G mode */
3924*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3925*59ac0c16Sdavemq 			    "Unsupported neptune type 16"));
3926*59ac0c16Sdavemq 			goto error_exit;
3927*59ac0c16Sdavemq 		case 1:
3928*59ac0c16Sdavemq 			/* TODO 1 1G mode */
3929*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3930*59ac0c16Sdavemq 			    "Unsupported neptune type 17"));
3931*59ac0c16Sdavemq 			goto error_exit;
3932*59ac0c16Sdavemq 		default:
3933*59ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3934*59ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
3935*59ac0c16Sdavemq 			    total_phy_fd));
3936*59ac0c16Sdavemq 			goto error_exit;
3937*59ac0c16Sdavemq 		}
3938*59ac0c16Sdavemq 		break;
3939*59ac0c16Sdavemq 	default:
394056d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3941*59ac0c16Sdavemq 		    "Unsupported neptune type 19"));
3942*59ac0c16Sdavemq 		goto error_exit;
394344961713Sgirish 	}
394444961713Sgirish 
3945*59ac0c16Sdavemq scan_exit:
394644961713Sgirish 
3947*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
3948*59ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
3949*59ac0c16Sdavemq 	return (status);
395044961713Sgirish 
3951*59ac0c16Sdavemq error_exit:
3952*59ac0c16Sdavemq 	return (NXGE_ERROR);
395344961713Sgirish }
395456d930aeSspeer 
395556d930aeSspeer boolean_t
395656d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
395756d930aeSspeer {
395856d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
395956d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
396056d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
396156d930aeSspeer 		return (B_FALSE);
396256d930aeSspeer 	else
396356d930aeSspeer 		return (B_TRUE);
396456d930aeSspeer }
3965*59ac0c16Sdavemq 
3966*59ac0c16Sdavemq static void
3967*59ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
3968*59ac0c16Sdavemq 
3969*59ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
3970*59ac0c16Sdavemq 	uint8_t xcvr_portn;
3971*59ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3972*59ac0c16Sdavemq 
3973*59ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
3974*59ac0c16Sdavemq 
3975*59ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
3976*59ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
3977*59ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
3978*59ac0c16Sdavemq 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
3979*59ac0c16Sdavemq 	}
3980*59ac0c16Sdavemq 	/*
3981*59ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
3982*59ac0c16Sdavemq 	 * swapped with ethernet port number. This is
3983*59ac0c16Sdavemq 	 * designed for better signal integrity in routing.
3984*59ac0c16Sdavemq 	 */
3985*59ac0c16Sdavemq 	switch (portn) {
3986*59ac0c16Sdavemq 	case 0:
3987*59ac0c16Sdavemq 		xcvr_portn += 3;
3988*59ac0c16Sdavemq 		break;
3989*59ac0c16Sdavemq 	case 1:
3990*59ac0c16Sdavemq 		xcvr_portn += 2;
3991*59ac0c16Sdavemq 		break;
3992*59ac0c16Sdavemq 	case 2:
3993*59ac0c16Sdavemq 		xcvr_portn += 1;
3994*59ac0c16Sdavemq 		break;
3995*59ac0c16Sdavemq 	case 3:
3996*59ac0c16Sdavemq 	default:
3997*59ac0c16Sdavemq 		break;
3998*59ac0c16Sdavemq 	}
3999*59ac0c16Sdavemq 
4000*59ac0c16Sdavemq 	MUTEX_ENTER(&nxge_mii_lock);
4001*59ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4002*59ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
4003*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
4004*59ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4005*59ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4006*59ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
4007*59ac0c16Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
4008*59ac0c16Sdavemq 		return;
4009*59ac0c16Sdavemq 	}
4010*59ac0c16Sdavemq 
4011*59ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4012*59ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
4013*59ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
4014*59ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4015*59ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4016*59ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
4017*59ac0c16Sdavemq 		MUTEX_EXIT(&nxge_mii_lock);
4018*59ac0c16Sdavemq 		return;
4019*59ac0c16Sdavemq 	}
4020*59ac0c16Sdavemq 
4021*59ac0c16Sdavemq 	MUTEX_EXIT(&nxge_mii_lock);
4022*59ac0c16Sdavemq }
4023