xref: /titanic_44/usr/src/uts/common/io/nxge/nxge_mac.c (revision 54925bf60766fbb4f1f2d7c843721406a7b7a3fb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/nxge/nxge_impl.h>
29 #include <sys/nxge/nxge_mac.h>
30 
31 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
32 #define	LM_WAIT_MULTIPLIER	8
33 
34 extern uint32_t nxge_no_link_notify;
35 extern boolean_t nxge_no_msg;
36 extern uint32_t nxge_lb_dbg;
37 extern nxge_os_mutex_t	nxge_mdio_lock;
38 extern nxge_os_mutex_t	nxge_mii_lock;
39 extern boolean_t nxge_jumbo_enable;
40 
41 typedef enum {
42 	CHECK_LINK_RESCHEDULE,
43 	CHECK_LINK_STOP
44 } check_link_state_t;
45 
46 static check_link_state_t nxge_check_link_stop(nxge_t *);
47 
48 /*
49  * Ethernet broadcast address definition.
50  */
51 static ether_addr_st etherbroadcastaddr =
52 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
53 /*
54  * Ethernet zero address definition.
55  */
56 static ether_addr_st etherzeroaddr =
57 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
58 /*
59  * Supported chip types
60  */
61 static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
62 static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
63 
64 #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
65 				sizeof (uint32_t))
66 #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
67 				sizeof (uint32_t))
68 /*
69  * static functions
70  */
71 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
72 static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
73 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
74 static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
75 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
76 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
77 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
78 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
79 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
80 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
81 static nxge_status_t nxge_check_mii_link(p_nxge_t);
82 static nxge_status_t nxge_check_10g_link(p_nxge_t);
83 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
84 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
85 static void nxge_bcm5464_link_led_off(p_nxge_t);
86 
87 /*
88  * xcvr tables for supported transceivers
89  */
90 
91 static nxge_xcvr_table_t nxge_n2_table = {
92 	nxge_n2_serdes_init,
93 	nxge_10G_xcvr_init,
94 	nxge_10G_link_intr_stop,
95 	nxge_10G_link_intr_start,
96 	nxge_check_10g_link,
97 	BCM8704_DEV_ID,
98 	PCS_XCVR,
99 	BCM8704_N2_PORT_ADDR_BASE
100 };
101 
102 static nxge_xcvr_table_t nxge_10G_fiber_table = {
103 	nxge_neptune_10G_serdes_init,
104 	nxge_10G_xcvr_init,
105 	nxge_10G_link_intr_stop,
106 	nxge_10G_link_intr_start,
107 	nxge_check_10g_link,
108 	BCM8704_DEV_ID,
109 	PCS_XCVR,
110 	BCM8704_NEPTUNE_PORT_ADDR_BASE
111 };
112 
113 static nxge_xcvr_table_t nxge_1G_copper_table = {
114 	NULL,
115 	nxge_1G_xcvr_init,
116 	nxge_1G_copper_link_intr_stop,
117 	nxge_1G_copper_link_intr_start,
118 	nxge_check_mii_link,
119 	BCM5464R_PHY_ID,
120 	INT_MII_XCVR,
121 	BCM5464_NEPTUNE_PORT_ADDR_BASE
122 };
123 
124 static nxge_xcvr_table_t nxge_1G_fiber_table = {
125 	nxge_1G_serdes_init,
126 	nxge_1G_xcvr_init,
127 	nxge_1G_fiber_link_intr_stop,
128 	nxge_1G_fiber_link_intr_start,
129 	nxge_check_mii_link,
130 	0,
131 	PCS_XCVR,
132 	0
133 };
134 
135 static nxge_xcvr_table_t nxge_10G_copper_table = {
136 	nxge_neptune_10G_serdes_init,
137 	NULL,
138 	NULL,
139 	NULL,
140 	0,
141 	PCS_XCVR,
142 	0
143 };
144 
145 nxge_status_t nxge_mac_init(p_nxge_t);
146 
147 /* Set up the PHY specific values. */
148 
149 nxge_status_t
150 nxge_setup_xcvr_table(p_nxge_t nxgep)
151 {
152 	nxge_status_t	status = NXGE_OK;
153 	uint32_t	port_type;
154 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
155 
156 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
157 	    portn));
158 
159 	if (nxgep->niu_type == N2_NIU) {
160 		nxgep->mac.portmode = PORT_10G_FIBER;
161 		nxgep->xcvr = nxge_n2_table;
162 		nxgep->xcvr.xcvr_addr += portn;
163 	} else {
164 		port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn);
165 		port_type = port_type & (NXGE_PORT_TYPE_MASK);
166 		switch (port_type) {
167 		case NXGE_PORT_1G_COPPER:
168 			nxgep->mac.portmode = PORT_1G_COPPER;
169 			nxgep->xcvr = nxge_1G_copper_table;
170 			if (nxgep->nxge_hw_p->platform_type ==
171 			    P_NEPTUNE_MARAMBA_P1) {
172 				nxgep->xcvr.xcvr_addr =
173 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
174 			} else if (nxgep->nxge_hw_p->platform_type ==
175 			    P_NEPTUNE_MARAMBA_P0) {
176 				nxgep->xcvr.xcvr_addr =
177 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
178 			}
179 			/*
180 			 * For Altas 4-1G copper, Xcvr port numbers are
181 			 * swapped with ethernet port number. This is
182 			 * designed for better signal integrity in routing.
183 			 */
184 			switch (portn) {
185 			case 0:
186 				nxgep->xcvr.xcvr_addr += 3;
187 				break;
188 			case 1:
189 				nxgep->xcvr.xcvr_addr += 2;
190 				break;
191 			case 2:
192 				nxgep->xcvr.xcvr_addr += 1;
193 				break;
194 			case 3:
195 				break;
196 			default:
197 				return (NXGE_ERROR);
198 			}
199 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
200 			break;
201 		case NXGE_PORT_10G_COPPER:
202 			nxgep->mac.portmode = PORT_10G_COPPER;
203 			nxgep->xcvr = nxge_10G_copper_table;
204 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
205 			break;
206 		case NXGE_PORT_1G_FIBRE:
207 			nxgep->mac.portmode = PORT_1G_FIBER;
208 			nxgep->xcvr = nxge_1G_fiber_table;
209 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr"));
210 			break;
211 		case NXGE_PORT_10G_FIBRE:
212 			nxgep->mac.portmode = PORT_10G_FIBER;
213 			nxgep->xcvr = nxge_10G_fiber_table;
214 			if ((nxgep->nxge_hw_p->platform_type ==
215 			    P_NEPTUNE_MARAMBA_P0) ||
216 			    (nxgep->nxge_hw_p->platform_type ==
217 			    P_NEPTUNE_MARAMBA_P1)) {
218 				nxgep->xcvr.xcvr_addr =
219 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
220 				/*
221 				 * Switch off LED for corresponding copper
222 				 * port
223 				 */
224 				nxge_bcm5464_link_led_off(nxgep);
225 			}
226 			nxgep->xcvr.xcvr_addr += portn;
227 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr"));
228 			break;
229 		default:
230 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
231 			    "Unknown port-type: 0x%x", port_type));
232 			return (NXGE_ERROR);
233 		}
234 	}
235 
236 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
237 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
238 	nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id;
239 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
240 
241 	return (status);
242 }
243 
244 /* Initialize the entire MAC and physical layer */
245 
246 nxge_status_t
247 nxge_mac_init(p_nxge_t nxgep)
248 {
249 	uint8_t			portn;
250 	nxge_status_t		status = NXGE_OK;
251 
252 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
253 
254 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
255 
256 	nxgep->mac.portnum = portn;
257 	nxgep->mac.porttype = PORT_TYPE_XMAC;
258 
259 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
260 		nxgep->mac.porttype = PORT_TYPE_BMAC;
261 
262 	/* Initialize XIF to configure a network mode */
263 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
264 		goto fail;
265 	}
266 
267 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
268 		goto fail;
269 	}
270 
271 	/* Initialize TX and RX MACs */
272 	/*
273 	 * Always perform XIF init first, before TX and RX MAC init
274 	 */
275 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
276 		goto fail;
277 
278 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
279 		goto fail;
280 
281 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
282 		goto fail;
283 
284 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
285 		goto fail;
286 
287 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
288 		goto fail;
289 
290 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
291 		goto fail;
292 
293 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
294 
295 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
296 
297 	return (NXGE_OK);
298 fail:
299 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
300 			"nxge_mac_init: failed to initialize MAC port<%d>",
301 			portn));
302 	return (status);
303 }
304 
305 /* Initialize the Ethernet Link */
306 
307 nxge_status_t
308 nxge_link_init(p_nxge_t nxgep)
309 {
310 	nxge_status_t		status = NXGE_OK;
311 #ifdef	NXGE_DEBUG
312 	uint8_t			portn;
313 
314 	portn = nxgep->mac.portnum;
315 
316 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
317 #endif
318 
319 	if (nxgep->niu_type == N2_NIU) {
320 		/* Workaround to get link up in both NIU ports */
321 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
322 			goto fail;
323 	}
324 	NXGE_DELAY(200000);
325 	/* Initialize internal serdes */
326 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
327 		goto fail;
328 	NXGE_DELAY(200000);
329 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
330 		goto fail;
331 
332 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
333 
334 	return (NXGE_OK);
335 
336 fail:
337 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
338 		"nxge_link_init: ",
339 		"failed to initialize Ethernet link on port<%d>",
340 		portn));
341 
342 	return (status);
343 }
344 
345 
346 /* Initialize the XIF sub-block within the MAC */
347 
348 nxge_status_t
349 nxge_xif_init(p_nxge_t nxgep)
350 {
351 	uint32_t		xif_cfg = 0;
352 	npi_attr_t		ap;
353 	uint8_t			portn;
354 	nxge_port_t		portt;
355 	nxge_port_mode_t	portmode;
356 	p_nxge_stats_t		statsp;
357 	npi_status_t		rs = NPI_SUCCESS;
358 	npi_handle_t		handle;
359 
360 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
361 
362 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
363 
364 	handle = nxgep->npi_handle;
365 	portmode = nxgep->mac.portmode;
366 	portt = nxgep->mac.porttype;
367 	statsp = nxgep->statsp;
368 
369 	if (portt == PORT_TYPE_XMAC) {
370 
371 		/* Setup XIF Configuration for XMAC */
372 
373 		if ((portmode == PORT_10G_FIBER) ||
374 					(portmode == PORT_10G_COPPER))
375 			xif_cfg |= CFG_XMAC_XIF_LFS;
376 
377 		if (portmode == PORT_1G_COPPER) {
378 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
379 		}
380 
381 		/* Set MAC Internal Loopback if necessary */
382 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
383 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
384 
385 		if (statsp->mac_stats.link_speed == 100)
386 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
387 
388 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
389 
390 		if (portmode == PORT_10G_FIBER) {
391 			if (statsp->mac_stats.link_up) {
392 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
393 			} else {
394 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
395 			}
396 		}
397 
398 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
399 		if (rs != NPI_SUCCESS)
400 			goto fail;
401 
402 		nxgep->mac.xif_config = xif_cfg;
403 
404 		/* Set Port Mode */
405 		if ((portmode == PORT_10G_FIBER) ||
406 					(portmode == PORT_10G_COPPER)) {
407 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
408 						MAC_XGMII_MODE, rs);
409 			if (rs != NPI_SUCCESS)
410 				goto fail;
411 			if (statsp->mac_stats.link_up) {
412 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
413 					goto fail;
414 			} else {
415 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
416 					goto fail;
417 			}
418 		} else if ((portmode == PORT_1G_FIBER) ||
419 						(portmode == PORT_1G_COPPER)) {
420 			if (statsp->mac_stats.link_speed == 1000) {
421 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
422 							MAC_GMII_MODE, rs);
423 			} else {
424 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
425 							MAC_MII_MODE, rs);
426 			}
427 			if (rs != NPI_SUCCESS)
428 				goto fail;
429 		} else {
430 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
431 					"nxge_xif_init: Unknown port mode (%d)"
432 					" for port<%d>", portmode, portn));
433 			goto fail;
434 		}
435 
436 	} else if (portt == PORT_TYPE_BMAC) {
437 
438 		/* Setup XIF Configuration for BMAC */
439 
440 		if (portmode == PORT_1G_COPPER) {
441 			if (statsp->mac_stats.link_speed == 100)
442 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
443 		}
444 
445 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
446 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
447 
448 		if (statsp->mac_stats.link_speed == 1000)
449 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
450 
451 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
452 
453 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
454 		if (rs != NPI_SUCCESS)
455 			goto fail;
456 		nxgep->mac.xif_config = xif_cfg;
457 	}
458 
459 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
460 	return (NXGE_OK);
461 fail:
462 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
463 			"nxge_xif_init: Failed to initialize XIF port<%d>",
464 			portn));
465 	return (NXGE_ERROR | rs);
466 }
467 
468 /* Initialize the PCS sub-block in the MAC */
469 
470 nxge_status_t
471 nxge_pcs_init(p_nxge_t nxgep)
472 {
473 	pcs_cfg_t		pcs_cfg;
474 	uint32_t		val;
475 	uint8_t			portn;
476 	nxge_port_mode_t	portmode;
477 	npi_handle_t		handle;
478 	p_nxge_stats_t		statsp;
479 	npi_status_t		rs = NPI_SUCCESS;
480 
481 	handle = nxgep->npi_handle;
482 	portmode = nxgep->mac.portmode;
483 	portn = nxgep->mac.portnum;
484 	statsp = nxgep->statsp;
485 
486 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
487 
488 	if (portmode == PORT_1G_FIBER) {
489 		/* Initialize port's PCS */
490 		pcs_cfg.value = 0;
491 		pcs_cfg.bits.w0.enable = 1;
492 		pcs_cfg.bits.w0.mask = 1;
493 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
494 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
495 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
496 			goto fail;
497 
498 	} else if ((portmode == PORT_10G_FIBER) ||
499 						(portmode == PORT_10G_COPPER)) {
500 		/* Use internal XPCS, bypass 1G PCS */
501 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
502 		val &= ~XMAC_XIF_XPCS_BYPASS;
503 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
504 
505 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
506 			goto fail;
507 
508 		/* Set XPCS Internal Loopback if necessary */
509 		if ((rs = npi_xmac_xpcs_read(handle, portn,
510 						XPCS_REG_CONTROL1, &val))
511 						!= NPI_SUCCESS)
512 			goto fail;
513 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
514 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
515 			val |= XPCS_CTRL1_LOOPBK;
516 		else
517 			val &= ~XPCS_CTRL1_LOOPBK;
518 		if ((rs = npi_xmac_xpcs_write(handle, portn,
519 						XPCS_REG_CONTROL1, val))
520 						!= NPI_SUCCESS)
521 			goto fail;
522 
523 		/* Clear descw errors */
524 		if ((rs = npi_xmac_xpcs_write(handle, portn,
525 						XPCS_REG_DESCWERR_COUNTER, 0))
526 						!= NPI_SUCCESS)
527 			goto fail;
528 		/* Clear symbol errors */
529 		if ((rs = npi_xmac_xpcs_read(handle, portn,
530 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
531 					!= NPI_SUCCESS)
532 			goto fail;
533 		if ((rs = npi_xmac_xpcs_read(handle, portn,
534 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
535 					!= NPI_SUCCESS)
536 			goto fail;
537 
538 	} else if (portmode == PORT_1G_COPPER) {
539 		if (portn < 4) {
540 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
541 					PCS_DATAPATH_MODE_MII);
542 		}
543 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
544 			goto fail;
545 
546 	} else {
547 		goto fail;
548 	}
549 pass:
550 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
551 	return (NXGE_OK);
552 fail:
553 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
554 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
555 			portn));
556 	return (NXGE_ERROR | rs);
557 }
558 
559 /* Initialize the Internal Serdes */
560 
561 nxge_status_t
562 nxge_serdes_init(p_nxge_t nxgep)
563 {
564 	p_nxge_stats_t		statsp;
565 #ifdef	NXGE_DEBUG
566 	uint8_t			portn;
567 #endif
568 	nxge_status_t		status = NXGE_OK;
569 
570 #ifdef	NXGE_DEBUG
571 	portn = nxgep->mac.portnum;
572 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
573 	    "==> nxge_serdes_init port<%d>", portn));
574 #endif
575 
576 	if (nxgep->xcvr.serdes_init) {
577 		statsp = nxgep->statsp;
578 		status = nxgep->xcvr.serdes_init(nxgep);
579 		if (status != NXGE_OK)
580 			goto fail;
581 		statsp->mac_stats.serdes_inits++;
582 	}
583 
584 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
585 	    portn));
586 
587 	return (NXGE_OK);
588 
589 fail:
590 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
591 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
592 	    portn));
593 
594 	return (status);
595 }
596 
597 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
598 
599 static nxge_status_t
600 nxge_n2_serdes_init(p_nxge_t nxgep)
601 {
602 	uint8_t portn;
603 	int chan;
604 	esr_ti_cfgpll_l_t pll_cfg_l;
605 	esr_ti_cfgrx_l_t rx_cfg_l;
606 	esr_ti_cfgrx_h_t rx_cfg_h;
607 	esr_ti_cfgtx_l_t tx_cfg_l;
608 	esr_ti_cfgtx_h_t tx_cfg_h;
609 	esr_ti_testcfg_t test_cfg;
610 	nxge_status_t status = NXGE_OK;
611 
612 	portn = nxgep->mac.portnum;
613 
614 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
615 			portn));
616 
617 	tx_cfg_l.value = 0;
618 	tx_cfg_h.value = 0;
619 	rx_cfg_l.value = 0;
620 	rx_cfg_h.value = 0;
621 	pll_cfg_l.value = 0;
622 	test_cfg.value = 0;
623 
624 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
625 		/* 0x0E01 */
626 		tx_cfg_l.bits.entx = 1;
627 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
628 
629 		/* 0x9101 */
630 		rx_cfg_l.bits.enrx = 1;
631 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
632 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
633 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
634 
635 		/* 0x0008 */
636 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
637 
638 		/* Set loopback mode if necessary */
639 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
640 			tx_cfg_l.bits.entest = 1;
641 			rx_cfg_l.bits.entest = 1;
642 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
643 			if ((status = nxge_mdio_write(nxgep, portn,
644 				ESR_N2_DEV_ADDR,
645 				ESR_N2_TEST_CFG_REG, test_cfg.value))
646 				!= NXGE_OK)
647 			goto fail;
648 		}
649 
650 		/* Use default PLL value */
651 
652 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
653 
654 		/* 0x0E21 */
655 		tx_cfg_l.bits.entx = 1;
656 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
657 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
658 
659 		/* 0x9121 */
660 		rx_cfg_l.bits.enrx = 1;
661 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
662 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
663 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
664 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
665 
666 		/* 0x8 */
667 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
668 
669 		/* MPY = 0x100 */
670 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
671 
672 		/* Set PLL */
673 		pll_cfg_l.bits.enpll = 1;
674 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
675 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
676 				!= NXGE_OK)
677 			goto fail;
678 	} else {
679 		goto fail;
680 	}
681 
682 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
683 
684 	NXGE_DELAY(20);
685 
686 	/* init TX channels */
687 	for (chan = 0; chan < 4; chan++) {
688 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
689 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
690 				!= NXGE_OK)
691 			goto fail;
692 
693 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
694 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
695 				!= NXGE_OK)
696 			goto fail;
697 	}
698 
699 	/* init RX channels */
700 	for (chan = 0; chan < 4; chan++) {
701 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
702 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
703 				!= NXGE_OK)
704 			goto fail;
705 
706 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
707 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
708 				!= NXGE_OK)
709 			goto fail;
710 	}
711 
712 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
713 			portn));
714 
715 	return (NXGE_OK);
716 fail:
717 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
718 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
719 				portn));
720 
721 	return (status);
722 }
723 
724 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
725 
726 static nxge_status_t
727 nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
728 {
729 	npi_handle_t		handle;
730 	uint8_t			portn;
731 	int			chan;
732 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
733 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
734 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
735 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
736 	uint64_t		val;
737 	uint16_t		val16l;
738 	uint16_t		val16h;
739 	nxge_status_t		status = NXGE_OK;
740 
741 	portn = nxgep->mac.portnum;
742 
743 	if ((portn != 0) && (portn != 1))
744 		return (NXGE_OK);
745 
746 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
747 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
748 
749 	handle = nxgep->npi_handle;
750 	switch (portn) {
751 	case 0:
752 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
753 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
754 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
755 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
756 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
757 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
758 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
759 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
760 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
761 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
762 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
763 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
764 
765 		/* Set Serdes0 Internal Loopback if necessary */
766 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
767 			ESR_REG_WR(handle,
768 			    ESR_0_TEST_CONFIG_REG,
769 			    ESR_PAD_LOOPBACK_CH3 |
770 			    ESR_PAD_LOOPBACK_CH2 |
771 			    ESR_PAD_LOOPBACK_CH1 |
772 			    ESR_PAD_LOOPBACK_CH0);
773 		} else {
774 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
775 		}
776 		break;
777 	case 1:
778 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
779 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
780 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
781 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
782 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
783 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
784 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
785 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
786 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
787 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
788 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
789 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
790 
791 		/* Set Serdes1 Internal Loopback if necessary */
792 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
793 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
794 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
795 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
796 		} else {
797 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
798 		}
799 		break;
800 	default:
801 		/* Nothing to do here */
802 		goto done;
803 	}
804 
805 	/* init TX RX channels */
806 	for (chan = 0; chan < 4; chan++) {
807 		if ((status = nxge_mdio_read(nxgep, portn,
808 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
809 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
810 			goto fail;
811 		if ((status = nxge_mdio_read(nxgep, portn,
812 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
813 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
814 			goto fail;
815 		if ((status = nxge_mdio_read(nxgep, portn,
816 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
817 		    &glue_ctrl0_l.value)) != NXGE_OK)
818 			goto fail;
819 		if ((status = nxge_mdio_read(nxgep, portn,
820 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
821 		    &glue_ctrl0_h.value)) != NXGE_OK)
822 			goto fail;
823 		rx_tx_ctrl_l.bits.enstretch = 1;
824 		rx_tx_ctrl_h.bits.vmuxlo = 2;
825 		rx_tx_ctrl_h.bits.vpulselo = 2;
826 		glue_ctrl0_l.bits.rxlosenable = 1;
827 		glue_ctrl0_l.bits.samplerate = 0xF;
828 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
829 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
830 		if ((status = nxge_mdio_write(nxgep, portn,
831 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
832 		    rx_tx_ctrl_l.value)) != NXGE_OK)
833 			goto fail;
834 		if ((status = nxge_mdio_write(nxgep, portn,
835 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
836 		    rx_tx_ctrl_h.value)) != NXGE_OK)
837 			goto fail;
838 		if ((status = nxge_mdio_write(nxgep, portn,
839 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
840 		    glue_ctrl0_l.value)) != NXGE_OK)
841 			goto fail;
842 		if ((status = nxge_mdio_write(nxgep, portn,
843 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
844 		    glue_ctrl0_h.value)) != NXGE_OK)
845 			goto fail;
846 		}
847 
848 	/* Apply Tx core reset */
849 	if ((status = nxge_mdio_write(nxgep, portn,
850 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
851 	    (uint16_t)0)) != NXGE_OK)
852 		goto fail;
853 
854 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
855 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
856 	    NXGE_OK)
857 		goto fail;
858 
859 	NXGE_DELAY(200);
860 
861 	/* Apply Rx core reset */
862 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
863 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
864 	    NXGE_OK)
865 		goto fail;
866 
867 	NXGE_DELAY(200);
868 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
869 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
870 		goto fail;
871 
872 	NXGE_DELAY(200);
873 	if ((status = nxge_mdio_read(nxgep, portn,
874 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
875 	    &val16l)) != NXGE_OK)
876 		goto fail;
877 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
878 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
879 		goto fail;
880 	if ((val16l != 0) || (val16h != 0)) {
881 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
882 		    "Failed to reset port<%d> XAUI Serdes", portn));
883 	}
884 
885 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
886 
887 	if (portn == 0) {
888 		if ((val & ESR_SIG_P0_BITS_MASK) !=
889 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
890 					ESR_SIG_XSERDES_RDY_P0 |
891 					ESR_SIG_XDETECT_P0_CH3 |
892 					ESR_SIG_XDETECT_P0_CH2 |
893 					ESR_SIG_XDETECT_P0_CH1 |
894 					ESR_SIG_XDETECT_P0_CH0)) {
895 			goto fail;
896 		}
897 	} else if (portn == 1) {
898 		if ((val & ESR_SIG_P1_BITS_MASK) !=
899 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
900 					ESR_SIG_XSERDES_RDY_P1 |
901 					ESR_SIG_XDETECT_P1_CH3 |
902 					ESR_SIG_XDETECT_P1_CH2 |
903 					ESR_SIG_XDETECT_P1_CH1 |
904 					ESR_SIG_XDETECT_P1_CH0)) {
905 			goto fail;
906 		}
907 	}
908 
909 done:
910 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
911 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
912 
913 	return (NXGE_OK);
914 fail:
915 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
916 	    "nxge_neptune_10G_serdes_init: "
917 	    "Failed to initialize Neptune serdes for port<%d>", portn));
918 
919 	return (status);
920 }
921 
922 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
923 
924 static nxge_status_t
925 nxge_1G_serdes_init(p_nxge_t nxgep)
926 {
927 	npi_handle_t		handle;
928 	uint8_t			portn;
929 	uint64_t		val;
930 
931 	portn = nxgep->mac.portnum;
932 
933 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
934 	    "==> nxge_1G_serdes_init port<%d>", portn));
935 
936 	handle = nxgep->npi_handle;
937 
938 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
939 	val &= ~ESR_PLL_CFG_FBDIV_2;
940 	switch (portn) {
941 	case 0:
942 		val |= ESR_PLL_CFG_HALF_RATE_0;
943 		break;
944 	case 1:
945 		val |= ESR_PLL_CFG_HALF_RATE_1;
946 		break;
947 	case 2:
948 		val |= ESR_PLL_CFG_HALF_RATE_2;
949 		break;
950 	case 3:
951 		val |= ESR_PLL_CFG_HALF_RATE_3;
952 		break;
953 	default:
954 		goto fail;
955 	}
956 
957 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
958 
959 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
960 	    "<== nxge_1G_serdes_init port<%d>", portn));
961 	return (NXGE_OK);
962 fail:
963 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
964 	    "nxge_1G_serdes_init: "
965 	    "Failed to initialize Neptune serdes for port<%d>",
966 	    portn));
967 
968 	return (NXGE_ERROR);
969 }
970 
971 /* Initialize the 10G (BCM8704) Transceiver */
972 
973 static nxge_status_t
974 nxge_10G_xcvr_init(p_nxge_t nxgep)
975 {
976 	p_nxge_stats_t		statsp;
977 	uint16_t		val;
978 #ifdef	NXGE_DEBUG
979 	uint8_t			portn;
980 	uint16_t		val1;
981 #endif
982 	uint8_t			phy_port_addr;
983 	pmd_tx_control_t	tx_ctl;
984 	control_t		ctl;
985 	phyxs_control_t		phyxs_ctl;
986 	pcs_control_t		pcs_ctl;
987 	uint32_t		delay = 0;
988 	optics_dcntr_t		op_ctr;
989 	nxge_status_t		status = NXGE_OK;
990 #ifdef	NXGE_DEBUG
991 	portn = nxgep->mac.portnum;
992 #endif
993 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
994 	    portn));
995 
996 	statsp = nxgep->statsp;
997 
998 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
999 
1000 	/* Disable Link LEDs */
1001 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1002 		goto fail;
1003 
1004 	/* Set Clause 45 */
1005 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
1006 
1007 	/* Reset the transceiver */
1008 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1009 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
1010 		goto fail;
1011 
1012 	phyxs_ctl.bits.reset = 1;
1013 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1014 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
1015 		goto fail;
1016 
1017 	do {
1018 		drv_usecwait(500);
1019 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1020 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
1021 		    &phyxs_ctl.value)) != NXGE_OK)
1022 			goto fail;
1023 		delay++;
1024 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
1025 	if (delay == 100) {
1026 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
1027 		    "failed to reset Transceiver on port<%d>", portn));
1028 		status = NXGE_ERROR;
1029 		goto fail;
1030 	}
1031 
1032 	/* Set to 0x7FBF */
1033 	ctl.value = 0;
1034 	ctl.bits.res1 = 0x3F;
1035 	ctl.bits.optxon_lvl = 1;
1036 	ctl.bits.oprxflt_lvl = 1;
1037 	ctl.bits.optrxlos_lvl = 1;
1038 	ctl.bits.optxflt_lvl = 1;
1039 	ctl.bits.opprflt_lvl = 1;
1040 	ctl.bits.obtmpflt_lvl = 1;
1041 	ctl.bits.opbiasflt_lvl = 1;
1042 	ctl.bits.optxrst_lvl = 1;
1043 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1044 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
1045 	    != NXGE_OK)
1046 		goto fail;
1047 
1048 	/* Set to 0x164 */
1049 	tx_ctl.value = 0;
1050 	tx_ctl.bits.tsck_lpwren = 1;
1051 	tx_ctl.bits.tx_dac_txck = 0x2;
1052 	tx_ctl.bits.tx_dac_txd = 0x1;
1053 	tx_ctl.bits.xfp_clken = 1;
1054 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1055 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
1056 	    tx_ctl.value)) != NXGE_OK)
1057 		goto fail;
1058 	/*
1059 	 * According to Broadcom's instruction, SW needs to read
1060 	 * back these registers twice after written.
1061 	 */
1062 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1063 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1064 	    != NXGE_OK)
1065 		goto fail;
1066 
1067 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1068 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1069 	    != NXGE_OK)
1070 		goto fail;
1071 
1072 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1073 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1074 	    != NXGE_OK)
1075 		goto fail;
1076 
1077 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1078 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1079 	    != NXGE_OK)
1080 		goto fail;
1081 
1082 	/* Enable Tx and Rx LEDs to be driven by traffic */
1083 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1084 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1085 	    &op_ctr.value)) != NXGE_OK)
1086 		goto fail;
1087 	op_ctr.bits.gpio_sel = 0x3;
1088 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1089 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1090 	    op_ctr.value)) != NXGE_OK)
1091 		goto fail;
1092 
1093 	NXGE_DELAY(1000000);
1094 
1095 	/* Set BCM8704 Internal Loopback mode if necessary */
1096 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1097 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
1098 	    != NXGE_OK)
1099 		goto fail;
1100 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
1101 		pcs_ctl.bits.loopback = 1;
1102 	else
1103 		pcs_ctl.bits.loopback = 0;
1104 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1105 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
1106 	    != NXGE_OK)
1107 		goto fail;
1108 
1109 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
1110 	if (status != NXGE_OK)
1111 		goto fail;
1112 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1113 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
1114 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
1115 	if (status != NXGE_OK)
1116 		goto fail;
1117 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1118 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
1119 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
1120 	if (status != NXGE_OK)
1121 		goto fail;
1122 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1123 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
1124 
1125 #ifdef	NXGE_DEBUG
1126 	/* Diagnose link issue if link is not up */
1127 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
1128 	    BCM8704_USER_ANALOG_STATUS0_REG,
1129 	    &val);
1130 	if (status != NXGE_OK)
1131 		goto fail;
1132 
1133 	status = nxge_mdio_read(nxgep, phy_port_addr,
1134 				BCM8704_USER_DEV3_ADDR,
1135 				BCM8704_USER_ANALOG_STATUS0_REG,
1136 				&val);
1137 	if (status != NXGE_OK)
1138 		goto fail;
1139 
1140 	status = nxge_mdio_read(nxgep, phy_port_addr,
1141 				BCM8704_USER_DEV3_ADDR,
1142 				BCM8704_USER_TX_ALARM_STATUS_REG,
1143 				&val1);
1144 	if (status != NXGE_OK)
1145 		goto fail;
1146 
1147 	status = nxge_mdio_read(nxgep, phy_port_addr,
1148 				BCM8704_USER_DEV3_ADDR,
1149 				BCM8704_USER_TX_ALARM_STATUS_REG,
1150 				&val1);
1151 	if (status != NXGE_OK)
1152 		goto fail;
1153 
1154 	if (val != 0x3FC) {
1155 		if ((val == 0x43BC) && (val1 != 0)) {
1156 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1157 			    "Cable not connected to peer or bad"
1158 			    " cable on port<%d>\n", portn));
1159 		} else if (val == 0x639C) {
1160 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1161 			    "Optical module (XFP) is bad or absent"
1162 			    " on port<%d>\n", portn));
1163 		}
1164 	}
1165 #endif
1166 
1167 	statsp->mac_stats.cap_10gfdx = 1;
1168 	statsp->mac_stats.lp_cap_10gfdx = 1;
1169 
1170 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
1171 	    portn));
1172 	return (NXGE_OK);
1173 
1174 fail:
1175 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1176 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
1177 	    "port<%d>", portn));
1178 	return (status);
1179 }
1180 
1181 /* Initialize the 1G copper (BCM 5464) Transceiver */
1182 
1183 static nxge_status_t
1184 nxge_1G_xcvr_init(p_nxge_t nxgep)
1185 {
1186 	p_nxge_param_t		param_arr = nxgep->param_arr;
1187 	p_nxge_stats_t		statsp = nxgep->statsp;
1188 	nxge_status_t		status = NXGE_OK;
1189 
1190 	/* Set Clause 22 */
1191 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
1192 
1193 	/* Set capability flags */
1194 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
1195 	statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value;
1196 	statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value;
1197 
1198 	status = nxge_mii_xcvr_init(nxgep);
1199 
1200 	return (status);
1201 }
1202 
1203 /* Initialize transceiver */
1204 
1205 nxge_status_t
1206 nxge_xcvr_init(p_nxge_t nxgep)
1207 {
1208 	p_nxge_stats_t		statsp;
1209 #ifdef	NXGE_DEBUG
1210 	uint8_t			portn;
1211 #endif
1212 
1213 	nxge_status_t		status = NXGE_OK;
1214 #ifdef	NXGE_DEBUG
1215 	portn = nxgep->mac.portnum;
1216 #endif
1217 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
1218 	statsp = nxgep->statsp;
1219 
1220 	/*
1221 	 * Initialize the xcvr statistics.
1222 	 */
1223 	statsp->mac_stats.cap_autoneg = 0;
1224 	statsp->mac_stats.cap_100T4 = 0;
1225 	statsp->mac_stats.cap_100fdx = 0;
1226 	statsp->mac_stats.cap_100hdx = 0;
1227 	statsp->mac_stats.cap_10fdx = 0;
1228 	statsp->mac_stats.cap_10hdx = 0;
1229 	statsp->mac_stats.cap_asmpause = 0;
1230 	statsp->mac_stats.cap_pause = 0;
1231 	statsp->mac_stats.cap_1000fdx = 0;
1232 	statsp->mac_stats.cap_1000hdx = 0;
1233 	statsp->mac_stats.cap_10gfdx = 0;
1234 	statsp->mac_stats.cap_10ghdx = 0;
1235 
1236 	/*
1237 	 * Initialize the link statistics.
1238 	 */
1239 	statsp->mac_stats.link_T4 = 0;
1240 	statsp->mac_stats.link_asmpause = 0;
1241 	statsp->mac_stats.link_pause = 0;
1242 
1243 	if (nxgep->xcvr.xcvr_init) {
1244 		status = nxgep->xcvr.xcvr_init(nxgep);
1245 		if (status != NXGE_OK)
1246 			goto fail;
1247 		statsp->mac_stats.xcvr_inits++;
1248 	}
1249 
1250 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
1251 	    portn));
1252 	return (NXGE_OK);
1253 
1254 fail:
1255 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1256 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
1257 	    portn));
1258 	return (status);
1259 }
1260 
1261 
1262 /* Initialize the TxMAC sub-block */
1263 
1264 nxge_status_t
1265 nxge_tx_mac_init(p_nxge_t nxgep)
1266 {
1267 	npi_attr_t		ap;
1268 	uint8_t			portn;
1269 	nxge_port_mode_t	portmode;
1270 	nxge_port_t		portt;
1271 	npi_handle_t		handle;
1272 	npi_status_t		rs = NPI_SUCCESS;
1273 
1274 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1275 	portt    = nxgep->mac.porttype;
1276 	handle   = nxgep->npi_handle;
1277 	portmode = nxgep->mac.portmode;
1278 
1279 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
1280 			portn));
1281 
1282 	/* Set Max and Min Frame Size */
1283 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
1284 		SET_MAC_ATTR2(handle, ap, portn,
1285 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
1286 	} else {
1287 		SET_MAC_ATTR2(handle, ap, portn,
1288 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
1289 	}
1290 
1291 	if (rs != NPI_SUCCESS)
1292 		goto fail;
1293 	if (nxgep->param_arr[param_accept_jumbo].value ||
1294 		nxgep->mac.is_jumbo == B_TRUE)
1295 		nxgep->mac.maxframesize = 0x2400;
1296 	else
1297 		nxgep->mac.maxframesize = 0x5EE + 4;
1298 	nxgep->mac.minframesize = 64;
1299 
1300 	if (portt == PORT_TYPE_XMAC) {
1301 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
1302 				0)) != NPI_SUCCESS)
1303 			goto fail;
1304 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
1305 		if ((portmode == PORT_10G_FIBER) ||
1306 					(portmode == PORT_10G_COPPER)) {
1307 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
1308 					XGMII_IPG_12_15, rs);
1309 			if (rs != NPI_SUCCESS)
1310 				goto fail;
1311 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
1312 		} else {
1313 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
1314 					MII_GMII_IPG_12, rs);
1315 			if (rs != NPI_SUCCESS)
1316 				goto fail;
1317 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
1318 		}
1319 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
1320 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
1321 			goto fail;
1322 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
1323 		nxgep->mac.maxburstsize = 0;	/* not programmable */
1324 		nxgep->mac.ctrltype = 0;	/* not programmable */
1325 		nxgep->mac.pa_size = 0;		/* not programmable */
1326 
1327 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
1328 							!= NPI_SUCCESS)
1329 			goto fail;
1330 
1331 	} else {
1332 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
1333 				0)) != NPI_SUCCESS)
1334 			goto fail;
1335 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
1336 
1337 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
1338 				rs);
1339 		if (rs != NPI_SUCCESS)
1340 			goto fail;
1341 		nxgep->mac.ctrltype = 0x8808;
1342 
1343 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
1344 		if (rs != NPI_SUCCESS)
1345 			goto fail;
1346 		nxgep->mac.pa_size = 0x7;
1347 
1348 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
1349 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
1350 			goto fail;
1351 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
1352 	}
1353 
1354 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
1355 			portn));
1356 
1357 	return (NXGE_OK);
1358 fail:
1359 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1360 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
1361 					portn));
1362 
1363 	return (NXGE_ERROR | rs);
1364 }
1365 
1366 /* Initialize the RxMAC sub-block */
1367 
1368 nxge_status_t
1369 nxge_rx_mac_init(p_nxge_t nxgep)
1370 {
1371 	npi_attr_t		ap;
1372 	uint32_t		i;
1373 	uint16_t		hashtab_e;
1374 	p_hash_filter_t		hash_filter;
1375 	nxge_port_t		portt;
1376 	uint8_t			portn;
1377 	npi_handle_t		handle;
1378 	npi_status_t		rs = NPI_SUCCESS;
1379 	uint16_t 		*addr16p;
1380 	uint16_t 		addr0, addr1, addr2;
1381 	xmac_rx_config_t	xconfig;
1382 	bmac_rx_config_t	bconfig;
1383 
1384 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1385 
1386 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
1387 			portn));
1388 	handle = nxgep->npi_handle;
1389 	portt = nxgep->mac.porttype;
1390 
1391 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
1392 	addr0 = ntohs(addr16p[2]);
1393 	addr1 = ntohs(addr16p[1]);
1394 	addr2 = ntohs(addr16p[0]);
1395 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
1396 		rs);
1397 
1398 	if (rs != NPI_SUCCESS)
1399 		goto fail;
1400 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
1401 	if (rs != NPI_SUCCESS)
1402 		goto fail;
1403 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
1404 	if (rs != NPI_SUCCESS)
1405 		goto fail;
1406 
1407 	/*
1408 	 * Load the multicast hash filter bits.
1409 	 */
1410 	hash_filter = nxgep->hash_filter;
1411 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
1412 		if (hash_filter != NULL) {
1413 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
1414 				(NMCFILTER_REGS - 1) - i];
1415 		} else {
1416 			hashtab_e = 0;
1417 		}
1418 
1419 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
1420 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
1421 			goto fail;
1422 	}
1423 
1424 	if (portt == PORT_TYPE_XMAC) {
1425 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
1426 				0)) != NPI_SUCCESS)
1427 			goto fail;
1428 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
1429 
1430 		(void) nxge_fflp_init_hostinfo(nxgep);
1431 
1432 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
1433 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
1434 			~CFG_XMAC_RX_STRIP_CRC;
1435 
1436 		if (nxgep->filter.all_phys_cnt != 0)
1437 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
1438 
1439 		if (nxgep->filter.all_multicast_cnt != 0)
1440 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
1441 
1442 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
1443 
1444 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
1445 					xconfig)) != NPI_SUCCESS)
1446 			goto fail;
1447 		nxgep->mac.rx_config = xconfig;
1448 
1449 		/* Comparison of mac unique address is always enabled on XMAC */
1450 
1451 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
1452 							!= NPI_SUCCESS)
1453 			goto fail;
1454 	} else {
1455 		(void) nxge_fflp_init_hostinfo(nxgep);
1456 
1457 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
1458 					0) != NPI_SUCCESS)
1459 			goto fail;
1460 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
1461 
1462 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
1463 			~CFG_BMAC_RX_STRIP_CRC;
1464 
1465 		if (nxgep->filter.all_phys_cnt != 0)
1466 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
1467 
1468 		if (nxgep->filter.all_multicast_cnt != 0)
1469 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
1470 
1471 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
1472 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
1473 					bconfig)) != NPI_SUCCESS)
1474 			goto fail;
1475 		nxgep->mac.rx_config = bconfig;
1476 
1477 		/* Always enable comparison of mac unique address */
1478 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
1479 					!= NPI_SUCCESS)
1480 			goto fail;
1481 	}
1482 
1483 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
1484 			portn));
1485 
1486 	return (NXGE_OK);
1487 
1488 fail:
1489 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1490 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
1491 				portn));
1492 
1493 	return (NXGE_ERROR | rs);
1494 }
1495 
1496 /* Enable TXMAC */
1497 
1498 nxge_status_t
1499 nxge_tx_mac_enable(p_nxge_t nxgep)
1500 {
1501 	npi_handle_t	handle;
1502 	npi_status_t	rs = NPI_SUCCESS;
1503 	nxge_status_t	status = NXGE_OK;
1504 
1505 	handle = nxgep->npi_handle;
1506 
1507 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
1508 			nxgep->mac.portnum));
1509 
1510 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
1511 		goto fail;
1512 
1513 	/* based on speed */
1514 	nxgep->msg_min = ETHERMIN;
1515 
1516 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1517 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
1518 						CFG_XMAC_TX)) != NPI_SUCCESS)
1519 			goto fail;
1520 	} else {
1521 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
1522 						CFG_BMAC_TX)) != NPI_SUCCESS)
1523 			goto fail;
1524 	}
1525 
1526 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
1527 			nxgep->mac.portnum));
1528 
1529 	return (NXGE_OK);
1530 fail:
1531 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1532 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
1533 			nxgep->mac.portnum));
1534 	if (rs != NPI_SUCCESS)
1535 		return (NXGE_ERROR | rs);
1536 	else
1537 		return (status);
1538 }
1539 
1540 /* Disable TXMAC */
1541 
1542 nxge_status_t
1543 nxge_tx_mac_disable(p_nxge_t nxgep)
1544 {
1545 	npi_handle_t	handle;
1546 	npi_status_t	rs = NPI_SUCCESS;
1547 
1548 	handle = nxgep->npi_handle;
1549 
1550 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
1551 			nxgep->mac.portnum));
1552 
1553 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1554 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
1555 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
1556 			goto fail;
1557 	} else {
1558 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
1559 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
1560 			goto fail;
1561 	}
1562 
1563 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
1564 			nxgep->mac.portnum));
1565 	return (NXGE_OK);
1566 fail:
1567 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1568 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
1569 			nxgep->mac.portnum));
1570 	return (NXGE_ERROR | rs);
1571 }
1572 
1573 /* Enable RXMAC */
1574 
1575 nxge_status_t
1576 nxge_rx_mac_enable(p_nxge_t nxgep)
1577 {
1578 	npi_handle_t	handle;
1579 	uint8_t 	portn;
1580 	npi_status_t	rs = NPI_SUCCESS;
1581 	nxge_status_t	status = NXGE_OK;
1582 
1583 	handle = nxgep->npi_handle;
1584 	portn = nxgep->mac.portnum;
1585 
1586 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
1587 			portn));
1588 
1589 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
1590 		goto fail;
1591 
1592 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1593 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
1594 						CFG_XMAC_RX)) != NPI_SUCCESS)
1595 			goto fail;
1596 	} else {
1597 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
1598 						CFG_BMAC_RX)) != NPI_SUCCESS)
1599 			goto fail;
1600 	}
1601 
1602 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
1603 			portn));
1604 
1605 	return (NXGE_OK);
1606 fail:
1607 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1608 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
1609 			portn));
1610 
1611 	if (rs != NPI_SUCCESS)
1612 		return (NXGE_ERROR | rs);
1613 	else
1614 		return (status);
1615 }
1616 
1617 /* Disable RXMAC */
1618 
1619 nxge_status_t
1620 nxge_rx_mac_disable(p_nxge_t nxgep)
1621 {
1622 	npi_handle_t	handle;
1623 	uint8_t		portn;
1624 	npi_status_t	rs = NPI_SUCCESS;
1625 
1626 	handle = nxgep->npi_handle;
1627 	portn = nxgep->mac.portnum;
1628 
1629 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
1630 			portn));
1631 
1632 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1633 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
1634 						CFG_XMAC_RX)) != NPI_SUCCESS)
1635 			goto fail;
1636 	} else {
1637 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
1638 						CFG_BMAC_RX)) != NPI_SUCCESS)
1639 			goto fail;
1640 	}
1641 
1642 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
1643 			portn));
1644 	return (NXGE_OK);
1645 fail:
1646 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1647 			"nxgep_rx_mac_disable: ",
1648 			"Failed to disable port<%d> RxMAC",
1649 			portn));
1650 
1651 	return (NXGE_ERROR | rs);
1652 }
1653 
1654 /* Reset TXMAC */
1655 
1656 nxge_status_t
1657 nxge_tx_mac_reset(p_nxge_t nxgep)
1658 {
1659 	npi_handle_t	handle;
1660 	uint8_t		portn;
1661 	npi_status_t	rs = NPI_SUCCESS;
1662 
1663 	handle = nxgep->npi_handle;
1664 	portn = nxgep->mac.portnum;
1665 
1666 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
1667 			portn));
1668 
1669 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1670 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
1671 		    != NPI_SUCCESS)
1672 			goto fail;
1673 	} else {
1674 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
1675 					!= NPI_SUCCESS)
1676 			goto fail;
1677 	}
1678 
1679 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
1680 			portn));
1681 
1682 	return (NXGE_OK);
1683 fail:
1684 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1685 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
1686 			portn));
1687 
1688 	return (NXGE_ERROR | rs);
1689 }
1690 
1691 /* Reset RXMAC */
1692 
1693 nxge_status_t
1694 nxge_rx_mac_reset(p_nxge_t nxgep)
1695 {
1696 	npi_handle_t	handle;
1697 	uint8_t		portn;
1698 	npi_status_t	rs = NPI_SUCCESS;
1699 
1700 	handle = nxgep->npi_handle;
1701 	portn = nxgep->mac.portnum;
1702 
1703 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
1704 			portn));
1705 
1706 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1707 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
1708 		    != NPI_SUCCESS)
1709 		goto fail;
1710 	} else {
1711 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
1712 					!= NPI_SUCCESS)
1713 		goto fail;
1714 	}
1715 
1716 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
1717 			portn));
1718 
1719 	return (NXGE_OK);
1720 fail:
1721 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1722 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
1723 			portn));
1724 	return (NXGE_ERROR | rs);
1725 }
1726 
1727 /* 10G fiber link interrupt start routine */
1728 
1729 static nxge_status_t
1730 nxge_10G_link_intr_start(p_nxge_t nxgep)
1731 {
1732 	npi_status_t	rs = NPI_SUCCESS;
1733 	uint8_t		portn = nxgep->mac.portnum;
1734 
1735 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
1736 
1737 	if (rs != NPI_SUCCESS)
1738 		return (NXGE_ERROR | rs);
1739 	else
1740 		return (NXGE_OK);
1741 }
1742 
1743 /* 10G fiber link interrupt stop routine */
1744 
1745 static nxge_status_t
1746 nxge_10G_link_intr_stop(p_nxge_t nxgep)
1747 {
1748 	npi_status_t	rs = NPI_SUCCESS;
1749 	uint8_t		portn = nxgep->mac.portnum;
1750 
1751 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
1752 
1753 	if (rs != NPI_SUCCESS)
1754 		return (NXGE_ERROR | rs);
1755 	else
1756 		return (NXGE_OK);
1757 }
1758 
1759 /* 1G fiber link interrupt start routine */
1760 
1761 static nxge_status_t
1762 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
1763 {
1764 	npi_status_t	rs = NPI_SUCCESS;
1765 	uint8_t		portn = nxgep->mac.portnum;
1766 
1767 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
1768 	if (rs != NPI_SUCCESS)
1769 		return (NXGE_ERROR | rs);
1770 	else
1771 		return (NXGE_OK);
1772 }
1773 
1774 /* 1G fiber link interrupt stop routine */
1775 
1776 static nxge_status_t
1777 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
1778 {
1779 	npi_status_t	rs = NPI_SUCCESS;
1780 	uint8_t		portn = nxgep->mac.portnum;
1781 
1782 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
1783 
1784 	if (rs != NPI_SUCCESS)
1785 		return (NXGE_ERROR | rs);
1786 	else
1787 		return (NXGE_OK);
1788 }
1789 
1790 /* 1G copper link interrupt start routine */
1791 
1792 static nxge_status_t
1793 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
1794 {
1795 	npi_status_t	rs = NPI_SUCCESS;
1796 	uint8_t		portn = nxgep->mac.portnum;
1797 
1798 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
1799 	    MII_BMSR, BMSR_LSTATUS);
1800 
1801 	if (rs != NPI_SUCCESS)
1802 		return (NXGE_ERROR | rs);
1803 	else
1804 		return (NXGE_OK);
1805 }
1806 
1807 /* 1G copper link interrupt stop routine */
1808 
1809 static nxge_status_t
1810 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
1811 {
1812 	npi_status_t	rs = NPI_SUCCESS;
1813 	uint8_t		portn = nxgep->mac.portnum;
1814 
1815 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
1816 
1817 	if (rs != NPI_SUCCESS)
1818 		return (NXGE_ERROR | rs);
1819 	else
1820 		return (NXGE_OK);
1821 }
1822 
1823 /* Enable/Disable Link Status change interrupt */
1824 
1825 nxge_status_t
1826 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
1827 {
1828 	uint8_t		portn;
1829 	nxge_status_t	status = NXGE_OK;
1830 
1831 	portn = nxgep->mac.portnum;
1832 
1833 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
1834 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
1835 		return (NXGE_OK);
1836 
1837 	if (enable == LINK_INTR_START)
1838 		status = nxgep->xcvr.link_intr_start(nxgep);
1839 	else if (enable == LINK_INTR_STOP)
1840 		status = nxgep->xcvr.link_intr_stop(nxgep);
1841 	if (status != NXGE_OK)
1842 		goto fail;
1843 
1844 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
1845 
1846 	return (NXGE_OK);
1847 fail:
1848 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1849 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
1850 			portn));
1851 
1852 	return (status);
1853 }
1854 
1855 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
1856 
1857 nxge_status_t
1858 nxge_mii_xcvr_init(p_nxge_t nxgep)
1859 {
1860 	p_nxge_param_t	param_arr;
1861 	p_nxge_stats_t	statsp;
1862 	uint8_t		xcvr_portn;
1863 	p_mii_regs_t	mii_regs;
1864 	mii_bmcr_t	bmcr;
1865 	mii_bmsr_t	bmsr;
1866 	mii_anar_t	anar;
1867 	mii_gcr_t	gcr;
1868 	mii_esr_t	esr;
1869 	mii_aux_ctl_t	bcm5464r_aux;
1870 	int		status = NXGE_OK;
1871 
1872 	uint_t delay;
1873 
1874 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
1875 
1876 	param_arr = nxgep->param_arr;
1877 	statsp = nxgep->statsp;
1878 	xcvr_portn = statsp->mac_stats.xcvr_portn;
1879 
1880 	mii_regs = NULL;
1881 
1882 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1883 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
1884 
1885 	/*
1886 	 * Reset the transceiver.
1887 	 */
1888 	delay = 0;
1889 	bmcr.value = 0;
1890 	bmcr.bits.reset = 1;
1891 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
1892 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
1893 		goto fail;
1894 	do {
1895 		drv_usecwait(500);
1896 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
1897 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
1898 				!= NXGE_OK)
1899 			goto fail;
1900 		delay++;
1901 	} while ((bmcr.bits.reset) && (delay < 1000));
1902 	if (delay == 1000) {
1903 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
1904 		goto fail;
1905 	}
1906 
1907 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
1908 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
1909 			&bmsr.value)) != NXGE_OK)
1910 		goto fail;
1911 
1912 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
1913 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
1914 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
1915 	param_arr[param_anar_100hdx].value = 0;
1916 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
1917 	param_arr[param_anar_10hdx].value = 0;
1918 
1919 	/*
1920 	 * Initialize the xcvr statistics.
1921 	 */
1922 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
1923 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
1924 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
1925 	statsp->mac_stats.cap_100hdx = 0;
1926 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
1927 	statsp->mac_stats.cap_10hdx = 0;
1928 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
1929 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
1930 
1931 	/*
1932 	 * Initialise the xcvr advertised capability statistics.
1933 	 */
1934 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
1935 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
1936 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
1937 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
1938 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
1939 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
1940 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
1941 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
1942 	statsp->mac_stats.adv_cap_asmpause =
1943 					param_arr[param_anar_asmpause].value;
1944 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
1945 
1946 
1947 	/*
1948 	 * Check for extended status just in case we're
1949 	 * running a Gigibit phy.
1950 	 */
1951 	if (bmsr.bits.extend_status) {
1952 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
1953 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
1954 				!= NXGE_OK)
1955 			goto fail;
1956 		param_arr[param_anar_1000fdx].value &=
1957 					esr.bits.link_1000fdx;
1958 		param_arr[param_anar_1000hdx].value = 0;
1959 
1960 		statsp->mac_stats.cap_1000fdx =
1961 			(esr.bits.link_1000Xfdx ||
1962 				esr.bits.link_1000fdx);
1963 		statsp->mac_stats.cap_1000hdx = 0;
1964 	} else {
1965 		param_arr[param_anar_1000fdx].value = 0;
1966 		param_arr[param_anar_1000hdx].value = 0;
1967 	}
1968 
1969 	/*
1970 	 * Initialize 1G Statistics once the capability is established.
1971 	 */
1972 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
1973 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
1974 
1975 	/*
1976 	 * Initialise the link statistics.
1977 	 */
1978 	statsp->mac_stats.link_T4 = 0;
1979 	statsp->mac_stats.link_asmpause = 0;
1980 	statsp->mac_stats.link_pause = 0;
1981 	statsp->mac_stats.link_speed = 0;
1982 	statsp->mac_stats.link_duplex = 0;
1983 	statsp->mac_stats.link_up = 0;
1984 
1985 	/*
1986 	 * Switch off Auto-negotiation, 100M and full duplex.
1987 	 */
1988 	bmcr.value = 0;
1989 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
1990 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
1991 		goto fail;
1992 
1993 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
1994 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
1995 		bmcr.bits.loopback = 1;
1996 		bmcr.bits.enable_autoneg = 0;
1997 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
1998 			bmcr.bits.speed_1000_sel = 1;
1999 		bmcr.bits.duplex_mode = 1;
2000 		param_arr[param_autoneg].value = 0;
2001 	} else {
2002 		bmcr.bits.loopback = 0;
2003 	}
2004 
2005 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
2006 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
2007 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
2008 		param_arr[param_autoneg].value = 0;
2009 		bcm5464r_aux.value = 0;
2010 		bcm5464r_aux.bits.ext_lb = 1;
2011 		bcm5464r_aux.bits.write_1 = 1;
2012 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
2013 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
2014 				!= NXGE_OK)
2015 			goto fail;
2016 	}
2017 
2018 	if (param_arr[param_autoneg].value) {
2019 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2020 				"Restarting Auto-negotiation."));
2021 		/*
2022 		 * Setup our Auto-negotiation advertisement register.
2023 		 */
2024 		anar.value = 0;
2025 		anar.bits.selector = 1;
2026 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
2027 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
2028 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
2029 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
2030 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
2031 		anar.bits.cap_asmpause = 0;
2032 		anar.bits.cap_pause = 0;
2033 		if (param_arr[param_anar_1000fdx].value ||
2034 			param_arr[param_anar_100fdx].value ||
2035 			param_arr[param_anar_10fdx].value) {
2036 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
2037 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
2038 		}
2039 
2040 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
2041 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
2042 				!= NXGE_OK)
2043 			goto fail;
2044 		if (bmsr.bits.extend_status) {
2045 			gcr.value = 0;
2046 			gcr.bits.ms_mode_en =
2047 				param_arr[param_master_cfg_enable].value;
2048 			gcr.bits.master =
2049 				param_arr[param_master_cfg_value].value;
2050 			gcr.bits.link_1000fdx =
2051 				param_arr[param_anar_1000fdx].value;
2052 			gcr.bits.link_1000hdx =
2053 				param_arr[param_anar_1000hdx].value;
2054 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2055 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
2056 				!= NXGE_OK)
2057 				goto fail;
2058 		}
2059 
2060 		bmcr.bits.enable_autoneg = 1;
2061 		bmcr.bits.restart_autoneg = 1;
2062 
2063 	} else {
2064 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
2065 		bmcr.bits.speed_1000_sel =
2066 			param_arr[param_anar_1000fdx].value |
2067 				param_arr[param_anar_1000hdx].value;
2068 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
2069 			(param_arr[param_anar_100fdx].value |
2070 				param_arr[param_anar_100hdx].value);
2071 		if (bmcr.bits.speed_1000_sel) {
2072 			statsp->mac_stats.link_speed = 1000;
2073 			gcr.value = 0;
2074 			gcr.bits.ms_mode_en =
2075 				param_arr[param_master_cfg_enable].value;
2076 			gcr.bits.master =
2077 				param_arr[param_master_cfg_value].value;
2078 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2079 				(uint8_t)(uint64_t)(&mii_regs->gcr),
2080 				gcr.value))
2081 				!= NXGE_OK)
2082 				goto fail;
2083 			if (param_arr[param_anar_1000fdx].value) {
2084 				bmcr.bits.duplex_mode = 1;
2085 				statsp->mac_stats.link_duplex = 2;
2086 			} else
2087 				statsp->mac_stats.link_duplex = 1;
2088 		} else if (bmcr.bits.speed_sel) {
2089 			statsp->mac_stats.link_speed = 100;
2090 			if (param_arr[param_anar_100fdx].value) {
2091 				bmcr.bits.duplex_mode = 1;
2092 				statsp->mac_stats.link_duplex = 2;
2093 			} else
2094 				statsp->mac_stats.link_duplex = 1;
2095 		} else {
2096 			statsp->mac_stats.link_speed = 10;
2097 			if (param_arr[param_anar_10fdx].value) {
2098 				bmcr.bits.duplex_mode = 1;
2099 				statsp->mac_stats.link_duplex = 2;
2100 			} else
2101 				statsp->mac_stats.link_duplex = 1;
2102 		}
2103 		if (statsp->mac_stats.link_duplex != 1) {
2104 			statsp->mac_stats.link_asmpause =
2105 						statsp->mac_stats.cap_asmpause;
2106 			statsp->mac_stats.link_pause =
2107 						statsp->mac_stats.cap_pause;
2108 		}
2109 
2110 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
2111 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
2112 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
2113 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
2114 				/* BCM5464R 1000mbps external loopback mode */
2115 				gcr.value = 0;
2116 				gcr.bits.ms_mode_en = 1;
2117 				gcr.bits.master = 1;
2118 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
2119 					(uint8_t)(uint64_t)(&mii_regs->gcr),
2120 					gcr.value))
2121 					!= NXGE_OK)
2122 					goto fail;
2123 				bmcr.value = 0;
2124 				bmcr.bits.speed_1000_sel = 1;
2125 				statsp->mac_stats.link_speed = 1000;
2126 			} else if (statsp->port_stats.lb_mode
2127 			    == nxge_lb_ext100) {
2128 				/* BCM5464R 100mbps external loopback mode */
2129 				bmcr.value = 0;
2130 				bmcr.bits.speed_sel = 1;
2131 				bmcr.bits.duplex_mode = 1;
2132 				statsp->mac_stats.link_speed = 100;
2133 			} else if (statsp->port_stats.lb_mode
2134 			    == nxge_lb_ext10) {
2135 				/* BCM5464R 10mbps external loopback mode */
2136 				bmcr.value = 0;
2137 				bmcr.bits.duplex_mode = 1;
2138 				statsp->mac_stats.link_speed = 10;
2139 			}
2140 		}
2141 	}
2142 
2143 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2144 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
2145 			bmcr.value)) != NXGE_OK)
2146 		goto fail;
2147 
2148 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2149 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
2150 		goto fail;
2151 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
2152 
2153 	/*
2154 	 * Initialize the xcvr status kept in the context structure.
2155 	 */
2156 	nxgep->soft_bmsr.value = 0;
2157 
2158 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2159 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
2160 			&nxgep->bmsr.value)) != NXGE_OK)
2161 		goto fail;
2162 
2163 	statsp->mac_stats.xcvr_inits++;
2164 	nxgep->bmsr.value = 0;
2165 
2166 fail:
2167 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2168 			"<== nxge_mii_xcvr_init status 0x%x", status));
2169 	return (status);
2170 }
2171 
2172 /* Read from a MII compliant register */
2173 
2174 nxge_status_t
2175 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
2176 		uint16_t *value)
2177 {
2178 	npi_status_t rs = NPI_SUCCESS;
2179 
2180 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
2181 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
2182 
2183 	MUTEX_ENTER(&nxge_mii_lock);
2184 
2185 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
2186 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
2187 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2188 			goto fail;
2189 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
2190 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
2191 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2192 			goto fail;
2193 	} else
2194 		goto fail;
2195 
2196 	MUTEX_EXIT(&nxge_mii_lock);
2197 
2198 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
2199 			"xcvr_reg<%d> value=0x%x",
2200 			xcvr_portn, xcvr_reg, *value));
2201 	return (NXGE_OK);
2202 fail:
2203 	MUTEX_EXIT(&nxge_mii_lock);
2204 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2205 			"nxge_mii_read: Failed to read mii on xcvr %d",
2206 			xcvr_portn));
2207 
2208 	return (NXGE_ERROR | rs);
2209 }
2210 
2211 /* Write to a MII compliant Register */
2212 
2213 nxge_status_t
2214 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
2215 		uint16_t value)
2216 {
2217 	npi_status_t rs = NPI_SUCCESS;
2218 
2219 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
2220 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
2221 			value));
2222 
2223 	MUTEX_ENTER(&nxge_mii_lock);
2224 
2225 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
2226 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
2227 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2228 			goto fail;
2229 	} else if (nxgep->mac.portmode == PORT_1G_FIBER) {
2230 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
2231 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2232 			goto fail;
2233 	} else
2234 		goto fail;
2235 
2236 	MUTEX_EXIT(&nxge_mii_lock);
2237 
2238 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
2239 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
2240 	return (NXGE_OK);
2241 fail:
2242 	MUTEX_EXIT(&nxge_mii_lock);
2243 
2244 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2245 			"nxge_mii_write: Failed to write mii on xcvr %d",
2246 			xcvr_portn));
2247 
2248 	return (NXGE_ERROR | rs);
2249 }
2250 
2251 /* Perform read from Clause45 serdes / transceiver device */
2252 
2253 nxge_status_t
2254 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
2255 		uint16_t xcvr_reg, uint16_t *value)
2256 {
2257 	npi_status_t rs = NPI_SUCCESS;
2258 
2259 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
2260 			xcvr_portn));
2261 
2262 	MUTEX_ENTER(&nxge_mdio_lock);
2263 
2264 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
2265 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
2266 		goto fail;
2267 
2268 	MUTEX_EXIT(&nxge_mdio_lock);
2269 
2270 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
2271 			xcvr_portn));
2272 	return (NXGE_OK);
2273 fail:
2274 	MUTEX_EXIT(&nxge_mdio_lock);
2275 
2276 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2277 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
2278 			xcvr_portn));
2279 
2280 	return (NXGE_ERROR | rs);
2281 }
2282 
2283 /* Perform write to Clause45 serdes / transceiver device */
2284 
2285 nxge_status_t
2286 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
2287 		uint16_t xcvr_reg, uint16_t value)
2288 {
2289 	npi_status_t rs = NPI_SUCCESS;
2290 
2291 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
2292 			xcvr_portn));
2293 
2294 	MUTEX_ENTER(&nxge_mdio_lock);
2295 
2296 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
2297 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
2298 		goto fail;
2299 
2300 	MUTEX_EXIT(&nxge_mdio_lock);
2301 
2302 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
2303 			xcvr_portn));
2304 	return (NXGE_OK);
2305 fail:
2306 	MUTEX_EXIT(&nxge_mdio_lock);
2307 
2308 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2309 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
2310 			xcvr_portn));
2311 
2312 	return (NXGE_ERROR | rs);
2313 }
2314 
2315 
2316 /* Check MII to see if there is any link status change */
2317 
2318 nxge_status_t
2319 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
2320 		nxge_link_state_t *link_up)
2321 {
2322 	p_nxge_param_t	param_arr;
2323 	p_nxge_stats_t	statsp;
2324 	p_mii_regs_t	mii_regs;
2325 	p_mii_bmsr_t	soft_bmsr;
2326 	mii_anar_t	anar;
2327 	mii_anlpar_t	anlpar;
2328 	mii_anar_t	an_common;
2329 	mii_aner_t	aner;
2330 	mii_gsr_t	gsr;
2331 	nxge_status_t	status = NXGE_OK;
2332 
2333 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
2334 
2335 	mii_regs = NULL;
2336 	param_arr = nxgep->param_arr;
2337 	statsp = nxgep->statsp;
2338 	soft_bmsr = &nxgep->soft_bmsr;
2339 	*link_up = LINK_NO_CHANGE;
2340 
2341 	if (bmsr_ints.bits.link_status) {
2342 		if (bmsr.bits.link_status) {
2343 			soft_bmsr->bits.link_status = 1;
2344 		} else {
2345 			statsp->mac_stats.link_up = 0;
2346 			soft_bmsr->bits.link_status = 0;
2347 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2348 					"Link down cable problem"));
2349 			*link_up = LINK_IS_DOWN;
2350 		}
2351 	}
2352 
2353 	if (param_arr[param_autoneg].value) {
2354 		if (bmsr_ints.bits.auto_neg_complete) {
2355 			if (bmsr.bits.auto_neg_complete)
2356 				soft_bmsr->bits.auto_neg_complete = 1;
2357 			else
2358 				soft_bmsr->bits.auto_neg_complete = 0;
2359 		}
2360 		if (soft_bmsr->bits.link_status == 0) {
2361 			statsp->mac_stats.link_T4 = 0;
2362 			statsp->mac_stats.link_speed = 0;
2363 			statsp->mac_stats.link_duplex = 0;
2364 			statsp->mac_stats.link_asmpause = 0;
2365 			statsp->mac_stats.link_pause = 0;
2366 			statsp->mac_stats.lp_cap_autoneg = 0;
2367 			statsp->mac_stats.lp_cap_100T4 = 0;
2368 			statsp->mac_stats.lp_cap_1000fdx = 0;
2369 			statsp->mac_stats.lp_cap_1000hdx = 0;
2370 			statsp->mac_stats.lp_cap_100fdx = 0;
2371 			statsp->mac_stats.lp_cap_100hdx = 0;
2372 			statsp->mac_stats.lp_cap_10fdx = 0;
2373 			statsp->mac_stats.lp_cap_10hdx = 0;
2374 			statsp->mac_stats.lp_cap_10gfdx = 0;
2375 			statsp->mac_stats.lp_cap_10ghdx = 0;
2376 			statsp->mac_stats.lp_cap_asmpause = 0;
2377 			statsp->mac_stats.lp_cap_pause = 0;
2378 		}
2379 	} else
2380 		soft_bmsr->bits.auto_neg_complete = 1;
2381 
2382 	if ((bmsr_ints.bits.link_status ||
2383 		bmsr_ints.bits.auto_neg_complete) &&
2384 		soft_bmsr->bits.link_status &&
2385 		soft_bmsr->bits.auto_neg_complete) {
2386 		statsp->mac_stats.link_up = 1;
2387 		if (param_arr[param_autoneg].value) {
2388 			if ((status = nxge_mii_read(nxgep,
2389 				statsp->mac_stats.xcvr_portn,
2390 				(uint8_t)(uint64_t)(&mii_regs->anar),
2391 					&anar.value)) != NXGE_OK)
2392 				goto fail;
2393 			if ((status = nxge_mii_read(nxgep,
2394 				statsp->mac_stats.xcvr_portn,
2395 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
2396 					&anlpar.value)) != NXGE_OK)
2397 				goto fail;
2398 			if ((status = nxge_mii_read(nxgep,
2399 				statsp->mac_stats.xcvr_portn,
2400 				(uint8_t)(uint64_t)(&mii_regs->aner),
2401 					&aner.value)) != NXGE_OK)
2402 				goto fail;
2403 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
2404 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
2405 			statsp->mac_stats.lp_cap_100fdx =
2406 							anlpar.bits.cap_100fdx;
2407 			statsp->mac_stats.lp_cap_100hdx =
2408 							anlpar.bits.cap_100hdx;
2409 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
2410 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
2411 			statsp->mac_stats.lp_cap_asmpause =
2412 						anlpar.bits.cap_asmpause;
2413 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
2414 			an_common.value = anar.value & anlpar.value;
2415 			if (param_arr[param_anar_1000fdx].value ||
2416 				param_arr[param_anar_1000hdx].value) {
2417 				if ((status = nxge_mii_read(nxgep,
2418 					statsp->mac_stats.xcvr_portn,
2419 					(uint8_t)(uint64_t)(&mii_regs->gsr),
2420 						&gsr.value))
2421 						!= NXGE_OK)
2422 					goto fail;
2423 				statsp->mac_stats.lp_cap_1000fdx =
2424 					gsr.bits.link_1000fdx;
2425 				statsp->mac_stats.lp_cap_1000hdx =
2426 					gsr.bits.link_1000hdx;
2427 				if (param_arr[param_anar_1000fdx].value &&
2428 					gsr.bits.link_1000fdx) {
2429 					statsp->mac_stats.link_speed = 1000;
2430 					statsp->mac_stats.link_duplex = 2;
2431 				} else if (
2432 					param_arr[param_anar_1000hdx].value &&
2433 						gsr.bits.link_1000hdx) {
2434 					statsp->mac_stats.link_speed = 1000;
2435 					statsp->mac_stats.link_duplex = 1;
2436 				}
2437 			}
2438 			if ((an_common.value != 0) &&
2439 					!(statsp->mac_stats.link_speed)) {
2440 				if (an_common.bits.cap_100T4) {
2441 					statsp->mac_stats.link_T4 = 1;
2442 					statsp->mac_stats.link_speed = 100;
2443 					statsp->mac_stats.link_duplex = 1;
2444 				} else if (an_common.bits.cap_100fdx) {
2445 					statsp->mac_stats.link_speed = 100;
2446 					statsp->mac_stats.link_duplex = 2;
2447 				} else if (an_common.bits.cap_100hdx) {
2448 					statsp->mac_stats.link_speed = 100;
2449 					statsp->mac_stats.link_duplex = 1;
2450 				} else if (an_common.bits.cap_10fdx) {
2451 					statsp->mac_stats.link_speed = 10;
2452 					statsp->mac_stats.link_duplex = 2;
2453 				} else if (an_common.bits.cap_10hdx) {
2454 					statsp->mac_stats.link_speed = 10;
2455 					statsp->mac_stats.link_duplex = 1;
2456 				} else {
2457 					goto fail;
2458 				}
2459 			}
2460 			if (statsp->mac_stats.link_duplex != 1) {
2461 				statsp->mac_stats.link_asmpause =
2462 					an_common.bits.cap_asmpause;
2463 				if (statsp->mac_stats.link_asmpause)
2464 				if ((statsp->mac_stats.cap_pause == 0) &&
2465 						(statsp->mac_stats.lp_cap_pause
2466 						== 1))
2467 						statsp->mac_stats.link_pause
2468 						= 0;
2469 					else
2470 						statsp->mac_stats.link_pause
2471 						= 1;
2472 				else
2473 					statsp->mac_stats.link_pause =
2474 						an_common.bits.cap_pause;
2475 			}
2476 		}
2477 		*link_up = LINK_IS_UP;
2478 	}
2479 
2480 	if (nxgep->link_notify) {
2481 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
2482 				LINK_IS_DOWN);
2483 		nxgep->link_notify = B_FALSE;
2484 	}
2485 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
2486 	return (NXGE_OK);
2487 fail:
2488 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2489 			"nxge_mii_check: Unable to check MII"));
2490 	return (status);
2491 }
2492 
2493 /* Add a multicast address entry into the HW hash table */
2494 
2495 nxge_status_t
2496 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
2497 {
2498 	uint32_t mchash;
2499 	p_hash_filter_t hash_filter;
2500 	uint16_t hash_bit;
2501 	boolean_t rx_init = B_FALSE;
2502 	uint_t j;
2503 	nxge_status_t status = NXGE_OK;
2504 
2505 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
2506 
2507 	RW_ENTER_WRITER(&nxgep->filter_lock);
2508 	mchash = crc32_mchash(addrp);
2509 	if (nxgep->hash_filter == NULL) {
2510 		NXGE_DEBUG_MSG((NULL, STR_CTL,
2511 			"Allocating hash filter storage."));
2512 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
2513 					KM_SLEEP);
2514 	}
2515 	hash_filter = nxgep->hash_filter;
2516 	j = mchash / HASH_REG_WIDTH;
2517 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
2518 	hash_filter->hash_filter_regs[j] |= hash_bit;
2519 	hash_filter->hash_bit_ref_cnt[mchash]++;
2520 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
2521 		hash_filter->hash_ref_cnt++;
2522 		rx_init = B_TRUE;
2523 	}
2524 	if (rx_init) {
2525 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
2526 			goto fail;
2527 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
2528 			goto fail;
2529 	}
2530 
2531 	RW_EXIT(&nxgep->filter_lock);
2532 
2533 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
2534 
2535 	return (NXGE_OK);
2536 fail:
2537 	RW_EXIT(&nxgep->filter_lock);
2538 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
2539 					"Unable to add multicast address"));
2540 	return (status);
2541 }
2542 
2543 /* Remove a multicast address entry from the HW hash table */
2544 
2545 nxge_status_t
2546 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
2547 {
2548 	uint32_t mchash;
2549 	p_hash_filter_t hash_filter;
2550 	uint16_t hash_bit;
2551 	boolean_t rx_init = B_FALSE;
2552 	uint_t j;
2553 	nxge_status_t status = NXGE_OK;
2554 
2555 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
2556 	RW_ENTER_WRITER(&nxgep->filter_lock);
2557 	mchash = crc32_mchash(addrp);
2558 	if (nxgep->hash_filter == NULL) {
2559 		NXGE_DEBUG_MSG((NULL, STR_CTL,
2560 			"Hash filter already de_allocated."));
2561 		RW_EXIT(&nxgep->filter_lock);
2562 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
2563 		return (NXGE_OK);
2564 	}
2565 	hash_filter = nxgep->hash_filter;
2566 	hash_filter->hash_bit_ref_cnt[mchash]--;
2567 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
2568 		j = mchash / HASH_REG_WIDTH;
2569 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
2570 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
2571 		hash_filter->hash_ref_cnt--;
2572 		rx_init = B_TRUE;
2573 	}
2574 	if (hash_filter->hash_ref_cnt == 0) {
2575 		NXGE_DEBUG_MSG((NULL, STR_CTL,
2576 			"De-allocating hash filter storage."));
2577 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
2578 		nxgep->hash_filter = NULL;
2579 	}
2580 
2581 	if (rx_init) {
2582 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
2583 			goto fail;
2584 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
2585 			goto fail;
2586 	}
2587 	RW_EXIT(&nxgep->filter_lock);
2588 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
2589 
2590 	return (NXGE_OK);
2591 fail:
2592 	RW_EXIT(&nxgep->filter_lock);
2593 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
2594 			"Unable to remove multicast address"));
2595 
2596 	return (status);
2597 }
2598 
2599 /* Set MAC address into MAC address HW registers */
2600 
2601 nxge_status_t
2602 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
2603 {
2604 	nxge_status_t status = NXGE_OK;
2605 
2606 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
2607 
2608 	MUTEX_ENTER(&nxgep->ouraddr_lock);
2609 	/*
2610 	 * Exit if the address is same as ouraddr or multicast or broadcast
2611 	 */
2612 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
2613 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
2614 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
2615 		goto nxge_set_mac_addr_exit;
2616 	}
2617 	nxgep->ouraddr = *addrp;
2618 	/*
2619 	 * Set new interface local address and re-init device.
2620 	 * This is destructive to any other streams attached
2621 	 * to this device.
2622 	 */
2623 	RW_ENTER_WRITER(&nxgep->filter_lock);
2624 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
2625 		goto fail;
2626 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
2627 		goto fail;
2628 
2629 	RW_EXIT(&nxgep->filter_lock);
2630 	MUTEX_EXIT(&nxgep->ouraddr_lock);
2631 	goto nxge_set_mac_addr_end;
2632 nxge_set_mac_addr_exit:
2633 	MUTEX_EXIT(&nxgep->ouraddr_lock);
2634 nxge_set_mac_addr_end:
2635 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
2636 
2637 	return (NXGE_OK);
2638 fail:
2639 	MUTEX_EXIT(&nxgep->ouraddr_lock);
2640 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
2641 			"Unable to set mac address"));
2642 	return (status);
2643 }
2644 
2645 static
2646 check_link_state_t
2647 nxge_check_link_stop(
2648 	nxge_t *nxge)
2649 {
2650 	/* If the poll has been cancelled, return STOP. */
2651 	MUTEX_ENTER(&nxge->poll_lock);
2652 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
2653 		nxge->poll_state = LINK_MONITOR_STOP;
2654 		nxge->nxge_link_poll_timerid = 0;
2655 		cv_broadcast(&nxge->poll_cv);
2656 		MUTEX_EXIT(&nxge->poll_lock);
2657 
2658 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
2659 		    "nxge_check_%s_link(port<%d>) stopped.",
2660 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
2661 		    nxge->mac.portnum));
2662 		return (CHECK_LINK_STOP);
2663 	}
2664 	MUTEX_EXIT(&nxge->poll_lock);
2665 
2666 	return (CHECK_LINK_RESCHEDULE);
2667 }
2668 
2669 /* Check status of MII (MIF or PCS) link */
2670 
2671 static nxge_status_t
2672 nxge_check_mii_link(p_nxge_t nxgep)
2673 {
2674 	mii_bmsr_t bmsr_ints, bmsr_data;
2675 	mii_anlpar_t anlpar;
2676 	mii_gsr_t gsr;
2677 	p_mii_regs_t mii_regs;
2678 	nxge_status_t status = NXGE_OK;
2679 	uint8_t portn;
2680 	nxge_link_state_t link_up;
2681 
2682 	if (nxgep->nxge_magic != NXGE_MAGIC)
2683 		return (NXGE_ERROR);
2684 
2685 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2686 		return (NXGE_OK);
2687 
2688 	portn = nxgep->mac.portnum;
2689 
2690 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
2691 	    portn));
2692 
2693 	mii_regs = NULL;
2694 
2695 	RW_ENTER_WRITER(&nxgep->filter_lock);
2696 
2697 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
2698 		goto nxge_check_mii_link_exit;
2699 
2700 	if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
2701 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
2702 		&bmsr_data.value)) != NXGE_OK)
2703 		goto fail;
2704 
2705 	if (nxgep->param_arr[param_autoneg].value) {
2706 		if ((status = nxge_mii_read(nxgep,
2707 			nxgep->statsp->mac_stats.xcvr_portn,
2708 			(uint8_t)(uint64_t)(&mii_regs->gsr),
2709 			&gsr.value)) != NXGE_OK)
2710 			goto fail;
2711 		if ((status = nxge_mii_read(nxgep,
2712 			nxgep->statsp->mac_stats.xcvr_portn,
2713 			(uint8_t)(uint64_t)(&mii_regs->anlpar),
2714 			&anlpar.value)) != NXGE_OK)
2715 			goto fail;
2716 		if (nxgep->statsp->mac_stats.link_up &&
2717 			((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
2718 				gsr.bits.link_1000fdx) ||
2719 			(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
2720 				gsr.bits.link_1000hdx) ||
2721 			(nxgep->statsp->mac_stats.lp_cap_100T4 ^
2722 				anlpar.bits.cap_100T4) ||
2723 			(nxgep->statsp->mac_stats.lp_cap_100fdx ^
2724 				anlpar.bits.cap_100fdx) ||
2725 			(nxgep->statsp->mac_stats.lp_cap_100hdx ^
2726 				anlpar.bits.cap_100hdx) ||
2727 			(nxgep->statsp->mac_stats.lp_cap_10fdx ^
2728 				anlpar.bits.cap_10fdx) ||
2729 			(nxgep->statsp->mac_stats.lp_cap_10hdx ^
2730 				anlpar.bits.cap_10hdx))) {
2731 			bmsr_data.bits.link_status = 0;
2732 		}
2733 	}
2734 
2735 	/* Workaround for link down issue */
2736 	if (bmsr_data.value == 0) {
2737 		cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n",
2738 		    nxgep->instance);
2739 		goto nxge_check_mii_link_exit;
2740 	}
2741 
2742 	bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
2743 	nxgep->bmsr.value = bmsr_data.value;
2744 	if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up))
2745 	    != NXGE_OK)
2746 		goto fail;
2747 
2748 nxge_check_mii_link_exit:
2749 	RW_EXIT(&nxgep->filter_lock);
2750 	if (link_up == LINK_IS_UP) {
2751 		nxge_link_is_up(nxgep);
2752 	} else if (link_up == LINK_IS_DOWN) {
2753 		nxge_link_is_down(nxgep);
2754 	}
2755 
2756 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2757 
2758 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
2759 	    portn));
2760 	return (NXGE_OK);
2761 
2762 fail:
2763 	RW_EXIT(&nxgep->filter_lock);
2764 
2765 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2766 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2767 	    "nxge_check_mii_link: Failed to check link port<%d>",
2768 	    portn));
2769 	return (status);
2770 }
2771 
2772 
2773 /*ARGSUSED*/
2774 static nxge_status_t
2775 nxge_check_10g_link(p_nxge_t nxgep)
2776 {
2777 	uint8_t		portn;
2778 
2779 	nxge_status_t	status = NXGE_OK;
2780 	boolean_t	link_up;
2781 
2782 	if (nxgep->nxge_magic != NXGE_MAGIC)
2783 		return (NXGE_ERROR);
2784 
2785 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2786 		return (NXGE_OK);
2787 
2788 	portn = nxgep->mac.portnum;
2789 
2790 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
2791 	    portn));
2792 
2793 	status = nxge_check_bcm8704_link(nxgep, &link_up);
2794 
2795 	if (status != NXGE_OK)
2796 		goto fail;
2797 
2798 	if (link_up) {
2799 		if (nxgep->link_notify ||
2800 			nxgep->statsp->mac_stats.link_up == 0) {
2801 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
2802 				goto fail;
2803 			nxgep->statsp->mac_stats.link_up = 1;
2804 			nxgep->statsp->mac_stats.link_speed = 10000;
2805 			nxgep->statsp->mac_stats.link_duplex = 2;
2806 
2807 			nxge_link_is_up(nxgep);
2808 			nxgep->link_notify = B_FALSE;
2809 		}
2810 	} else {
2811 		if (nxgep->link_notify ||
2812 			nxgep->statsp->mac_stats.link_up == 1) {
2813 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
2814 				goto fail;
2815 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2816 			    "Link down cable problem"));
2817 			nxgep->statsp->mac_stats.link_up = 0;
2818 			nxgep->statsp->mac_stats.link_speed = 0;
2819 			nxgep->statsp->mac_stats.link_duplex = 0;
2820 
2821 			nxge_link_is_down(nxgep);
2822 			nxgep->link_notify = B_FALSE;
2823 		}
2824 	}
2825 
2826 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
2827 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
2828 	    portn));
2829 	return (NXGE_OK);
2830 
2831 fail:
2832 	(void) nxge_check_link_stop(nxgep);
2833 
2834 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2835 	    "nxge_check_10g_link: Failed to check link port<%d>",
2836 	    portn));
2837 	return (status);
2838 }
2839 
2840 
2841 /* Declare link down */
2842 
2843 void
2844 nxge_link_is_down(p_nxge_t nxgep)
2845 {
2846 	p_nxge_stats_t statsp;
2847 	char link_stat_msg[64];
2848 
2849 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
2850 
2851 	statsp = nxgep->statsp;
2852 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
2853 	    statsp->mac_stats.xcvr_portn);
2854 
2855 	if (nxge_no_msg == B_FALSE) {
2856 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2857 	}
2858 
2859 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
2860 
2861 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
2862 }
2863 
2864 /* Declare link up */
2865 
2866 void
2867 nxge_link_is_up(p_nxge_t nxgep)
2868 {
2869 	p_nxge_stats_t statsp;
2870 	char link_stat_msg[64];
2871 	uint32_t val;
2872 
2873 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
2874 
2875 	statsp = nxgep->statsp;
2876 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
2877 	    statsp->mac_stats.xcvr_portn,
2878 	    statsp->mac_stats.link_speed);
2879 
2880 	if (statsp->mac_stats.link_T4)
2881 		(void) strcat(link_stat_msg, "T4");
2882 	else if (statsp->mac_stats.link_duplex == 2)
2883 		(void) strcat(link_stat_msg, "full duplex");
2884 	else
2885 		(void) strcat(link_stat_msg, "half duplex");
2886 
2887 	(void) nxge_xif_init(nxgep);
2888 
2889 	/* Clean up symbol errors incurred during link transition */
2890 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
2891 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
2892 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
2893 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
2894 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
2895 	}
2896 
2897 	if (nxge_no_msg == B_FALSE) {
2898 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
2899 	}
2900 
2901 	mac_link_update(nxgep->mach, LINK_STATE_UP);
2902 
2903 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
2904 }
2905 
2906 /*
2907  * Calculate the bit in the multicast address filter
2908  * that selects the given * address.
2909  * Note: For GEM, the last 8-bits are used.
2910  */
2911 uint32_t
2912 crc32_mchash(p_ether_addr_t addr)
2913 {
2914 	uint8_t *cp;
2915 	uint32_t crc;
2916 	uint32_t c;
2917 	int byte;
2918 	int bit;
2919 
2920 	cp = (uint8_t *)addr;
2921 	crc = (uint32_t)0xffffffff;
2922 	for (byte = 0; byte < 6; byte++) {
2923 		c = (uint32_t)cp[byte];
2924 		for (bit = 0; bit < 8; bit++) {
2925 			if ((c & 0x1) ^ (crc & 0x1))
2926 				crc = (crc >> 1)^0xedb88320;
2927 			else
2928 				crc = (crc >> 1);
2929 			c >>= 1;
2930 		}
2931 	}
2932 	return ((~crc) >> (32 - HASH_BITS));
2933 }
2934 
2935 /* Reset serdes */
2936 
2937 nxge_status_t
2938 nxge_serdes_reset(p_nxge_t nxgep)
2939 {
2940 	npi_handle_t		handle;
2941 
2942 	handle = nxgep->npi_handle;
2943 
2944 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
2945 	drv_usecwait(500);
2946 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
2947 
2948 	return (NXGE_OK);
2949 }
2950 
2951 /* Monitor link status using interrupt or polling */
2952 
2953 nxge_status_t
2954 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
2955 {
2956 	nxge_status_t status = NXGE_OK;
2957 
2958 	/*
2959 	 * Return immediately if this is an imaginary XMAC port.
2960 	 * (At least, we don't have 4-port XMAC cards yet.)
2961 	 */
2962 	if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1))
2963 		return (NXGE_OK);
2964 
2965 	if (nxgep->statsp == NULL) {
2966 		/* stats has not been allocated. */
2967 		return (NXGE_OK);
2968 	}
2969 	/* Don't check link if we're not in internal loopback mode */
2970 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
2971 		return (NXGE_OK);
2972 
2973 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2974 	    "==> nxge_link_monitor port<%d> enable=%d",
2975 	    nxgep->mac.portnum, enable));
2976 	if (enable == LINK_MONITOR_START) {
2977 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
2978 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
2979 			    != NXGE_OK)
2980 				goto fail;
2981 		} else {
2982 			timeout_id_t timerid;
2983 
2984 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
2985 				return (NXGE_OK);
2986 
2987 			if (nxgep->xcvr.check_link) {
2988 				timerid = timeout(
2989 				    (fptrv_t)(nxgep->xcvr.check_link),
2990 				    nxgep,
2991 				    drv_usectohz(LINK_MONITOR_PERIOD));
2992 				MUTEX_ENTER(&nxgep->poll_lock);
2993 				nxgep->nxge_link_poll_timerid = timerid;
2994 				MUTEX_EXIT(&nxgep->poll_lock);
2995 			} else {
2996 				return (NXGE_ERROR);
2997 			}
2998 		}
2999 	} else {
3000 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
3001 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
3002 			    != NXGE_OK)
3003 				goto fail;
3004 		} else {
3005 			clock_t rv;
3006 
3007 			MUTEX_ENTER(&nxgep->poll_lock);
3008 
3009 			/* If <timerid> == 0, the link monitor has */
3010 			/* never been started, or just now stopped. */
3011 			if (nxgep->nxge_link_poll_timerid == 0) {
3012 				MUTEX_EXIT(&nxgep->poll_lock);
3013 				return (NXGE_OK);
3014 			}
3015 
3016 			nxgep->poll_state = LINK_MONITOR_STOPPING;
3017 			rv = cv_timedwait(&nxgep->poll_cv,
3018 			    &nxgep->poll_lock,
3019 			    ddi_get_lbolt() +
3020 			    drv_usectohz(LM_WAIT_MULTIPLIER *
3021 			    LINK_MONITOR_PERIOD));
3022 			if (rv == -1) {
3023 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3024 				    "==> stopping port %d: "
3025 				    "cv_timedwait(%d) timed out",
3026 				    nxgep->mac.portnum, nxgep->poll_state));
3027 				nxgep->poll_state = LINK_MONITOR_STOP;
3028 				nxgep->nxge_link_poll_timerid = 0;
3029 			}
3030 
3031 			MUTEX_EXIT(&nxgep->poll_lock);
3032 		}
3033 	}
3034 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3035 	    "<== nxge_link_monitor port<%d> enable=%d",
3036 	    nxgep->mac.portnum, enable));
3037 	return (NXGE_OK);
3038 fail:
3039 	return (status);
3040 }
3041 
3042 /* Set promiscous mode */
3043 
3044 nxge_status_t
3045 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
3046 {
3047 	nxge_status_t status = NXGE_OK;
3048 
3049 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
3050 
3051 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
3052 
3053 	RW_ENTER_WRITER(&nxgep->filter_lock);
3054 
3055 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
3056 		goto fail;
3057 	}
3058 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
3059 		goto fail;
3060 	}
3061 
3062 	RW_EXIT(&nxgep->filter_lock);
3063 
3064 	if (on)
3065 		nxgep->statsp->mac_stats.promisc = B_TRUE;
3066 	else
3067 		nxgep->statsp->mac_stats.promisc = B_FALSE;
3068 
3069 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
3070 
3071 	return (NXGE_OK);
3072 fail:
3073 	RW_EXIT(&nxgep->filter_lock);
3074 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
3075 	    "Unable to set promisc (%d)", on));
3076 
3077 	return (status);
3078 }
3079 
3080 /*ARGSUSED*/
3081 uint_t
3082 nxge_mif_intr(void *arg1, void *arg2)
3083 {
3084 #ifdef	NXGE_DEBUG
3085 	p_nxge_t		nxgep = (p_nxge_t)arg2;
3086 #endif
3087 #if NXGE_MIF
3088 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
3089 	uint32_t		status;
3090 	npi_handle_t		handle;
3091 	uint8_t			portn;
3092 	p_nxge_stats_t		statsp;
3093 #endif
3094 
3095 #ifdef	NXGE_MIF
3096 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
3097 		nxgep = ldvp->nxgep;
3098 	}
3099 	nxgep = ldvp->nxgep;
3100 #endif
3101 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
3102 
3103 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
3104 	return (DDI_INTR_CLAIMED);
3105 
3106 mif_intr_fail:
3107 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
3108 	return (DDI_INTR_UNCLAIMED);
3109 }
3110 
3111 /*ARGSUSED*/
3112 uint_t
3113 nxge_mac_intr(void *arg1, void *arg2)
3114 {
3115 	p_nxge_t		nxgep = (p_nxge_t)arg2;
3116 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
3117 	p_nxge_ldg_t		ldgp;
3118 	uint32_t		status;
3119 	npi_handle_t		handle;
3120 	uint8_t			portn;
3121 	p_nxge_stats_t		statsp;
3122 	npi_status_t		rs = NPI_SUCCESS;
3123 
3124 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
3125 		nxgep = ldvp->nxgep;
3126 	}
3127 
3128 	ldgp = ldvp->ldgp;
3129 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
3130 	    "group %d", ldgp->ldg));
3131 
3132 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3133 	/*
3134 	 * This interrupt handler is for a specific
3135 	 * mac port.
3136 	 */
3137 	statsp = (p_nxge_stats_t)nxgep->statsp;
3138 	portn = nxgep->mac.portnum;
3139 
3140 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3141 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
3142 
3143 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3144 		rs = npi_xmac_tx_get_istatus(handle, portn,
3145 					(xmac_tx_iconfig_t *)&status);
3146 		if (rs != NPI_SUCCESS)
3147 			goto npi_fail;
3148 		if (status & ICFG_XMAC_TX_ALL) {
3149 			if (status & ICFG_XMAC_TX_UNDERRUN) {
3150 				statsp->xmac_stats.tx_underflow_err++;
3151 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3152 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
3153 			}
3154 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
3155 				statsp->xmac_stats.tx_maxpktsize_err++;
3156 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3157 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
3158 			}
3159 			if (status & ICFG_XMAC_TX_OVERFLOW) {
3160 				statsp->xmac_stats.tx_overflow_err++;
3161 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3162 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
3163 			}
3164 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
3165 				statsp->xmac_stats.tx_fifo_xfr_err++;
3166 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3167 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
3168 			}
3169 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
3170 				statsp->xmac_stats.tx_byte_cnt +=
3171 							XTXMAC_BYTE_CNT_MASK;
3172 			}
3173 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
3174 				statsp->xmac_stats.tx_frame_cnt +=
3175 							XTXMAC_FRM_CNT_MASK;
3176 			}
3177 		}
3178 
3179 		rs = npi_xmac_rx_get_istatus(handle, portn,
3180 					(xmac_rx_iconfig_t *)&status);
3181 		if (rs != NPI_SUCCESS)
3182 			goto npi_fail;
3183 		if (status & ICFG_XMAC_RX_ALL) {
3184 			if (status & ICFG_XMAC_RX_OVERFLOW)
3185 				statsp->xmac_stats.rx_overflow_err++;
3186 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
3187 				statsp->xmac_stats.rx_underflow_err++;
3188 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3189 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
3190 			}
3191 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
3192 				statsp->xmac_stats.rx_crc_err_cnt +=
3193 							XRXMAC_CRC_ER_CNT_MASK;
3194 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3195 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
3196 			}
3197 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
3198 				statsp->xmac_stats.rx_len_err_cnt +=
3199 							MAC_LEN_ER_CNT_MASK;
3200 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3201 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
3202 			}
3203 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
3204 				statsp->xmac_stats.rx_viol_err_cnt +=
3205 							XRXMAC_CD_VIO_CNT_MASK;
3206 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3207 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
3208 			}
3209 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
3210 				statsp->xmac_stats.rx_byte_cnt +=
3211 							XRXMAC_BT_CNT_MASK;
3212 			}
3213 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
3214 				statsp->xmac_stats.rx_hist1_cnt +=
3215 							XRXMAC_HIST_CNT1_MASK;
3216 			}
3217 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
3218 				statsp->xmac_stats.rx_hist2_cnt +=
3219 							XRXMAC_HIST_CNT2_MASK;
3220 			}
3221 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
3222 				statsp->xmac_stats.rx_hist3_cnt +=
3223 							XRXMAC_HIST_CNT3_MASK;
3224 			}
3225 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
3226 				statsp->xmac_stats.rx_hist4_cnt +=
3227 							XRXMAC_HIST_CNT4_MASK;
3228 			}
3229 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
3230 				statsp->xmac_stats.rx_hist5_cnt +=
3231 							XRXMAC_HIST_CNT5_MASK;
3232 			}
3233 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
3234 				statsp->xmac_stats.rx_hist6_cnt +=
3235 							XRXMAC_HIST_CNT6_MASK;
3236 			}
3237 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
3238 				statsp->xmac_stats.rx_broadcast_cnt +=
3239 							XRXMAC_BC_FRM_CNT_MASK;
3240 			}
3241 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
3242 				statsp->xmac_stats.rx_mult_cnt +=
3243 							XRXMAC_MC_FRM_CNT_MASK;
3244 			}
3245 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
3246 				statsp->xmac_stats.rx_frag_cnt +=
3247 							XRXMAC_FRAG_CNT_MASK;
3248 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3249 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
3250 			}
3251 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
3252 				statsp->xmac_stats.rx_frame_align_err_cnt +=
3253 							XRXMAC_AL_ER_CNT_MASK;
3254 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3255 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
3256 			}
3257 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
3258 				statsp->xmac_stats.rx_linkfault_err_cnt +=
3259 							XMAC_LINK_FLT_CNT_MASK;
3260 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3261 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
3262 			}
3263 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
3264 				statsp->xmac_stats.rx_remotefault_err++;
3265 			}
3266 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
3267 				statsp->xmac_stats.rx_localfault_err++;
3268 			}
3269 		}
3270 
3271 		rs = npi_xmac_ctl_get_istatus(handle, portn,
3272 						(xmac_ctl_iconfig_t *)&status);
3273 		if (rs != NPI_SUCCESS)
3274 			goto npi_fail;
3275 		if (status & ICFG_XMAC_CTRL_ALL) {
3276 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
3277 				statsp->xmac_stats.rx_pause_cnt++;
3278 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
3279 				statsp->xmac_stats.tx_pause_state++;
3280 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
3281 				statsp->xmac_stats.tx_nopause_state++;
3282 		}
3283 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
3284 		rs = npi_bmac_tx_get_istatus(handle, portn,
3285 						(bmac_tx_iconfig_t *)&status);
3286 		if (rs != NPI_SUCCESS)
3287 			goto npi_fail;
3288 		if (status & ICFG_BMAC_TX_ALL) {
3289 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
3290 				statsp->bmac_stats.tx_underrun_err++;
3291 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3292 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
3293 			}
3294 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
3295 				statsp->bmac_stats.tx_max_pkt_err++;
3296 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3297 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
3298 			}
3299 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
3300 				statsp->bmac_stats.tx_byte_cnt +=
3301 							BTXMAC_BYTE_CNT_MASK;
3302 			}
3303 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
3304 				statsp->bmac_stats.tx_frame_cnt +=
3305 							BTXMAC_FRM_CNT_MASK;
3306 			}
3307 		}
3308 
3309 		rs = npi_bmac_rx_get_istatus(handle, portn,
3310 						(bmac_rx_iconfig_t *)&status);
3311 		if (rs != NPI_SUCCESS)
3312 			goto npi_fail;
3313 		if (status & ICFG_BMAC_RX_ALL) {
3314 			if (status & ICFG_BMAC_RX_OVERFLOW) {
3315 				statsp->bmac_stats.rx_overflow_err++;
3316 			}
3317 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
3318 				statsp->bmac_stats.rx_frame_cnt +=
3319 							RXMAC_FRM_CNT_MASK;
3320 			}
3321 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
3322 				statsp->bmac_stats.rx_crc_err_cnt +=
3323 							BMAC_CRC_ER_CNT_MASK;
3324 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3325 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
3326 			}
3327 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
3328 				statsp->bmac_stats.rx_len_err_cnt +=
3329 							MAC_LEN_ER_CNT_MASK;
3330 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3331 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
3332 			}
3333 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
3334 				statsp->bmac_stats.rx_viol_err_cnt +=
3335 							BMAC_CD_VIO_CNT_MASK;
3336 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3337 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
3338 			}
3339 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
3340 				statsp->bmac_stats.rx_byte_cnt +=
3341 							BRXMAC_BYTE_CNT_MASK;
3342 			}
3343 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
3344 				statsp->bmac_stats.rx_align_err_cnt +=
3345 							BMAC_AL_ER_CNT_MASK;
3346 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3347 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
3348 			}
3349 
3350 			rs = npi_bmac_ctl_get_istatus(handle, portn,
3351 						(bmac_ctl_iconfig_t *)&status);
3352 			if (rs != NPI_SUCCESS)
3353 				goto npi_fail;
3354 
3355 			if (status & ICFG_BMAC_CTL_ALL) {
3356 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
3357 					statsp->bmac_stats.rx_pause_cnt++;
3358 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
3359 					statsp->bmac_stats.tx_pause_state++;
3360 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
3361 					statsp->bmac_stats.tx_nopause_state++;
3362 			}
3363 		}
3364 
3365 	if (ldgp->nldvs == 1) {
3366 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
3367 			B_TRUE, ldgp->ldg_timer);
3368 	}
3369 
3370 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
3371 	return (DDI_INTR_CLAIMED);
3372 
3373 npi_fail:
3374 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
3375 	return (DDI_INTR_UNCLAIMED);
3376 }
3377 
3378 nxge_status_t
3379 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
3380 {
3381 	uint8_t		phy_port_addr;
3382 	nxge_status_t	status = NXGE_OK;
3383 	boolean_t	rx_sig_ok;
3384 	boolean_t	pcs_blk_lock;
3385 	boolean_t	link_align;
3386 	uint16_t	val1, val2, val3;
3387 #ifdef	NXGE_DEBUG_SYMBOL_ERR
3388 	uint16_t	val_debug;
3389 	uint16_t	val;
3390 #endif
3391 
3392 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
3393 
3394 #ifdef	NXGE_DEBUG_SYMBOL_ERR
3395 	/* Check Device 3 Register Device 3 0xC809 */
3396 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
3397 	if ((val_debug & ~0x200) != 0) {
3398 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
3399 				nxgep->mac.portnum, val_debug);
3400 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
3401 				&val_debug);
3402 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
3403 				nxgep->mac.portnum, val_debug);
3404 	}
3405 
3406 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3407 					XPCS_REG_DESCWERR_COUNTER, &val);
3408 	if (val != 0)
3409 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
3410 
3411 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3412 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
3413 	if (val != 0)
3414 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
3415 
3416 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3417 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
3418 	if (val != 0)
3419 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
3420 #endif
3421 
3422 	/* Check from BCM8704 if 10G link is up or down */
3423 
3424 	/* Check Device 1 Register 0xA bit0 */
3425 	status = nxge_mdio_read(nxgep, phy_port_addr,
3426 			BCM8704_PMA_PMD_DEV_ADDR,
3427 			BCM8704_PMD_RECEIVE_SIG_DETECT,
3428 			&val1);
3429 	if (status != NXGE_OK)
3430 		goto fail;
3431 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
3432 
3433 	/* Check Device 3 Register 0x20 bit0 */
3434 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
3435 			BCM8704_PCS_DEV_ADDR,
3436 			BCM8704_10GBASE_R_PCS_STATUS_REG,
3437 			&val2)) != NPI_SUCCESS)
3438 		goto fail;
3439 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
3440 
3441 	/* Check Device 4 Register 0x18 bit12 */
3442 	status = nxge_mdio_read(nxgep, phy_port_addr,
3443 			BCM8704_PHYXS_ADDR,
3444 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
3445 			&val3);
3446 	if (status != NXGE_OK)
3447 		goto fail;
3448 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
3449 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
3450 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
3451 
3452 #ifdef	NXGE_DEBUG_ALIGN_ERR
3453 	/* Temp workaround for link down issue */
3454 	if (pcs_blk_lock == B_FALSE) {
3455 		if (val2 != 0x4) {
3456 			pcs_blk_lock = B_TRUE;
3457 			cmn_err(CE_NOTE,
3458 				"!LINK DEBUG: port%d PHY Dev3 "
3459 				"Reg 0x20 = 0x%x\n",
3460 				nxgep->mac.portnum, val2);
3461 		}
3462 	}
3463 
3464 	if (link_align == B_FALSE) {
3465 		if (val3 != 0x140f) {
3466 			link_align = B_TRUE;
3467 			cmn_err(CE_NOTE,
3468 				"!LINK DEBUG: port%d PHY Dev4 "
3469 				"Reg 0x18 = 0x%x\n",
3470 				nxgep->mac.portnum, val3);
3471 		}
3472 	}
3473 
3474 	if (rx_sig_ok == B_FALSE) {
3475 		if ((val2 == 0) || (val3 == 0)) {
3476 			rx_sig_ok = B_TRUE;
3477 			cmn_err(CE_NOTE,
3478 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
3479 				nxgep->mac.portnum);
3480 		}
3481 	}
3482 #endif
3483 
3484 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
3485 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
3486 
3487 	return (NXGE_OK);
3488 fail:
3489 	return (status);
3490 }
3491 
3492 nxge_status_t
3493 nxge_10g_link_led_on(p_nxge_t nxgep)
3494 {
3495 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
3496 	    != NPI_SUCCESS)
3497 		return (NXGE_ERROR);
3498 	else
3499 		return (NXGE_OK);
3500 }
3501 
3502 nxge_status_t
3503 nxge_10g_link_led_off(p_nxge_t nxgep)
3504 {
3505 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
3506 	    != NPI_SUCCESS)
3507 		return (NXGE_ERROR);
3508 	else
3509 		return (NXGE_OK);
3510 }
3511 
3512 /* Check if the given id read using the given MDIO Clause is supported */
3513 
3514 static boolean_t
3515 nxge_is_supported_phy(uint32_t id, uint8_t type)
3516 {
3517 	int		i;
3518 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
3519 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
3520 	boolean_t	found = B_FALSE;
3521 
3522 	switch (type) {
3523 	case CLAUSE_45_TYPE:
3524 		for (i = 0; i < cl45_arr_len; i++) {
3525 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
3526 			    (id & BCM_PHY_ID_MASK)) {
3527 				found = B_TRUE;
3528 				break;
3529 			}
3530 		}
3531 		break;
3532 	case CLAUSE_22_TYPE:
3533 		for (i = 0; i < cl22_arr_len; i++) {
3534 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
3535 			    (id & BCM_PHY_ID_MASK)) {
3536 				found = B_TRUE;
3537 				break;
3538 			}
3539 		}
3540 		break;
3541 	default:
3542 		break;
3543 	}
3544 
3545 	return (found);
3546 }
3547 
3548 /*
3549  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
3550  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
3551  * read. Then use the values obtained to determine the phy type of each port
3552  * and the Neptune type.
3553  */
3554 
3555 nxge_status_t
3556 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
3557 {
3558 	int		i, j, k, l;
3559 	uint16_t	val1 = 0;
3560 	uint16_t	val2 = 0;
3561 	uint32_t	pma_pmd_dev_id = 0;
3562 	uint32_t	pcs_dev_id = 0;
3563 	uint32_t	phy_id = 0;
3564 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
3565 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
3566 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
3567 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
3568 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
3569 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
3570 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
3571 	uint8_t		total_port_fd, total_phy_fd;
3572 	nxge_status_t	status = NXGE_OK;
3573 	npi_status_t	npi_status = NPI_SUCCESS;
3574 	npi_handle_t	handle;
3575 	int		prt_id = -1;
3576 
3577 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
3578 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3579 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
3580 	    nxgep->niu_type));
3581 
3582 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3583 	j = k = l = 0;
3584 	total_port_fd = total_phy_fd = 0;
3585 	/*
3586 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
3587 	 * for on chip serdes usages.
3588 	 */
3589 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
3590 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3591 		    NXGE_DEV_ID_REG_1, &val1);
3592 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR,
3593 		    NXGE_DEV_ID_REG_2, &val2);
3594 		pma_pmd_dev_id = val1;
3595 		pma_pmd_dev_id = (pma_pmd_dev_id << 16);
3596 		pma_pmd_dev_id |= val2;
3597 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
3598 		    "devid[0x%llx]", i, pma_pmd_dev_id));
3599 
3600 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
3601 			pma_pmd_dev_fd[i] = 1;
3602 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3603 			    "PMA/PMD dev found", i));
3604 			if (j < NXGE_PORTS_NEPTUNE) {
3605 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
3606 				    BCM_PHY_ID_MASK;
3607 				j++;
3608 			}
3609 		} else {
3610 			pma_pmd_dev_fd[i] = 0;
3611 		}
3612 
3613 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3614 		    NXGE_DEV_ID_REG_1, &val1);
3615 		(void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR,
3616 		    NXGE_DEV_ID_REG_2, &val2);
3617 		pcs_dev_id = val1;
3618 		pcs_dev_id = (pcs_dev_id << 16);
3619 		pcs_dev_id |= val2;
3620 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3621 		    "devid[0x%llx]", i, pcs_dev_id));
3622 
3623 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
3624 			pcs_dev_fd[i] = 1;
3625 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
3626 			    "dev found", i));
3627 			if (k < NXGE_PORTS_NEPTUNE) {
3628 				port_pcs_dev_id[k] = pcs_dev_id &
3629 				    BCM_PHY_ID_MASK;
3630 				k++;
3631 			}
3632 		} else {
3633 			pcs_dev_fd[i] = 0;
3634 		}
3635 
3636 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
3637 			port_fd[i] = 1;
3638 		else
3639 			port_fd[i] = 0;
3640 		total_port_fd += port_fd[i];
3641 
3642 		npi_status = npi_mac_mif_mii_read(handle, i,
3643 		    NXGE_PHY_ID_REG_1, &val1);
3644 		if (npi_status != NPI_SUCCESS) {
3645 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3646 			    "clause 22 read to reg 2 failed!!!"));
3647 			goto error_exit;
3648 		}
3649 		npi_status = npi_mac_mif_mii_read(handle, i,
3650 		    NXGE_PHY_ID_REG_2, &val2);
3651 		if (npi_status != 0) {
3652 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
3653 			    "clause 22 read to reg 3 failed!!!"));
3654 			goto error_exit;
3655 		}
3656 		phy_id = val1;
3657 		phy_id = (phy_id << 16);
3658 		phy_id |= val2;
3659 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3660 		    "[0x%llx]", i, phy_id));
3661 
3662 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
3663 			phy_fd[i] = 1;
3664 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
3665 			    "found", i));
3666 			if (l < NXGE_PORTS_NEPTUNE) {
3667 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
3668 				l++;
3669 			}
3670 		} else {
3671 			phy_fd[i] = 0;
3672 		}
3673 		total_phy_fd += phy_fd[i];
3674 	}
3675 
3676 	switch (total_port_fd) {
3677 	case 2:
3678 		switch (total_phy_fd) {
3679 		case 2:
3680 			/* 2 10G, 2 1G */
3681 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3682 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3683 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3684 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
3685 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3686 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY))) {
3687 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3688 			} else {
3689 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3690 				    "Unsupported neptune type 1"));
3691 				goto error_exit;
3692 			}
3693 			break;
3694 		case 1:
3695 			/* TODO - 2 10G, 1 1G */
3696 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3697 			    "Unsupported neptune type 2 10G, 1 1G"));
3698 			goto error_exit;
3699 		case 0:
3700 			/* 2 10G */
3701 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3702 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3703 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3704 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
3705 				hw_p->niu_type = NEPTUNE_2_10GF;
3706 			} else {
3707 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3708 				    "Unsupported neptune type 2"));
3709 				goto error_exit;
3710 			}
3711 			break;
3712 		case 4:
3713 			/* Maramba with 2 XAUI */
3714 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
3715 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
3716 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
3717 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
3718 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3719 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
3720 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
3721 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
3722 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
3723 
3724 				/*
3725 				 * Check the first phy port address against
3726 				 * the known phy start addresses to determine
3727 				 * the platform type.
3728 				 */
3729 				for (i = NXGE_EXT_PHY_PORT_ST;
3730 				    i < NXGE_MAX_PHY_PORTS; i++) {
3731 					if (phy_fd[i] == 1)
3732 						break;
3733 				}
3734 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3735 					hw_p->platform_type =
3736 					    P_NEPTUNE_MARAMBA_P0;
3737 				} else if (i ==
3738 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3739 					hw_p->platform_type =
3740 					    P_NEPTUNE_MARAMBA_P1;
3741 				} else {
3742 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3743 					    "Unknown port %d...Cannot "
3744 					    "determine platform type", i));
3745 				}
3746 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3747 				    "Maramba with 2 XAUI"));
3748 			} else {
3749 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3750 				    "Unsupported neptune type 3"));
3751 				goto error_exit;
3752 			}
3753 			break;
3754 		default:
3755 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3756 			    "Unsupported neptune type 5"));
3757 			goto error_exit;
3758 		}
3759 		break;
3760 	case 1:
3761 		switch (total_phy_fd) {
3762 		case 3:
3763 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
3764 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
3765 				/* The 10G port is BCM8704 */
3766 				for (i = NXGE_EXT_PHY_PORT_ST;
3767 				    i < NXGE_MAX_PHY_PORTS; i++) {
3768 					if (port_fd[i] == 1) {
3769 						prt_id = i;
3770 						break;
3771 					}
3772 				}
3773 
3774 				if (nxgep->niu_type == N2_NIU)
3775 					prt_id %= BCM8704_N2_PORT_ADDR_BASE;
3776 				else
3777 					prt_id %=
3778 					    BCM8704_NEPTUNE_PORT_ADDR_BASE;
3779 
3780 				if (prt_id == 0) {
3781 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3782 				} else if (prt_id == 1) {
3783 					hw_p->niu_type =
3784 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3785 				} else {
3786 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3787 					    "Unsupported neptune type 6"));
3788 					goto error_exit;
3789 				}
3790 			} else {
3791 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3792 				    "Unsupported neptune type 7"));
3793 				goto error_exit;
3794 			}
3795 			break;
3796 		case 2:
3797 			/*
3798 			 * TODO 2 1G, 1 10G mode.
3799 			 * Differentiate between 1_1G_1_10G_1_1G and
3800 			 * 1_10G_2_1G
3801 			 */
3802 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3803 			    "Unsupported neptune type 8"));
3804 			goto error_exit;
3805 		case 1:
3806 			/*
3807 			 * TODO 1 1G, 1 10G mode.
3808 			 * Differentiate between 1_1G_1_10G and
3809 			 * 1_10G_1_1G
3810 			 */
3811 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3812 			    "Unsupported neptune type 9"));
3813 			goto error_exit;
3814 		case 0:
3815 			/* TODO 1 10G mode */
3816 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3817 			    "Unsupported neptune type 10"));
3818 			goto error_exit;
3819 		case 4:
3820 			/* Maramba with 1 XAUI */
3821 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
3822 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
3823 				/* The 10G port is BCM8704 */
3824 				for (i = NXGE_EXT_PHY_PORT_ST;
3825 				    i < NXGE_MAX_PHY_PORTS; i++) {
3826 					if (port_fd[i] == 1) {
3827 						prt_id = i;
3828 						break;
3829 					}
3830 				}
3831 
3832 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
3833 				if (prt_id == 0) {
3834 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
3835 				} else if (prt_id == 1) {
3836 					hw_p->niu_type =
3837 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
3838 				} else {
3839 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3840 					    "Unsupported neptune type 11"));
3841 					goto error_exit;
3842 				}
3843 
3844 				/*
3845 				 * Check the first phy port address against
3846 				 * the known phy start addresses to determine
3847 				 * the platform type.
3848 				 */
3849 				for (i = NXGE_EXT_PHY_PORT_ST;
3850 				    i < NXGE_MAX_PHY_PORTS; i++) {
3851 					if (phy_fd[i] == 1)
3852 						break;
3853 				}
3854 
3855 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
3856 					hw_p->platform_type =
3857 					    P_NEPTUNE_MARAMBA_P0;
3858 				} else if (i ==
3859 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3860 					hw_p->platform_type =
3861 					    P_NEPTUNE_MARAMBA_P1;
3862 				} else {
3863 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3864 					    "Unknown port %d...Cannot "
3865 					    "determine platform type", i));
3866 				}
3867 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3868 				    "Maramba with 1 XAUI"));
3869 			} else {
3870 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3871 				    "Unsupported neptune type 12"));
3872 				goto error_exit;
3873 			}
3874 			break;
3875 		default:
3876 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3877 			    "Unsupported neptune type 13"));
3878 			goto error_exit;
3879 		}
3880 		break;
3881 	case 0:
3882 		switch (total_phy_fd) {
3883 		case 4:
3884 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
3885 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
3886 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
3887 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
3888 
3889 				hw_p->niu_type = NEPTUNE_4_1GC;
3890 
3891 				/*
3892 				 * Check the first phy port address against
3893 				 * the known phy start addresses to determine
3894 				 * the platform type.
3895 				 */
3896 				for (i = NXGE_EXT_PHY_PORT_ST;
3897 				    i < NXGE_MAX_PHY_PORTS; i++) {
3898 					if (phy_fd[i] == 1)
3899 						break;
3900 				}
3901 
3902 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
3903 					hw_p->platform_type =
3904 					    P_NEPTUNE_MARAMBA_P1;
3905 				}
3906 			} else {
3907 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3908 				    "Unsupported neptune type 14"));
3909 				goto error_exit;
3910 			}
3911 			break;
3912 		case 3:
3913 			/* TODO 3 1G mode */
3914 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3915 			    "Unsupported neptune type 15"));
3916 			goto error_exit;
3917 		case 2:
3918 			/* TODO 2 1G mode */
3919 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3920 			    "Unsupported neptune type 16"));
3921 			goto error_exit;
3922 		case 1:
3923 			/* TODO 1 1G mode */
3924 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3925 			    "Unsupported neptune type 17"));
3926 			goto error_exit;
3927 		default:
3928 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3929 			    "Unsupported neptune type 18, total phy fd %d",
3930 			    total_phy_fd));
3931 			goto error_exit;
3932 		}
3933 		break;
3934 	default:
3935 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3936 		    "Unsupported neptune type 19"));
3937 		goto error_exit;
3938 	}
3939 
3940 scan_exit:
3941 
3942 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
3943 	    "niu type [0x%x]\n", hw_p->niu_type));
3944 	return (status);
3945 
3946 error_exit:
3947 	return (NXGE_ERROR);
3948 }
3949 
3950 boolean_t
3951 nxge_is_valid_local_mac(ether_addr_st mac_addr)
3952 {
3953 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
3954 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
3955 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
3956 		return (B_FALSE);
3957 	else
3958 		return (B_TRUE);
3959 }
3960 
3961 static void
3962 nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
3963 
3964 	npi_status_t rs = NPI_SUCCESS;
3965 	uint8_t xcvr_portn;
3966 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3967 
3968 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
3969 
3970 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
3971 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
3972 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
3973 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
3974 	}
3975 	/*
3976 	 * For Altas 4-1G copper, Xcvr port numbers are
3977 	 * swapped with ethernet port number. This is
3978 	 * designed for better signal integrity in routing.
3979 	 */
3980 	switch (portn) {
3981 	case 0:
3982 		xcvr_portn += 3;
3983 		break;
3984 	case 1:
3985 		xcvr_portn += 2;
3986 		break;
3987 	case 2:
3988 		xcvr_portn += 1;
3989 		break;
3990 	case 3:
3991 	default:
3992 		break;
3993 	}
3994 
3995 	MUTEX_ENTER(&nxge_mii_lock);
3996 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
3997 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
3998 	if (rs != NPI_SUCCESS) {
3999 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4000 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4001 		    "returned error 0x[%x]", rs));
4002 		MUTEX_EXIT(&nxge_mii_lock);
4003 		return;
4004 	}
4005 
4006 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4007 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
4008 	if (rs != NPI_SUCCESS) {
4009 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4010 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4011 		    "returned error 0x[%x]", rs));
4012 		MUTEX_EXIT(&nxge_mii_lock);
4013 		return;
4014 	}
4015 
4016 	MUTEX_EXIT(&nxge_mii_lock);
4017 }
4018