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