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