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