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