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