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