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