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