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