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