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