xref: /titanic_44/usr/src/uts/common/io/nxge/nxge_mac.c (revision afbc45417fe46ac092547adfe04ef4966809b862)
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 			/*
1593 			 * RDY signal stays low may due to the absent of the
1594 			 * external PHY, it is not an error condition. But still
1595 			 * print the message for the debugging purpose when link
1596 			 * stays down
1597 			 */
1598 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1599 			    "nxge_neptune_10G_serdes_init: "
1600 			    "Serdes/signal for port<%d> not ready", portn));
1601 			goto done;
1602 		}
1603 	} else if (portn == 1) {
1604 		/* Wait for serdes to be ready */
1605 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1606 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1607 			if ((val & ESR_SIG_P1_BITS_MASK) !=
1608 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1609 			    ESR_SIG_XSERDES_RDY_P1 |
1610 			    ESR_SIG_XDETECT_P1_CH3 |
1611 			    ESR_SIG_XDETECT_P1_CH2 |
1612 			    ESR_SIG_XDETECT_P1_CH1 |
1613 			    ESR_SIG_XDETECT_P1_CH0))
1614 
1615 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1616 			else
1617 				break;
1618 		}
1619 
1620 		if (i == MAX_SERDES_RDY_RETRIES) {
1621 			/*
1622 			 * RDY signal stays low may due to the absent of the
1623 			 * external PHY, it is not an error condition. But still
1624 			 * print the message for the debugging purpose when link
1625 			 * stays down
1626 			 */
1627 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1628 			    "nxge_neptune_10G_serdes_init: "
1629 			    "Serdes/signal for port<%d> not ready", portn));
1630 			goto done;
1631 		}
1632 	}
1633 
1634 done:
1635 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1636 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
1637 
1638 	return (NXGE_OK);
1639 fail:
1640 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1641 	    "nxge_neptune_10G_serdes_init: "
1642 	    "Failed to initialize Neptune serdes for port<%d>", portn));
1643 
1644 	return (status);
1645 }
1646 
1647 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
1648 
1649 static nxge_status_t
1650 nxge_1G_serdes_init(p_nxge_t nxgep)
1651 {
1652 	npi_handle_t		handle;
1653 	uint8_t			portn;
1654 	int			chan;
1655 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1656 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1657 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1658 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
1659 	uint64_t		val;
1660 	uint16_t		val16l;
1661 	uint16_t		val16h;
1662 	nxge_status_t		status = NXGE_OK;
1663 
1664 	portn = nxgep->mac.portnum;
1665 
1666 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1667 	    "==> nxge_1G_serdes_init port<%d>", portn));
1668 
1669 	handle = nxgep->npi_handle;
1670 
1671 	switch (portn) {
1672 	case 0:
1673 		/* Assert the reset register */
1674 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1675 		val |= ESR_RESET_0;
1676 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1677 
1678 		/* Set the PLL register to 0x79 */
1679 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1680 		    ESR_PLL_CFG_1G_SERDES);
1681 
1682 		/* Set the control register to 0x249249f */
1683 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
1684 
1685 		/* Set Serdes0 Internal Loopback if necessary */
1686 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1687 			/* Set pad loopback modes 0xaa */
1688 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
1689 			    ESR_TSTCFG_LBTEST_PAD);
1690 		} else {
1691 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1692 		}
1693 
1694 		/* Deassert the reset register */
1695 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1696 		val &= ~ESR_RESET_0;
1697 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1698 		break;
1699 
1700 	case 1:
1701 		/* Assert the reset register */
1702 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1703 		val |= ESR_RESET_1;
1704 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1705 
1706 		/* Set PLL register to 0x79 */
1707 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1708 		    ESR_PLL_CFG_1G_SERDES);
1709 
1710 		/* Set the control register to 0x249249f */
1711 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
1712 
1713 		/* Set Serdes1 Internal Loopback if necessary */
1714 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1715 			/* Set pad loopback mode 0xaa */
1716 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
1717 			    ESR_TSTCFG_LBTEST_PAD);
1718 		} else {
1719 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
1720 		}
1721 
1722 		/* Deassert the reset register */
1723 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1724 		val &= ~ESR_RESET_1;
1725 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1726 		break;
1727 
1728 	default:
1729 		/* Nothing to do here */
1730 		goto done;
1731 	}
1732 
1733 	/* init TX RX channels */
1734 	for (chan = 0; chan < 4; chan++) {
1735 		if ((status = nxge_mdio_read(nxgep, portn,
1736 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1737 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
1738 			goto fail;
1739 		}
1740 		if ((status = nxge_mdio_read(nxgep, portn,
1741 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1742 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
1743 			goto fail;
1744 		}
1745 		if ((status = nxge_mdio_read(nxgep, portn,
1746 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1747 		    &glue_ctrl0_l.value)) != NXGE_OK) {
1748 			goto fail;
1749 		}
1750 		if ((status = nxge_mdio_read(nxgep, portn,
1751 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1752 		    &glue_ctrl0_h.value)) != NXGE_OK) {
1753 			goto fail;
1754 		}
1755 
1756 		rx_tx_ctrl_l.bits.enstretch = 1;
1757 		rx_tx_ctrl_h.bits.vmuxlo = 2;
1758 		rx_tx_ctrl_h.bits.vpulselo = 2;
1759 		glue_ctrl0_l.bits.rxlosenable = 1;
1760 		glue_ctrl0_l.bits.samplerate = 0xF;
1761 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
1762 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
1763 		if ((status = nxge_mdio_write(nxgep, portn,
1764 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1765 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
1766 			goto fail;
1767 		}
1768 		if ((status = nxge_mdio_write(nxgep, portn,
1769 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1770 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
1771 			goto fail;
1772 		}
1773 		if ((status = nxge_mdio_write(nxgep, portn,
1774 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1775 		    glue_ctrl0_l.value)) != NXGE_OK) {
1776 			goto fail;
1777 		}
1778 		if ((status = nxge_mdio_write(nxgep, portn,
1779 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1780 		    glue_ctrl0_h.value)) != NXGE_OK) {
1781 			goto fail;
1782 		}
1783 	}
1784 
1785 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1786 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
1787 		goto fail;
1788 	}
1789 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1790 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
1791 		goto fail;
1792 	}
1793 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1794 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
1795 		goto fail;
1796 	}
1797 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1798 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
1799 		goto fail;
1800 	}
1801 
1802 	/* Apply Tx core reset */
1803 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1804 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
1805 		goto fail;
1806 	}
1807 
1808 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1809 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
1810 	    NXGE_OK) {
1811 		goto fail;
1812 	}
1813 
1814 	NXGE_DELAY(200);
1815 
1816 	/* Apply Rx core reset */
1817 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1818 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
1819 	    NXGE_OK) {
1820 		goto fail;
1821 	}
1822 
1823 	NXGE_DELAY(200);
1824 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1825 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
1826 		goto fail;
1827 	}
1828 
1829 	NXGE_DELAY(200);
1830 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1831 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
1832 		goto fail;
1833 	}
1834 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1835 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
1836 		goto fail;
1837 	}
1838 	if ((val16l != 0) || (val16h != 0)) {
1839 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1840 		    "Failed to reset port<%d> XAUI Serdes "
1841 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
1842 		status = NXGE_ERROR;
1843 		goto fail;
1844 	}
1845 
1846 	NXGE_DELAY(200);
1847 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1848 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1849 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
1850 	    "val 0x%x", portn, val));
1851 	if (portn == 0) {
1852 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
1853 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
1854 			/*
1855 			 * RDY signal stays low may due to the absent of the
1856 			 * external PHY, it is not an error condition. But still
1857 			 * print the message for the debugging purpose when link
1858 			 * stays down
1859 			 */
1860 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1861 			    "nxge_neptune_1G_serdes_init: "
1862 			    "Serdes/signal for port<%d> not ready", portn));
1863 			goto done;
1864 		}
1865 	} else if (portn == 1) {
1866 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
1867 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
1868 			/*
1869 			 * RDY signal stays low may due to the absent of the
1870 			 * external PHY, it is not an error condition. But still
1871 			 * print the message for the debugging purpose when link
1872 			 * stays down
1873 			 */
1874 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1875 			    "nxge_neptune_1G_serdes_init: "
1876 			    "Serdes/signal for port<%d> not ready", portn));
1877 			goto done;
1878 		}
1879 	}
1880 done:
1881 
1882 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1883 	    "<== nxge_1G_serdes_init port<%d>", portn));
1884 	return (NXGE_OK);
1885 fail:
1886 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1887 	    "nxge_1G_serdes_init: "
1888 	    "Failed to initialize Neptune serdes for port<%d>",
1889 	    portn));
1890 
1891 	return (status);
1892 }
1893 
1894 /* Initialize the BCM 8704 xcvr */
1895 
1896 static nxge_status_t
1897 nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
1898 {
1899 	uint16_t		val;
1900 #ifdef	NXGE_DEBUG
1901 	uint8_t			portn;
1902 	uint16_t		val1;
1903 #endif
1904 	uint8_t			phy_port_addr;
1905 	pmd_tx_control_t	tx_ctl;
1906 	control_t		ctl;
1907 	phyxs_control_t		phyxs_ctl;
1908 	pcs_control_t		pcs_ctl;
1909 	uint32_t		delay = 0;
1910 	optics_dcntr_t		op_ctr;
1911 	nxge_status_t		status = NXGE_OK;
1912 #ifdef	NXGE_DEBUG
1913 	portn = nxgep->mac.portnum;
1914 #endif
1915 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
1916 	    portn));
1917 
1918 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
1919 
1920 	/* Reset the transceiver */
1921 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1922 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
1923 		goto fail;
1924 
1925 	phyxs_ctl.bits.reset = 1;
1926 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1927 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
1928 		goto fail;
1929 
1930 	do {
1931 		drv_usecwait(500);
1932 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1933 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
1934 		    &phyxs_ctl.value)) != NXGE_OK)
1935 			goto fail;
1936 		delay++;
1937 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
1938 	if (delay == 100) {
1939 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
1940 		    "failed to reset Transceiver on port<%d>", portn));
1941 		status = NXGE_ERROR;
1942 		goto fail;
1943 	}
1944 
1945 	/* Set to 0x7FBF */
1946 	ctl.value = 0;
1947 	ctl.bits.res1 = 0x3F;
1948 	ctl.bits.optxon_lvl = 1;
1949 	ctl.bits.oprxflt_lvl = 1;
1950 	ctl.bits.optrxlos_lvl = 1;
1951 	ctl.bits.optxflt_lvl = 1;
1952 	ctl.bits.opprflt_lvl = 1;
1953 	ctl.bits.obtmpflt_lvl = 1;
1954 	ctl.bits.opbiasflt_lvl = 1;
1955 	ctl.bits.optxrst_lvl = 1;
1956 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1957 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
1958 	    != NXGE_OK)
1959 		goto fail;
1960 
1961 	/* Set to 0x164 */
1962 	tx_ctl.value = 0;
1963 	tx_ctl.bits.tsck_lpwren = 1;
1964 	tx_ctl.bits.tx_dac_txck = 0x2;
1965 	tx_ctl.bits.tx_dac_txd = 0x1;
1966 	tx_ctl.bits.xfp_clken = 1;
1967 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1968 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
1969 	    tx_ctl.value)) != NXGE_OK)
1970 		goto fail;
1971 	/*
1972 	 * According to Broadcom's instruction, SW needs to read
1973 	 * back these registers twice after written.
1974 	 */
1975 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1976 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1977 	    != NXGE_OK)
1978 		goto fail;
1979 
1980 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1981 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1982 	    != NXGE_OK)
1983 		goto fail;
1984 
1985 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1986 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1987 	    != NXGE_OK)
1988 		goto fail;
1989 
1990 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1991 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1992 	    != NXGE_OK)
1993 		goto fail;
1994 
1995 	/* Enable Tx and Rx LEDs to be driven by traffic */
1996 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1997 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1998 	    &op_ctr.value)) != NXGE_OK)
1999 		goto fail;
2000 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2001 		op_ctr.bits.gpio_sel = 0x1;
2002 	} else {
2003 		op_ctr.bits.gpio_sel = 0x3;
2004 	}
2005 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2006 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2007 	    op_ctr.value)) != NXGE_OK)
2008 		goto fail;
2009 
2010 	NXGE_DELAY(1000000);
2011 
2012 	/* Set BCM8704 Internal Loopback mode if necessary */
2013 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2014 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2015 	    != NXGE_OK)
2016 		goto fail;
2017 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2018 		pcs_ctl.bits.loopback = 1;
2019 	else
2020 		pcs_ctl.bits.loopback = 0;
2021 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2022 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2023 	    != NXGE_OK)
2024 		goto fail;
2025 
2026 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
2027 	if (status != NXGE_OK)
2028 		goto fail;
2029 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2030 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
2031 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
2032 	if (status != NXGE_OK)
2033 		goto fail;
2034 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2035 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
2036 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
2037 	if (status != NXGE_OK)
2038 		goto fail;
2039 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2040 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
2041 
2042 #ifdef	NXGE_DEBUG
2043 	/* Diagnose link issue if link is not up */
2044 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
2045 	    BCM8704_USER_ANALOG_STATUS0_REG,
2046 	    &val);
2047 	if (status != NXGE_OK)
2048 		goto fail;
2049 
2050 	status = nxge_mdio_read(nxgep, phy_port_addr,
2051 				BCM8704_USER_DEV3_ADDR,
2052 				BCM8704_USER_ANALOG_STATUS0_REG,
2053 				&val);
2054 	if (status != NXGE_OK)
2055 		goto fail;
2056 
2057 	status = nxge_mdio_read(nxgep, phy_port_addr,
2058 				BCM8704_USER_DEV3_ADDR,
2059 				BCM8704_USER_TX_ALARM_STATUS_REG,
2060 				&val1);
2061 	if (status != NXGE_OK)
2062 		goto fail;
2063 
2064 	status = nxge_mdio_read(nxgep, phy_port_addr,
2065 				BCM8704_USER_DEV3_ADDR,
2066 				BCM8704_USER_TX_ALARM_STATUS_REG,
2067 				&val1);
2068 	if (status != NXGE_OK)
2069 		goto fail;
2070 
2071 	if (val != 0x3FC) {
2072 		if ((val == 0x43BC) && (val1 != 0)) {
2073 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2074 			    "Cable not connected to peer or bad"
2075 			    " cable on port<%d>\n", portn));
2076 		} else if (val == 0x639C) {
2077 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2078 			    "Optical module (XFP) is bad or absent"
2079 			    " on port<%d>\n", portn));
2080 		}
2081 	}
2082 #endif
2083 
2084 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
2085 	    portn));
2086 	return (NXGE_OK);
2087 
2088 fail:
2089 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2090 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
2091 	    "port<%d>", nxgep->mac.portnum));
2092 	return (NXGE_ERROR);
2093 }
2094 
2095 /* Initialize the BCM 8706 Transceiver */
2096 
2097 static nxge_status_t
2098 nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
2099 {
2100 	uint8_t			phy_port_addr;
2101 	phyxs_control_t		phyxs_ctl;
2102 	pcs_control_t		pcs_ctl;
2103 	uint32_t		delay = 0;
2104 	optics_dcntr_t		op_ctr;
2105 	nxge_status_t		status = NXGE_OK;
2106 #ifdef	NXGE_DEBUG
2107 	uint8_t			portn = nxgep->mac.portnum;
2108 #endif
2109 
2110 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2111 	    portn));
2112 
2113 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
2114 
2115 	/* Reset the transceiver */
2116 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2117 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
2118 		goto fail;
2119 
2120 	phyxs_ctl.bits.reset = 1;
2121 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2122 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
2123 		goto fail;
2124 	do {
2125 		drv_usecwait(500);
2126 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2127 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
2128 		    &phyxs_ctl.value)) != NXGE_OK)
2129 			goto fail;
2130 		delay++;
2131 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
2132 
2133 	if (delay == 100) {
2134 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2135 		    "failed to reset Transceiver on port<%d>", portn));
2136 		status = NXGE_ERROR;
2137 		goto fail;
2138 	}
2139 
2140 	NXGE_DELAY(1000000);
2141 
2142 	/* Set BCM8706 Internal Loopback mode if necessary */
2143 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2144 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2145 	    != NXGE_OK)
2146 		goto fail;
2147 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2148 		pcs_ctl.bits.loopback = 1;
2149 	else
2150 		pcs_ctl.bits.loopback = 0;
2151 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2152 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2153 	    != NXGE_OK)
2154 		goto fail;
2155 
2156 	/* Enable Tx and Rx LEDs to be driven by traffic */
2157 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2158 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2159 	    &op_ctr.value)) != NXGE_OK)
2160 		goto fail;
2161 	op_ctr.bits.gpio_sel = 0x3;
2162 	op_ctr.bits.res2 = 0x1;
2163 
2164 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2165 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2166 	    op_ctr.value)) != NXGE_OK)
2167 		goto fail;
2168 
2169 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2170 	    portn));
2171 	return (NXGE_OK);
2172 
2173 fail:
2174 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2175 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
2176 	    "port<%d>", nxgep->mac.portnum));
2177 	return (status);
2178 }
2179 
2180 #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
2181 
2182 #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
2183 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
2184 
2185 #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
2186 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
2187 
2188 
2189 static void
2190 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
2191 {
2192 	uint16_t	value;
2193 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
2194 
2195 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
2196 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
2197 		value &= ~MRVL_88X2011_LED_BLK_MASK;
2198 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
2199 		(void) nxge_mdio_write(nxgep, phy,
2200 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
2201 		    value);
2202 	}
2203 }
2204 
2205 static nxge_status_t
2206 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
2207 {
2208 	nxge_status_t	status;
2209 	pcs_control_t	pcs_ctl;
2210 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
2211 
2212 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
2213 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
2214 
2215 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2216 		pcs_ctl.bits.loopback = 1;
2217 	else
2218 		pcs_ctl.bits.loopback = 0;
2219 
2220 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
2221 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
2222 
2223 fail:
2224 	return (status);
2225 }
2226 
2227 
2228 static void
2229 nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
2230 {
2231 	uint16_t	val2;
2232 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
2233 
2234 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
2235 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
2236 	    MRVL_88X2011_LED_CTL_MASK);
2237 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
2238 
2239 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
2240 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
2241 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2242 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
2243 	}
2244 }
2245 
2246 
2247 static nxge_status_t
2248 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
2249 {
2250 	uint8_t		phy;
2251 	nxge_status_t	status;
2252 	uint16_t	clk;
2253 
2254 	phy = nxgep->statsp->mac_stats.xcvr_portn;
2255 
2256 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2257 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
2258 	    nxgep->mac.portnum, phy));
2259 
2260 	/* Set LED functions	*/
2261 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
2262 	/* PCS activity */
2263 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
2264 
2265 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
2266 	    MRVL_88X2011_GEN_CTL, &clk);
2267 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
2268 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
2269 	    MRVL_88X2011_GEN_CTL, clk);
2270 
2271 	/* Set internal loopback mode if necessary */
2272 
2273 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
2274 
2275 	/* Enable PMD */
2276 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
2277 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
2278 
2279 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
2280 
2281 fail:
2282 	return (status);
2283 }
2284 
2285 
2286 
2287 /* Initialize the 10G Transceiver */
2288 
2289 static nxge_status_t
2290 nxge_10G_xcvr_init(p_nxge_t nxgep)
2291 {
2292 	p_nxge_stats_t		statsp;
2293 	p_nxge_param_t		param_arr = nxgep->param_arr;
2294 	nxge_status_t		status = NXGE_OK;
2295 #ifdef	NXGE_DEBUG
2296 	uint8_t			portn = nxgep->mac.portnum;
2297 #endif
2298 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
2299 	    portn));
2300 
2301 	statsp = nxgep->statsp;
2302 
2303 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
2304 		goto done;
2305 	}
2306 
2307 	/* Disable Link LEDs */
2308 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
2309 		goto fail;
2310 
2311 	/* Set Clause 45 */
2312 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
2313 
2314 	switch (nxgep->chip_id) {
2315 	case BCM8704_CHIP_ID:
2316 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2317 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
2318 		status = nxge_BCM8704_xcvr_init(nxgep);
2319 		break;
2320 	case BCM8706_CHIP_ID:
2321 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2322 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
2323 		status = nxge_BCM8706_xcvr_init(nxgep);
2324 		break;
2325 	case MRVL88X201X_CHIP_ID:
2326 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2327 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
2328 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
2329 		break;
2330 	default:
2331 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
2332 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
2333 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
2334 		goto fail;
2335 	}
2336 
2337 	if (status != NXGE_OK) {
2338 		goto fail;
2339 	}
2340 done:
2341 	statsp->mac_stats.cap_10gfdx = 1;
2342 	statsp->mac_stats.lp_cap_10gfdx = 1;
2343 	statsp->mac_stats.adv_cap_asmpause =
2344 	    param_arr[param_anar_asmpause].value;
2345 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
2346 
2347 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
2348 	    portn));
2349 	return (NXGE_OK);
2350 
2351 fail:
2352 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2353 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
2354 	    "port<%d>", nxgep->mac.portnum));
2355 	return (NXGE_ERROR);
2356 }
2357 
2358 /* Initialize the 1G copper (BCM 5464) Transceiver */
2359 
2360 static nxge_status_t
2361 nxge_1G_xcvr_init(p_nxge_t nxgep)
2362 {
2363 	p_nxge_param_t		param_arr = nxgep->param_arr;
2364 	p_nxge_stats_t		statsp = nxgep->statsp;
2365 	nxge_status_t		status = NXGE_OK;
2366 
2367 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
2368 		statsp->mac_stats.cap_1000fdx =
2369 		    param_arr[param_anar_1000fdx].value;
2370 		goto done;
2371 	}
2372 
2373 	/* Set Clause 22 */
2374 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
2375 
2376 	/* Set capability flags */
2377 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
2378 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
2379 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
2380 		statsp->mac_stats.cap_100fdx =
2381 		    param_arr[param_anar_100fdx].value;
2382 		statsp->mac_stats.cap_10fdx =
2383 		    param_arr[param_anar_10fdx].value;
2384 	}
2385 
2386 	status = nxge_mii_xcvr_init(nxgep);
2387 done:
2388 	return (status);
2389 }
2390 
2391 /* Initialize transceiver */
2392 
2393 nxge_status_t
2394 nxge_xcvr_init(p_nxge_t nxgep)
2395 {
2396 	p_nxge_stats_t		statsp;
2397 #ifdef	NXGE_DEBUG
2398 	uint8_t			portn;
2399 #endif
2400 
2401 	nxge_status_t		status = NXGE_OK;
2402 #ifdef	NXGE_DEBUG
2403 	portn = nxgep->mac.portnum;
2404 #endif
2405 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
2406 	statsp = nxgep->statsp;
2407 
2408 	/*
2409 	 * Initialize the xcvr statistics.
2410 	 */
2411 	statsp->mac_stats.cap_autoneg = 0;
2412 	statsp->mac_stats.cap_100T4 = 0;
2413 	statsp->mac_stats.cap_100fdx = 0;
2414 	statsp->mac_stats.cap_100hdx = 0;
2415 	statsp->mac_stats.cap_10fdx = 0;
2416 	statsp->mac_stats.cap_10hdx = 0;
2417 	statsp->mac_stats.cap_asmpause = 0;
2418 	statsp->mac_stats.cap_pause = 0;
2419 	statsp->mac_stats.cap_1000fdx = 0;
2420 	statsp->mac_stats.cap_1000hdx = 0;
2421 	statsp->mac_stats.cap_10gfdx = 0;
2422 	statsp->mac_stats.cap_10ghdx = 0;
2423 
2424 	/*
2425 	 * Initialize the link statistics.
2426 	 */
2427 	statsp->mac_stats.link_T4 = 0;
2428 	statsp->mac_stats.link_asmpause = 0;
2429 	statsp->mac_stats.link_pause = 0;
2430 
2431 	if (nxgep->xcvr.xcvr_init) {
2432 		status = nxgep->xcvr.xcvr_init(nxgep);
2433 		if (status != NXGE_OK)
2434 			goto fail;
2435 		statsp->mac_stats.xcvr_inits++;
2436 	}
2437 
2438 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
2439 	    portn));
2440 	return (NXGE_OK);
2441 
2442 fail:
2443 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2444 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
2445 	    portn));
2446 	return (status);
2447 }
2448 
2449 /* Look for transceiver type */
2450 
2451 nxge_status_t
2452 nxge_xcvr_find(p_nxge_t nxgep)
2453 {
2454 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
2455 	    nxgep->mac.portnum));
2456 
2457 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
2458 		return (NXGE_ERROR);
2459 
2460 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
2461 		return (NXGE_ERROR);
2462 
2463 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
2464 	    nxgep->statsp->mac_stats.xcvr_inuse));
2465 	return (NXGE_OK);
2466 }
2467 
2468 /* Initialize the TxMAC sub-block */
2469 
2470 nxge_status_t
2471 nxge_tx_mac_init(p_nxge_t nxgep)
2472 {
2473 	npi_attr_t		ap;
2474 	uint8_t			portn;
2475 	nxge_port_mode_t	portmode;
2476 	nxge_port_t		portt;
2477 	npi_handle_t		handle;
2478 	npi_status_t		rs = NPI_SUCCESS;
2479 
2480 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2481 	portt    = nxgep->mac.porttype;
2482 	handle   = nxgep->npi_handle;
2483 	portmode = nxgep->mac.portmode;
2484 
2485 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
2486 			portn));
2487 	/* Set Max and Min Frame Size */
2488 	/*
2489 	 * Use maxframesize to configure the hardware maxframe size
2490 	 * and minframesize to configure the hardwae minframe size.
2491 	 */
2492 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2493 	    "==> nxge_tx_mac_init: port<%d> "
2494 	    "min framesize %d max framesize %d ",
2495 	    nxgep->mac.minframesize,
2496 	    nxgep->mac.maxframesize,
2497 	    portn));
2498 
2499 	SET_MAC_ATTR2(handle, ap, portn,
2500 	    MAC_PORT_FRAME_SIZE,
2501 	    nxgep->mac.minframesize,
2502 	    nxgep->mac.maxframesize,
2503 	    rs);
2504 	if (rs != NPI_SUCCESS)
2505 		goto fail;
2506 
2507 	if (portt == PORT_TYPE_XMAC) {
2508 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
2509 				0)) != NPI_SUCCESS)
2510 			goto fail;
2511 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
2512 		if ((portmode == PORT_10G_FIBER) ||
2513 		    (portmode == PORT_10G_COPPER) ||
2514 		    (portmode == PORT_10G_SERDES)) {
2515 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
2516 					XGMII_IPG_12_15, rs);
2517 			if (rs != NPI_SUCCESS)
2518 				goto fail;
2519 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
2520 		} else {
2521 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
2522 					MII_GMII_IPG_12, rs);
2523 			if (rs != NPI_SUCCESS)
2524 				goto fail;
2525 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
2526 		}
2527 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
2528 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
2529 			goto fail;
2530 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
2531 		nxgep->mac.maxburstsize = 0;	/* not programmable */
2532 		nxgep->mac.ctrltype = 0;	/* not programmable */
2533 		nxgep->mac.pa_size = 0;		/* not programmable */
2534 
2535 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
2536 							!= NPI_SUCCESS)
2537 			goto fail;
2538 
2539 	} else {
2540 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
2541 				0)) != NPI_SUCCESS)
2542 			goto fail;
2543 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
2544 
2545 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
2546 				rs);
2547 		if (rs != NPI_SUCCESS)
2548 			goto fail;
2549 		nxgep->mac.ctrltype = 0x8808;
2550 
2551 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
2552 		if (rs != NPI_SUCCESS)
2553 			goto fail;
2554 		nxgep->mac.pa_size = 0x7;
2555 
2556 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
2557 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
2558 			goto fail;
2559 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
2560 	}
2561 
2562 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
2563 			portn));
2564 
2565 	return (NXGE_OK);
2566 fail:
2567 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2568 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
2569 					portn));
2570 
2571 	return (NXGE_ERROR | rs);
2572 }
2573 
2574 int
2575 nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep)
2576 {
2577 	int rdc_tbl;
2578 
2579 	/*
2580 	 * Get an RDC table (version 0).
2581 	 */
2582 	if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) {
2583 		NXGE_ERROR_MSG((nxgep, OBP_CTL,
2584 		    "nxge_hio_hostinfo_get_rdc_table: "
2585 		    "there are no free RDC tables!"));
2586 		return (EBUSY);
2587 	}
2588 
2589 	return (rdc_tbl);
2590 }
2591 
2592 /*
2593  * nxge_hio_hostinfo_init
2594  *
2595  *	Initialize an alternate MAC address, and bind a macrdctbln to it.
2596  *
2597  * Arguments:
2598  * 	nxge
2599  * 	vr	The Virtualization Region
2600  * 	macaddr	The alternate MAC address
2601  *
2602  * Notes:
2603  *	1. Find & bind an RDC table to <nxge>.
2604  *	2. Program an alternate MAC address (<macaddr>).
2605  *	3. Bind the RDC table to <macaddr>.
2606  *
2607  * Context:
2608  *	Service domain
2609  *
2610  * Side Effects:
2611  *	nxge->class_config.mac_host_info[slot].rdctbl
2612  *	vr->slot & vr->altmac
2613  *
2614  */
2615 int
2616 nxge_hio_hostinfo_init(
2617 	nxge_t *nxge,
2618 	nxge_hio_vr_t *vr,	/* Virtualization Region */
2619 	ether_addr_t *macaddr)	/* The alternate MAC address */
2620 {
2621 	int rdc_tbl, slot;
2622 
2623 	nxge_class_pt_cfg_t *class;
2624 	hostinfo_t mac_rdc;
2625 	npi_mac_addr_t altmac;
2626 	nxge_mmac_t *mmac_info;
2627 	nxge_rdc_grp_t	*group;
2628 	uint8_t *addr = (uint8_t *)macaddr;
2629 
2630 	mutex_enter(nxge->genlock);
2631 
2632 	rdc_tbl = vr->rdc_tbl;
2633 
2634 	/* Initialize the NXGE RDC table data structure. */
2635 	group = &nxge->pt_config.rdc_grps[rdc_tbl];
2636 	group->port = NXGE_GET_PORT_NUM(nxge->function_num);
2637 	group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
2638 	group->flag = 1;	/* This group has been configured. */
2639 
2640 	mmac_info = &nxge->nxge_mmac_info;
2641 
2642 	/*
2643 	 * Are there free slots.
2644 	 */
2645 	if (mmac_info->naddrfree == 0) {
2646 		mutex_exit(nxge->genlock);
2647 		return (ENOSPC);
2648 	}
2649 
2650 	/*
2651 	 * The vswitch has already added this MAC address.
2652 	 * Find its assigned slot.
2653 	 */
2654 	if (mmac_info->num_factory_mmac < mmac_info->num_mmac) {
2655 		for (slot = mmac_info->num_factory_mmac + 1;
2656 		    slot <= mmac_info->num_mmac; slot++) {
2657 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
2658 				break;
2659 		}
2660 		if (slot > mmac_info->num_mmac) {
2661 			for (slot = 1; slot <= mmac_info->num_factory_mmac;
2662 			    slot++) {
2663 				if (!(mmac_info->mac_pool[slot].flags
2664 				    & MMAC_SLOT_USED))
2665 					break;
2666 			}
2667 		}
2668 	} else {
2669 		for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
2670 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
2671 				break;
2672 		}
2673 	}
2674 
2675 	ASSERT(slot <= mmac_info->num_mmac);
2676 	vr->slot = slot;
2677 	slot = vr->slot - 1;
2678 
2679 	/*
2680 	 * Programm the mac address.
2681 	 */
2682 	altmac.w2 = (((uint16_t)addr[0]) << 8) |
2683 	    (((uint16_t)addr[1]) & 0x0ff);
2684 	altmac.w1 = (((uint16_t)addr[2]) << 8) |
2685 	    (((uint16_t)addr[3]) & 0x0ff);
2686 	altmac.w0 = (((uint16_t)addr[4]) << 8) |
2687 	    (((uint16_t)addr[5]) & 0x0ff);
2688 
2689 	if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET,
2690 	    nxge->function_num, slot, &altmac) != NPI_SUCCESS) {
2691 		mutex_exit(nxge->genlock);
2692 		return (EIO);
2693 	}
2694 
2695 	/*
2696 	 * Associate <rdc_tbl> with this MAC address slot.
2697 	 */
2698 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2699 
2700 	/* Update this variable. */
2701 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2702 	class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl;
2703 
2704 	mac_rdc.value = 0;
2705 	mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl;
2706 	mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr;
2707 	/* <mpr_npr> had better be 1! */
2708 
2709 	/* Program the RDC table. */
2710 	if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET,
2711 		nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) {
2712 		mutex_exit(nxge->genlock);
2713 		(void) nxge_m_mmac_remove(nxge, vr->slot);
2714 		return (EIO);
2715 	}
2716 
2717 	if (nxge->mac.portnum != XMAC_PORT_0 &&
2718 	    nxge->mac.portnum != XMAC_PORT_1)
2719 		slot++;
2720 
2721 	/* (Re-)enable the MAC address. */
2722 	(void) npi_mac_altaddr_enable(
2723 		nxge->npi_handle, nxge->mac.portnum, slot);
2724 
2725 	bcopy(macaddr, vr->altmac, sizeof (vr->altmac));
2726 
2727 	/*
2728 	 * Update mmac
2729 	 */
2730 	bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL);
2731 	mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED;
2732 	mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR;
2733 	mmac_info->naddrfree--;
2734 	nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE);
2735 
2736 	mutex_exit(nxge->genlock);
2737 	return (0);
2738 }
2739 
2740 /*
2741  * nxge_hio_hostinfo_uninit
2742  *
2743  *	Uninitialize an alternate MAC address.
2744  *
2745  * Arguments:
2746  * 	nxge
2747  * 	vr	The Virtualization Region
2748  *
2749  * Notes:
2750  *	1. Remove the VR's alternate MAC address.
2751  *	1. Free (unbind) the RDC table allocated to this VR.
2752  *
2753  * Context:
2754  *	Service domain
2755  *
2756  * Side Effects:
2757  *	nxge->class_config.mac_host_info[slot].rdctbl
2758  *
2759  */
2760 void
2761 nxge_hio_hostinfo_uninit(
2762 	nxge_t *nxge,
2763 	nxge_hio_vr_t *vr)
2764 {
2765 	nxge_class_pt_cfg_t *class;
2766 
2767 	(void) npi_mac_altaddr_disable(
2768 		nxge->npi_handle, nxge->mac.portnum, vr->slot);
2769 
2770 	/* Set this variable to its default. */
2771 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
2772 	class->mac_host_info[vr->slot].rdctbl =
2773 	    nxge->pt_config.hw_config.def_mac_rxdma_grpid;
2774 
2775 	(void) nxge_m_mmac_remove(nxge, vr->slot);
2776 	vr->slot = -1;
2777 
2778 	(void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl);
2779 	vr->rdc_tbl = -1;
2780 }
2781 
2782 /* Initialize the RxMAC sub-block */
2783 
2784 nxge_status_t
2785 nxge_rx_mac_init(p_nxge_t nxgep)
2786 {
2787 	npi_attr_t		ap;
2788 	uint32_t		i;
2789 	uint16_t		hashtab_e;
2790 	p_hash_filter_t		hash_filter;
2791 	nxge_port_t		portt;
2792 	uint8_t			portn;
2793 	npi_handle_t		handle;
2794 	npi_status_t		rs = NPI_SUCCESS;
2795 	uint16_t 		*addr16p;
2796 	uint16_t 		addr0, addr1, addr2;
2797 	xmac_rx_config_t	xconfig;
2798 	bmac_rx_config_t	bconfig;
2799 
2800 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2801 
2802 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
2803 			portn));
2804 	handle = nxgep->npi_handle;
2805 	portt = nxgep->mac.porttype;
2806 
2807 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
2808 	addr0 = ntohs(addr16p[2]);
2809 	addr1 = ntohs(addr16p[1]);
2810 	addr2 = ntohs(addr16p[0]);
2811 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
2812 		rs);
2813 
2814 	if (rs != NPI_SUCCESS)
2815 		goto fail;
2816 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
2817 	if (rs != NPI_SUCCESS)
2818 		goto fail;
2819 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
2820 	if (rs != NPI_SUCCESS)
2821 		goto fail;
2822 
2823 	/*
2824 	 * Load the multicast hash filter bits.
2825 	 */
2826 	hash_filter = nxgep->hash_filter;
2827 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
2828 		if (hash_filter != NULL) {
2829 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
2830 				(NMCFILTER_REGS - 1) - i];
2831 		} else {
2832 			hashtab_e = 0;
2833 		}
2834 
2835 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
2836 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
2837 			goto fail;
2838 	}
2839 
2840 	if (portt == PORT_TYPE_XMAC) {
2841 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
2842 				0)) != NPI_SUCCESS)
2843 			goto fail;
2844 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
2845 
2846 		(void) nxge_fflp_init_hostinfo(nxgep);
2847 
2848 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
2849 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
2850 			~CFG_XMAC_RX_STRIP_CRC;
2851 
2852 		if (nxgep->filter.all_phys_cnt != 0)
2853 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
2854 
2855 		if (nxgep->filter.all_multicast_cnt != 0)
2856 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
2857 
2858 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
2859 
2860 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
2861 					xconfig)) != NPI_SUCCESS)
2862 			goto fail;
2863 		nxgep->mac.rx_config = xconfig;
2864 
2865 		/* Comparison of mac unique address is always enabled on XMAC */
2866 
2867 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
2868 							!= NPI_SUCCESS)
2869 			goto fail;
2870 	} else {
2871 		(void) nxge_fflp_init_hostinfo(nxgep);
2872 
2873 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
2874 					0) != NPI_SUCCESS)
2875 			goto fail;
2876 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
2877 
2878 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
2879 			~CFG_BMAC_RX_STRIP_CRC;
2880 
2881 		if (nxgep->filter.all_phys_cnt != 0)
2882 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
2883 
2884 		if (nxgep->filter.all_multicast_cnt != 0)
2885 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
2886 
2887 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
2888 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
2889 					bconfig)) != NPI_SUCCESS)
2890 			goto fail;
2891 		nxgep->mac.rx_config = bconfig;
2892 
2893 		/* Always enable comparison of mac unique address */
2894 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
2895 					!= NPI_SUCCESS)
2896 			goto fail;
2897 	}
2898 
2899 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
2900 			portn));
2901 
2902 	return (NXGE_OK);
2903 
2904 fail:
2905 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2906 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
2907 				portn));
2908 
2909 	return (NXGE_ERROR | rs);
2910 }
2911 
2912 /* Enable TXMAC */
2913 
2914 nxge_status_t
2915 nxge_tx_mac_enable(p_nxge_t nxgep)
2916 {
2917 	npi_handle_t	handle;
2918 	npi_status_t	rs = NPI_SUCCESS;
2919 	nxge_status_t	status = NXGE_OK;
2920 
2921 	handle = nxgep->npi_handle;
2922 
2923 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
2924 			nxgep->mac.portnum));
2925 
2926 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
2927 		goto fail;
2928 
2929 	/* based on speed */
2930 	nxgep->msg_min = ETHERMIN;
2931 
2932 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2933 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
2934 						CFG_XMAC_TX)) != NPI_SUCCESS)
2935 			goto fail;
2936 	} else {
2937 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
2938 						CFG_BMAC_TX)) != NPI_SUCCESS)
2939 			goto fail;
2940 	}
2941 
2942 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
2943 			nxgep->mac.portnum));
2944 
2945 	return (NXGE_OK);
2946 fail:
2947 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2948 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
2949 			nxgep->mac.portnum));
2950 	if (rs != NPI_SUCCESS)
2951 		return (NXGE_ERROR | rs);
2952 	else
2953 		return (status);
2954 }
2955 
2956 /* Disable TXMAC */
2957 
2958 nxge_status_t
2959 nxge_tx_mac_disable(p_nxge_t nxgep)
2960 {
2961 	npi_handle_t	handle;
2962 	npi_status_t	rs = NPI_SUCCESS;
2963 
2964 	if (isLDOMguest(nxgep))
2965 		return (NXGE_OK);
2966 
2967 	handle = nxgep->npi_handle;
2968 
2969 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
2970 			nxgep->mac.portnum));
2971 
2972 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2973 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
2974 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
2975 			goto fail;
2976 	} else {
2977 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
2978 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
2979 			goto fail;
2980 	}
2981 
2982 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
2983 			nxgep->mac.portnum));
2984 	return (NXGE_OK);
2985 fail:
2986 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2987 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
2988 			nxgep->mac.portnum));
2989 	return (NXGE_ERROR | rs);
2990 }
2991 
2992 /* Enable RXMAC */
2993 
2994 nxge_status_t
2995 nxge_rx_mac_enable(p_nxge_t nxgep)
2996 {
2997 	npi_handle_t	handle;
2998 	uint8_t 	portn;
2999 	npi_status_t	rs = NPI_SUCCESS;
3000 	nxge_status_t	status = NXGE_OK;
3001 
3002 	/* This is a service-domain-only activity. */
3003 	if (isLDOMguest(nxgep))
3004 		return (status);
3005 
3006 	handle = nxgep->npi_handle;
3007 	portn = nxgep->mac.portnum;
3008 
3009 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
3010 			portn));
3011 
3012 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
3013 		goto fail;
3014 
3015 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3016 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
3017 		    CFG_XMAC_RX)) != NPI_SUCCESS)
3018 			goto fail;
3019 	} else {
3020 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
3021 		    CFG_BMAC_RX)) != NPI_SUCCESS)
3022 			goto fail;
3023 	}
3024 
3025 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3026 	    "<== nxge_rx_mac_enable: port<%d>", portn));
3027 
3028 	return (NXGE_OK);
3029 fail:
3030 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3031 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
3032 
3033 	if (rs != NPI_SUCCESS)
3034 		return (NXGE_ERROR | rs);
3035 	else
3036 		return (status);
3037 }
3038 
3039 /* Disable RXMAC */
3040 
3041 nxge_status_t
3042 nxge_rx_mac_disable(p_nxge_t nxgep)
3043 {
3044 	npi_handle_t	handle;
3045 	uint8_t		portn;
3046 	npi_status_t	rs = NPI_SUCCESS;
3047 
3048 	/* If we are a guest domain driver, don't bother. */
3049 	if (isLDOMguest(nxgep))
3050 		return (NXGE_OK);
3051 
3052 	handle = nxgep->npi_handle;
3053 	portn = nxgep->mac.portnum;
3054 
3055 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
3056 			portn));
3057 
3058 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3059 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
3060 						CFG_XMAC_RX)) != NPI_SUCCESS)
3061 			goto fail;
3062 	} else {
3063 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
3064 						CFG_BMAC_RX)) != NPI_SUCCESS)
3065 			goto fail;
3066 	}
3067 
3068 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
3069 			portn));
3070 	return (NXGE_OK);
3071 fail:
3072 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3073 			"nxgep_rx_mac_disable: ",
3074 			"Failed to disable port<%d> RxMAC",
3075 			portn));
3076 
3077 	return (NXGE_ERROR | rs);
3078 }
3079 
3080 /* Reset TXMAC */
3081 
3082 nxge_status_t
3083 nxge_tx_mac_reset(p_nxge_t nxgep)
3084 {
3085 	npi_handle_t	handle;
3086 	uint8_t		portn;
3087 	npi_status_t	rs = NPI_SUCCESS;
3088 
3089 	handle = nxgep->npi_handle;
3090 	portn = nxgep->mac.portnum;
3091 
3092 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
3093 			portn));
3094 
3095 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3096 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
3097 		    != NPI_SUCCESS)
3098 			goto fail;
3099 	} else {
3100 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
3101 					!= NPI_SUCCESS)
3102 			goto fail;
3103 	}
3104 
3105 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
3106 			portn));
3107 
3108 	return (NXGE_OK);
3109 fail:
3110 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3111 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
3112 			portn));
3113 
3114 	return (NXGE_ERROR | rs);
3115 }
3116 
3117 /* Reset RXMAC */
3118 
3119 nxge_status_t
3120 nxge_rx_mac_reset(p_nxge_t nxgep)
3121 {
3122 	npi_handle_t	handle;
3123 	uint8_t		portn;
3124 	npi_status_t	rs = NPI_SUCCESS;
3125 
3126 	handle = nxgep->npi_handle;
3127 	portn = nxgep->mac.portnum;
3128 
3129 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
3130 			portn));
3131 
3132 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3133 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
3134 		    != NPI_SUCCESS)
3135 		goto fail;
3136 	} else {
3137 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
3138 					!= NPI_SUCCESS)
3139 		goto fail;
3140 	}
3141 
3142 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
3143 			portn));
3144 
3145 	return (NXGE_OK);
3146 fail:
3147 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3148 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
3149 			portn));
3150 	return (NXGE_ERROR | rs);
3151 }
3152 
3153 /* 10G fiber link interrupt start routine */
3154 
3155 static nxge_status_t
3156 nxge_10G_link_intr_start(p_nxge_t nxgep)
3157 {
3158 	npi_status_t	rs = NPI_SUCCESS;
3159 	uint8_t		portn = nxgep->mac.portnum;
3160 
3161 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
3162 
3163 	if (rs != NPI_SUCCESS)
3164 		return (NXGE_ERROR | rs);
3165 	else
3166 		return (NXGE_OK);
3167 }
3168 
3169 /* 10G fiber link interrupt stop routine */
3170 
3171 static nxge_status_t
3172 nxge_10G_link_intr_stop(p_nxge_t nxgep)
3173 {
3174 	npi_status_t	rs = NPI_SUCCESS;
3175 	uint8_t		portn = nxgep->mac.portnum;
3176 
3177 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
3178 
3179 	if (rs != NPI_SUCCESS)
3180 		return (NXGE_ERROR | rs);
3181 	else
3182 		return (NXGE_OK);
3183 }
3184 
3185 /* 1G fiber link interrupt start routine */
3186 
3187 static nxge_status_t
3188 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
3189 {
3190 	npi_status_t	rs = NPI_SUCCESS;
3191 	uint8_t		portn = nxgep->mac.portnum;
3192 
3193 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
3194 	if (rs != NPI_SUCCESS)
3195 		return (NXGE_ERROR | rs);
3196 	else
3197 		return (NXGE_OK);
3198 }
3199 
3200 /* 1G fiber link interrupt stop routine */
3201 
3202 static nxge_status_t
3203 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
3204 {
3205 	npi_status_t	rs = NPI_SUCCESS;
3206 	uint8_t		portn = nxgep->mac.portnum;
3207 
3208 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
3209 
3210 	if (rs != NPI_SUCCESS)
3211 		return (NXGE_ERROR | rs);
3212 	else
3213 		return (NXGE_OK);
3214 }
3215 
3216 /* 1G copper link interrupt start routine */
3217 
3218 static nxge_status_t
3219 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
3220 {
3221 	npi_status_t	rs = NPI_SUCCESS;
3222 	uint8_t		portn = nxgep->mac.portnum;
3223 
3224 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
3225 	    MII_STATUS, MII_STATUS_LINKUP);
3226 
3227 	if (rs != NPI_SUCCESS)
3228 		return (NXGE_ERROR | rs);
3229 	else
3230 		return (NXGE_OK);
3231 }
3232 
3233 /* 1G copper link interrupt stop routine */
3234 
3235 static nxge_status_t
3236 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
3237 {
3238 	npi_status_t	rs = NPI_SUCCESS;
3239 	uint8_t		portn = nxgep->mac.portnum;
3240 
3241 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
3242 
3243 	if (rs != NPI_SUCCESS)
3244 		return (NXGE_ERROR | rs);
3245 	else
3246 		return (NXGE_OK);
3247 }
3248 
3249 /* Enable/Disable Link Status change interrupt */
3250 
3251 nxge_status_t
3252 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
3253 {
3254 	uint8_t		portn;
3255 	nxge_status_t	status = NXGE_OK;
3256 
3257 	portn = nxgep->mac.portnum;
3258 
3259 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
3260 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
3261 		return (NXGE_OK);
3262 
3263 	if (enable == LINK_INTR_START)
3264 		status = nxgep->xcvr.link_intr_start(nxgep);
3265 	else if (enable == LINK_INTR_STOP)
3266 		status = nxgep->xcvr.link_intr_stop(nxgep);
3267 	if (status != NXGE_OK)
3268 		goto fail;
3269 
3270 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
3271 
3272 	return (NXGE_OK);
3273 fail:
3274 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3275 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
3276 			portn));
3277 
3278 	return (status);
3279 }
3280 
3281 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
3282 
3283 nxge_status_t
3284 nxge_mii_xcvr_init(p_nxge_t nxgep)
3285 {
3286 	p_nxge_param_t	param_arr;
3287 	p_nxge_stats_t	statsp;
3288 	uint8_t		xcvr_portn;
3289 	p_mii_regs_t	mii_regs;
3290 	mii_bmcr_t	bmcr;
3291 	mii_bmsr_t	bmsr;
3292 	mii_anar_t	anar;
3293 	mii_gcr_t	gcr;
3294 	mii_esr_t	esr;
3295 	mii_aux_ctl_t	bcm5464r_aux;
3296 	int		status = NXGE_OK;
3297 
3298 	uint_t delay;
3299 
3300 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
3301 
3302 	param_arr = nxgep->param_arr;
3303 	statsp = nxgep->statsp;
3304 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3305 
3306 	mii_regs = NULL;
3307 
3308 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3309 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3310 
3311 	/*
3312 	 * The mif phy mode may be connected to either a copper link
3313 	 * or fiber link. Read the mode control register to get the fiber
3314 	 * configuration if it is hard-wired to fiber link.
3315 	 */
3316 	(void) nxge_mii_get_link_mode(nxgep);
3317 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3318 		return (nxge_mii_xcvr_fiber_init(nxgep));
3319 	}
3320 
3321 	/*
3322 	 * Reset the transceiver.
3323 	 */
3324 	delay = 0;
3325 	bmcr.value = 0;
3326 	bmcr.bits.reset = 1;
3327 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3328 #if defined(__i386)
3329 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3330 #else
3331 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3332 #endif
3333 		goto fail;
3334 	do {
3335 		drv_usecwait(500);
3336 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3337 #if defined(__i386)
3338 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
3339 #else
3340 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
3341 #endif
3342 				!= NXGE_OK)
3343 			goto fail;
3344 		delay++;
3345 	} while ((bmcr.bits.reset) && (delay < 1000));
3346 	if (delay == 1000) {
3347 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
3348 		goto fail;
3349 	}
3350 
3351 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3352 #if defined(__i386)
3353 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
3354 #else
3355 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
3356 #endif
3357 			&bmsr.value)) != NXGE_OK)
3358 		goto fail;
3359 
3360 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
3361 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
3362 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
3363 	param_arr[param_anar_100hdx].value = 0;
3364 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
3365 	param_arr[param_anar_10hdx].value = 0;
3366 
3367 	/*
3368 	 * Initialize the xcvr statistics.
3369 	 */
3370 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
3371 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
3372 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
3373 	statsp->mac_stats.cap_100hdx = 0;
3374 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
3375 	statsp->mac_stats.cap_10hdx = 0;
3376 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
3377 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3378 
3379 	/*
3380 	 * Initialise the xcvr advertised capability statistics.
3381 	 */
3382 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
3383 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3384 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3385 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
3386 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
3387 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
3388 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
3389 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
3390 	statsp->mac_stats.adv_cap_asmpause =
3391 					param_arr[param_anar_asmpause].value;
3392 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3393 
3394 
3395 	/*
3396 	 * Check for extended status just in case we're
3397 	 * running a Gigibit phy.
3398 	 */
3399 	if (bmsr.bits.extend_status) {
3400 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3401 #if defined(__i386)
3402 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
3403 #else
3404 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
3405 #endif
3406 				!= NXGE_OK)
3407 			goto fail;
3408 		param_arr[param_anar_1000fdx].value &=
3409 					esr.bits.link_1000fdx;
3410 		param_arr[param_anar_1000hdx].value = 0;
3411 
3412 		statsp->mac_stats.cap_1000fdx =
3413 			(esr.bits.link_1000Xfdx ||
3414 				esr.bits.link_1000fdx);
3415 		statsp->mac_stats.cap_1000hdx = 0;
3416 	} else {
3417 		param_arr[param_anar_1000fdx].value = 0;
3418 		param_arr[param_anar_1000hdx].value = 0;
3419 	}
3420 
3421 	/*
3422 	 * Initialize 1G Statistics once the capability is established.
3423 	 */
3424 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3425 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3426 
3427 	/*
3428 	 * Initialise the link statistics.
3429 	 */
3430 	statsp->mac_stats.link_T4 = 0;
3431 	statsp->mac_stats.link_asmpause = 0;
3432 	statsp->mac_stats.link_pause = 0;
3433 	statsp->mac_stats.link_speed = 0;
3434 	statsp->mac_stats.link_duplex = 0;
3435 	statsp->mac_stats.link_up = 0;
3436 
3437 	/*
3438 	 * Switch off Auto-negotiation, 100M and full duplex.
3439 	 */
3440 	bmcr.value = 0;
3441 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3442 #if defined(__i386)
3443 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3444 #else
3445 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3446 #endif
3447 		goto fail;
3448 
3449 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
3450 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
3451 		bmcr.bits.loopback = 1;
3452 		bmcr.bits.enable_autoneg = 0;
3453 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
3454 			bmcr.bits.speed_1000_sel = 1;
3455 		bmcr.bits.duplex_mode = 1;
3456 		param_arr[param_autoneg].value = 0;
3457 	} else {
3458 		bmcr.bits.loopback = 0;
3459 	}
3460 
3461 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
3462 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
3463 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
3464 		param_arr[param_autoneg].value = 0;
3465 		bcm5464r_aux.value = 0;
3466 		bcm5464r_aux.bits.ext_lb = 1;
3467 		bcm5464r_aux.bits.write_1 = 1;
3468 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3469 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
3470 				!= NXGE_OK)
3471 			goto fail;
3472 	}
3473 
3474 	if (param_arr[param_autoneg].value) {
3475 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3476 				"Restarting Auto-negotiation."));
3477 		/*
3478 		 * Setup our Auto-negotiation advertisement register.
3479 		 */
3480 		anar.value = 0;
3481 		anar.bits.selector = 1;
3482 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
3483 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
3484 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
3485 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
3486 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
3487 		anar.bits.cap_asmpause = 0;
3488 		anar.bits.cap_pause = 0;
3489 		if (param_arr[param_anar_1000fdx].value ||
3490 			param_arr[param_anar_100fdx].value ||
3491 			param_arr[param_anar_10fdx].value) {
3492 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
3493 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
3494 		}
3495 
3496 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3497 #if defined(__i386)
3498 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
3499 #else
3500 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
3501 #endif
3502 				!= NXGE_OK)
3503 			goto fail;
3504 		if (bmsr.bits.extend_status) {
3505 			gcr.value = 0;
3506 			gcr.bits.ms_mode_en =
3507 				param_arr[param_master_cfg_enable].value;
3508 			gcr.bits.master =
3509 				param_arr[param_master_cfg_value].value;
3510 			gcr.bits.link_1000fdx =
3511 				param_arr[param_anar_1000fdx].value;
3512 			gcr.bits.link_1000hdx =
3513 				param_arr[param_anar_1000hdx].value;
3514 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3515 #if defined(__i386)
3516 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
3517 #else
3518 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
3519 #endif
3520 				!= NXGE_OK)
3521 				goto fail;
3522 		}
3523 
3524 		bmcr.bits.enable_autoneg = 1;
3525 		bmcr.bits.restart_autoneg = 1;
3526 
3527 	} else {
3528 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
3529 		bmcr.bits.speed_1000_sel =
3530 			param_arr[param_anar_1000fdx].value |
3531 				param_arr[param_anar_1000hdx].value;
3532 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
3533 			(param_arr[param_anar_100fdx].value |
3534 				param_arr[param_anar_100hdx].value);
3535 		if (bmcr.bits.speed_1000_sel) {
3536 			statsp->mac_stats.link_speed = 1000;
3537 			gcr.value = 0;
3538 			gcr.bits.ms_mode_en =
3539 				param_arr[param_master_cfg_enable].value;
3540 			gcr.bits.master =
3541 				param_arr[param_master_cfg_value].value;
3542 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3543 #if defined(__i386)
3544 				(uint8_t)(uint32_t)(&mii_regs->gcr),
3545 #else
3546 				(uint8_t)(uint64_t)(&mii_regs->gcr),
3547 #endif
3548 				gcr.value))
3549 				!= NXGE_OK)
3550 				goto fail;
3551 			if (param_arr[param_anar_1000fdx].value) {
3552 				bmcr.bits.duplex_mode = 1;
3553 				statsp->mac_stats.link_duplex = 2;
3554 			} else
3555 				statsp->mac_stats.link_duplex = 1;
3556 		} else if (bmcr.bits.speed_sel) {
3557 			statsp->mac_stats.link_speed = 100;
3558 			if (param_arr[param_anar_100fdx].value) {
3559 				bmcr.bits.duplex_mode = 1;
3560 				statsp->mac_stats.link_duplex = 2;
3561 			} else
3562 				statsp->mac_stats.link_duplex = 1;
3563 		} else {
3564 			statsp->mac_stats.link_speed = 10;
3565 			if (param_arr[param_anar_10fdx].value) {
3566 				bmcr.bits.duplex_mode = 1;
3567 				statsp->mac_stats.link_duplex = 2;
3568 			} else
3569 				statsp->mac_stats.link_duplex = 1;
3570 		}
3571 		if (statsp->mac_stats.link_duplex != 1) {
3572 			statsp->mac_stats.link_asmpause =
3573 						statsp->mac_stats.cap_asmpause;
3574 			statsp->mac_stats.link_pause =
3575 						statsp->mac_stats.cap_pause;
3576 		}
3577 
3578 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
3579 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
3580 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
3581 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
3582 				/* BCM5464R 1000mbps external loopback mode */
3583 				gcr.value = 0;
3584 				gcr.bits.ms_mode_en = 1;
3585 				gcr.bits.master = 1;
3586 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
3587 #if defined(__i386)
3588 					(uint8_t)(uint32_t)(&mii_regs->gcr),
3589 #else
3590 					(uint8_t)(uint64_t)(&mii_regs->gcr),
3591 #endif
3592 					gcr.value))
3593 					!= NXGE_OK)
3594 					goto fail;
3595 				bmcr.value = 0;
3596 				bmcr.bits.speed_1000_sel = 1;
3597 				statsp->mac_stats.link_speed = 1000;
3598 			} else if (statsp->port_stats.lb_mode
3599 			    == nxge_lb_ext100) {
3600 				/* BCM5464R 100mbps external loopback mode */
3601 				bmcr.value = 0;
3602 				bmcr.bits.speed_sel = 1;
3603 				bmcr.bits.duplex_mode = 1;
3604 				statsp->mac_stats.link_speed = 100;
3605 			} else if (statsp->port_stats.lb_mode
3606 			    == nxge_lb_ext10) {
3607 				/* BCM5464R 10mbps external loopback mode */
3608 				bmcr.value = 0;
3609 				bmcr.bits.duplex_mode = 1;
3610 				statsp->mac_stats.link_speed = 10;
3611 			}
3612 		}
3613 	}
3614 
3615 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3616 #if defined(__i386)
3617 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
3618 #else
3619 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
3620 #endif
3621 			bmcr.value)) != NXGE_OK)
3622 		goto fail;
3623 
3624 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3625 #if defined(__i386)
3626 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3627 #else
3628 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3629 #endif
3630 		goto fail;
3631 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
3632 
3633 	/*
3634 	 * Initialize the xcvr status kept in the context structure.
3635 	 */
3636 	nxgep->soft_bmsr.value = 0;
3637 
3638 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3639 #if defined(__i386)
3640 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
3641 #else
3642 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
3643 #endif
3644 			&nxgep->bmsr.value)) != NXGE_OK)
3645 		goto fail;
3646 
3647 	statsp->mac_stats.xcvr_inits++;
3648 	nxgep->bmsr.value = 0;
3649 
3650 fail:
3651 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3652 			"<== nxge_mii_xcvr_init status 0x%x", status));
3653 	return (status);
3654 }
3655 
3656 nxge_status_t
3657 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
3658 {
3659 	p_nxge_param_t	param_arr;
3660 	p_nxge_stats_t	statsp;
3661 	uint8_t		xcvr_portn;
3662 	p_mii_regs_t	mii_regs;
3663 	mii_bmcr_t	bmcr;
3664 	mii_bmsr_t	bmsr;
3665 	mii_gcr_t	gcr;
3666 	mii_esr_t	esr;
3667 	mii_aux_ctl_t	bcm5464r_aux;
3668 	int		status = NXGE_OK;
3669 
3670 	uint_t delay;
3671 
3672 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
3673 
3674 	param_arr = nxgep->param_arr;
3675 	statsp = nxgep->statsp;
3676 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3677 
3678 	mii_regs = NULL;
3679 
3680 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3681 	    "nxge_mii_xcvr_fiber_init: "
3682 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3683 
3684 	/*
3685 	 * Reset the transceiver.
3686 	 */
3687 	delay = 0;
3688 	bmcr.value = 0;
3689 	bmcr.bits.reset = 1;
3690 
3691 #if defined(__i386)
3692 
3693 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3694 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3695 		goto fail;
3696 #else
3697 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3698 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3699 		goto fail;
3700 #endif
3701 	do {
3702 		drv_usecwait(500);
3703 #if defined(__i386)
3704 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3705 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
3706 		    != NXGE_OK)
3707 			goto fail;
3708 #else
3709 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3710 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
3711 		    != NXGE_OK)
3712 			goto fail;
3713 #endif
3714 		delay++;
3715 	} while ((bmcr.bits.reset) && (delay < 1000));
3716 	if (delay == 1000) {
3717 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
3718 		goto fail;
3719 	}
3720 
3721 #if defined(__i386)
3722 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3723 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3724 		goto fail;
3725 #else
3726 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3727 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
3728 		goto fail;
3729 #endif
3730 
3731 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
3732 	param_arr[param_anar_100T4].value = 0;
3733 	param_arr[param_anar_100fdx].value = 0;
3734 	param_arr[param_anar_100hdx].value = 0;
3735 	param_arr[param_anar_10fdx].value = 0;
3736 	param_arr[param_anar_10hdx].value = 0;
3737 
3738 	/*
3739 	 * Initialize the xcvr statistics.
3740 	 */
3741 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
3742 	statsp->mac_stats.cap_100T4 = 0;
3743 	statsp->mac_stats.cap_100fdx = 0;
3744 	statsp->mac_stats.cap_100hdx = 0;
3745 	statsp->mac_stats.cap_10fdx = 0;
3746 	statsp->mac_stats.cap_10hdx = 0;
3747 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
3748 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3749 
3750 	/*
3751 	 * Initialize the xcvr advertised capability statistics.
3752 	 */
3753 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
3754 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3755 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3756 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
3757 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
3758 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
3759 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
3760 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
3761 	statsp->mac_stats.adv_cap_asmpause =
3762 	    param_arr[param_anar_asmpause].value;
3763 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3764 
3765 	/*
3766 	 * Check for extended status just in case we're
3767 	 * running a Gigibit phy.
3768 	 */
3769 	if (bmsr.bits.extend_status) {
3770 #if defined(__i386)
3771 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3772 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
3773 		    NXGE_OK)
3774 			goto fail;
3775 #else
3776 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3777 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
3778 		    NXGE_OK)
3779 			goto fail;
3780 #endif
3781 		param_arr[param_anar_1000fdx].value &=
3782 		    esr.bits.link_1000fdx;
3783 		param_arr[param_anar_1000hdx].value = 0;
3784 
3785 		statsp->mac_stats.cap_1000fdx =
3786 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
3787 		statsp->mac_stats.cap_1000hdx = 0;
3788 	} else {
3789 		param_arr[param_anar_1000fdx].value = 0;
3790 		param_arr[param_anar_1000hdx].value = 0;
3791 	}
3792 
3793 	/*
3794 	 * Initialize 1G Statistics once the capability is established.
3795 	 */
3796 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3797 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3798 
3799 	/*
3800 	 * Initialize the link statistics.
3801 	 */
3802 	statsp->mac_stats.link_T4 = 0;
3803 	statsp->mac_stats.link_asmpause = 0;
3804 	statsp->mac_stats.link_pause = 0;
3805 	statsp->mac_stats.link_speed = 0;
3806 	statsp->mac_stats.link_duplex = 0;
3807 	statsp->mac_stats.link_up = 0;
3808 
3809 	/*
3810 	 * Switch off Auto-negotiation, 100M and full duplex.
3811 	 */
3812 	bmcr.value = 0;
3813 #if defined(__i386)
3814 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3815 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3816 		goto fail;
3817 #else
3818 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3819 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3820 		goto fail;
3821 #endif
3822 
3823 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
3824 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
3825 		bmcr.bits.loopback = 1;
3826 		bmcr.bits.enable_autoneg = 0;
3827 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
3828 			bmcr.bits.speed_1000_sel = 1;
3829 		bmcr.bits.duplex_mode = 1;
3830 		param_arr[param_autoneg].value = 0;
3831 	} else {
3832 		bmcr.bits.loopback = 0;
3833 	}
3834 
3835 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
3836 		param_arr[param_autoneg].value = 0;
3837 		bcm5464r_aux.value = 0;
3838 		bcm5464r_aux.bits.ext_lb = 1;
3839 		bcm5464r_aux.bits.write_1 = 1;
3840 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3841 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
3842 			goto fail;
3843 	}
3844 
3845 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
3846 	bmcr.bits.speed_1000_sel = 1;
3847 	bmcr.bits.speed_sel = 0;
3848 	bmcr.bits.duplex_mode = 1;
3849 	statsp->mac_stats.link_speed = 1000;
3850 	statsp->mac_stats.link_duplex = 2;
3851 
3852 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
3853 		/* BCM5464R 1000mbps external loopback mode */
3854 		gcr.value = 0;
3855 		gcr.bits.ms_mode_en = 1;
3856 		gcr.bits.master = 1;
3857 #if defined(__i386)
3858 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3859 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
3860 		    gcr.value)) != NXGE_OK)
3861 			goto fail;
3862 #else
3863 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3864 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
3865 		    gcr.value)) != NXGE_OK)
3866 			goto fail;
3867 #endif
3868 		bmcr.value = 0;
3869 		bmcr.bits.speed_1000_sel = 1;
3870 		statsp->mac_stats.link_speed = 1000;
3871 	}
3872 
3873 #if defined(__i386)
3874 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3875 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3876 	    bmcr.value)) != NXGE_OK)
3877 		goto fail;
3878 #else
3879 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3880 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3881 	    bmcr.value)) != NXGE_OK)
3882 		goto fail;
3883 #endif
3884 
3885 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3886 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
3887 	    bmcr.value));
3888 
3889 #if defined(__i386)
3890 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3891 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3892 		goto fail;
3893 #else
3894 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3895 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
3896 		goto fail;
3897 #endif
3898 
3899 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3900 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
3901 
3902 	/*
3903 	 * Initialize the xcvr status kept in the context structure.
3904 	 */
3905 	nxgep->soft_bmsr.value = 0;
3906 #if defined(__i386)
3907 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3908 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3909 	    &nxgep->bmsr.value)) != NXGE_OK)
3910 		goto fail;
3911 #else
3912 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3913 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3914 	    &nxgep->bmsr.value)) != NXGE_OK)
3915 		goto fail;
3916 #endif
3917 
3918 	statsp->mac_stats.xcvr_inits++;
3919 	nxgep->bmsr.value = 0;
3920 
3921 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3922 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3923 	return (status);
3924 
3925 fail:
3926 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3927 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
3928 	return (status);
3929 }
3930 
3931 /* Read from a MII compliant register */
3932 
3933 nxge_status_t
3934 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
3935 		uint16_t *value)
3936 {
3937 	npi_status_t rs = NPI_SUCCESS;
3938 
3939 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
3940 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
3941 
3942 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
3943 
3944 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3945 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
3946 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
3947 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
3948 			goto fail;
3949 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
3950 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
3951 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
3952 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
3953 			goto fail;
3954 	} else
3955 		goto fail;
3956 
3957 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
3958 
3959 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
3960 			"xcvr_reg<%d> value=0x%x",
3961 			xcvr_portn, xcvr_reg, *value));
3962 	return (NXGE_OK);
3963 fail:
3964 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
3965 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3966 			"nxge_mii_read: Failed to read mii on xcvr %d",
3967 			xcvr_portn));
3968 
3969 	return (NXGE_ERROR | rs);
3970 }
3971 
3972 /* Write to a MII compliant Register */
3973 
3974 nxge_status_t
3975 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
3976 		uint16_t value)
3977 {
3978 	npi_status_t rs = NPI_SUCCESS;
3979 
3980 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
3981 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
3982 			value));
3983 
3984 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
3985 
3986 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3987 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
3988 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
3989 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
3990 			goto fail;
3991 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
3992 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
3993 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
3994 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
3995 			goto fail;
3996 	} else
3997 		goto fail;
3998 
3999 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4000 
4001 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
4002 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
4003 	return (NXGE_OK);
4004 fail:
4005 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4006 
4007 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4008 			"nxge_mii_write: Failed to write mii on xcvr %d",
4009 			xcvr_portn));
4010 
4011 	return (NXGE_ERROR | rs);
4012 }
4013 
4014 /* Perform read from Clause45 serdes / transceiver device */
4015 
4016 nxge_status_t
4017 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
4018 		uint16_t xcvr_reg, uint16_t *value)
4019 {
4020 	npi_status_t rs = NPI_SUCCESS;
4021 
4022 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
4023 			xcvr_portn));
4024 
4025 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4026 
4027 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
4028 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
4029 		goto fail;
4030 
4031 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4032 
4033 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
4034 			xcvr_portn));
4035 	return (NXGE_OK);
4036 fail:
4037 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4038 
4039 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4040 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
4041 			xcvr_portn));
4042 
4043 	return (NXGE_ERROR | rs);
4044 }
4045 
4046 /* Perform write to Clause45 serdes / transceiver device */
4047 
4048 nxge_status_t
4049 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
4050 		uint16_t xcvr_reg, uint16_t value)
4051 {
4052 	npi_status_t rs = NPI_SUCCESS;
4053 
4054 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
4055 			xcvr_portn));
4056 
4057 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4058 
4059 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
4060 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
4061 		goto fail;
4062 
4063 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4064 
4065 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
4066 			xcvr_portn));
4067 	return (NXGE_OK);
4068 fail:
4069 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4070 
4071 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4072 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
4073 			xcvr_portn));
4074 
4075 	return (NXGE_ERROR | rs);
4076 }
4077 
4078 
4079 /* Check MII to see if there is any link status change */
4080 
4081 nxge_status_t
4082 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
4083 		nxge_link_state_t *link_up)
4084 {
4085 	p_nxge_param_t	param_arr;
4086 	p_nxge_stats_t	statsp;
4087 	p_mii_regs_t	mii_regs;
4088 	p_mii_bmsr_t	soft_bmsr;
4089 	mii_anar_t	anar;
4090 	mii_anlpar_t	anlpar;
4091 	mii_anar_t	an_common;
4092 	mii_aner_t	aner;
4093 	mii_gsr_t	gsr;
4094 	nxge_status_t	status = NXGE_OK;
4095 
4096 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
4097 
4098 	mii_regs = NULL;
4099 	param_arr = nxgep->param_arr;
4100 	statsp = nxgep->statsp;
4101 	soft_bmsr = &nxgep->soft_bmsr;
4102 	*link_up = LINK_NO_CHANGE;
4103 
4104 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4105 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
4106 	    bmsr.value, bmsr_ints.value));
4107 
4108 	if (bmsr_ints.bits.link_status) {
4109 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4110 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
4111 		    bmsr.value, bmsr_ints.value));
4112 		if (bmsr.bits.link_status) {
4113 			soft_bmsr->bits.link_status = 1;
4114 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4115 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
4116 		    "0x%x", bmsr.value, bmsr_ints.value));
4117 		} else {
4118 			statsp->mac_stats.link_up = 0;
4119 			soft_bmsr->bits.link_status = 0;
4120 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4121 					"Link down cable problem"));
4122 			*link_up = LINK_IS_DOWN;
4123 		}
4124 	}
4125 
4126 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
4127 	    param_arr[param_autoneg].value) {
4128 		if (bmsr_ints.bits.auto_neg_complete) {
4129 			if (bmsr.bits.auto_neg_complete)
4130 				soft_bmsr->bits.auto_neg_complete = 1;
4131 			else
4132 				soft_bmsr->bits.auto_neg_complete = 0;
4133 		}
4134 		if (soft_bmsr->bits.link_status == 0) {
4135 			statsp->mac_stats.link_T4 = 0;
4136 			statsp->mac_stats.link_speed = 0;
4137 			statsp->mac_stats.link_duplex = 0;
4138 			statsp->mac_stats.link_asmpause = 0;
4139 			statsp->mac_stats.link_pause = 0;
4140 			statsp->mac_stats.lp_cap_autoneg = 0;
4141 			statsp->mac_stats.lp_cap_100T4 = 0;
4142 			statsp->mac_stats.lp_cap_1000fdx = 0;
4143 			statsp->mac_stats.lp_cap_1000hdx = 0;
4144 			statsp->mac_stats.lp_cap_100fdx = 0;
4145 			statsp->mac_stats.lp_cap_100hdx = 0;
4146 			statsp->mac_stats.lp_cap_10fdx = 0;
4147 			statsp->mac_stats.lp_cap_10hdx = 0;
4148 			statsp->mac_stats.lp_cap_10gfdx = 0;
4149 			statsp->mac_stats.lp_cap_10ghdx = 0;
4150 			statsp->mac_stats.lp_cap_asmpause = 0;
4151 			statsp->mac_stats.lp_cap_pause = 0;
4152 		}
4153 	} else
4154 		soft_bmsr->bits.auto_neg_complete = 1;
4155 
4156 	if ((bmsr_ints.bits.link_status ||
4157 		bmsr_ints.bits.auto_neg_complete) &&
4158 		soft_bmsr->bits.link_status &&
4159 		soft_bmsr->bits.auto_neg_complete) {
4160 		statsp->mac_stats.link_up = 1;
4161 
4162 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4163 		    "==> nxge_mii_check "
4164 		    "(auto negotiation complete or link up) "
4165 		    "soft bmsr 0x%x bmsr_int 0x%x",
4166 		    bmsr.value, bmsr_ints.value));
4167 
4168 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4169 		    param_arr[param_autoneg].value) {
4170 			if ((status = nxge_mii_read(nxgep,
4171 				statsp->mac_stats.xcvr_portn,
4172 #if defined(__i386)
4173 				(uint8_t)(uint32_t)(&mii_regs->anar),
4174 #else
4175 				(uint8_t)(uint64_t)(&mii_regs->anar),
4176 #endif
4177 					&anar.value)) != NXGE_OK)
4178 				goto fail;
4179 			if ((status = nxge_mii_read(nxgep,
4180 				statsp->mac_stats.xcvr_portn,
4181 #if defined(__i386)
4182 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4183 #else
4184 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4185 #endif
4186 					&anlpar.value)) != NXGE_OK)
4187 				goto fail;
4188 			if ((status = nxge_mii_read(nxgep,
4189 				statsp->mac_stats.xcvr_portn,
4190 #if defined(__i386)
4191 				(uint8_t)(uint32_t)(&mii_regs->aner),
4192 #else
4193 				(uint8_t)(uint64_t)(&mii_regs->aner),
4194 #endif
4195 					&aner.value)) != NXGE_OK)
4196 				goto fail;
4197 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
4198 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
4199 			statsp->mac_stats.lp_cap_100fdx =
4200 							anlpar.bits.cap_100fdx;
4201 			statsp->mac_stats.lp_cap_100hdx =
4202 							anlpar.bits.cap_100hdx;
4203 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
4204 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
4205 			statsp->mac_stats.lp_cap_asmpause =
4206 						anlpar.bits.cap_asmpause;
4207 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
4208 			an_common.value = anar.value & anlpar.value;
4209 			if (param_arr[param_anar_1000fdx].value ||
4210 				param_arr[param_anar_1000hdx].value) {
4211 				if ((status = nxge_mii_read(nxgep,
4212 					statsp->mac_stats.xcvr_portn,
4213 #if defined(__i386)
4214 					(uint8_t)(uint32_t)(&mii_regs->gsr),
4215 #else
4216 					(uint8_t)(uint64_t)(&mii_regs->gsr),
4217 #endif
4218 						&gsr.value))
4219 						!= NXGE_OK)
4220 					goto fail;
4221 				statsp->mac_stats.lp_cap_1000fdx =
4222 					gsr.bits.link_1000fdx;
4223 				statsp->mac_stats.lp_cap_1000hdx =
4224 					gsr.bits.link_1000hdx;
4225 				if (param_arr[param_anar_1000fdx].value &&
4226 					gsr.bits.link_1000fdx) {
4227 					statsp->mac_stats.link_speed = 1000;
4228 					statsp->mac_stats.link_duplex = 2;
4229 				} else if (
4230 					param_arr[param_anar_1000hdx].value &&
4231 						gsr.bits.link_1000hdx) {
4232 					statsp->mac_stats.link_speed = 1000;
4233 					statsp->mac_stats.link_duplex = 1;
4234 				}
4235 			}
4236 			if ((an_common.value != 0) &&
4237 					!(statsp->mac_stats.link_speed)) {
4238 				if (an_common.bits.cap_100T4) {
4239 					statsp->mac_stats.link_T4 = 1;
4240 					statsp->mac_stats.link_speed = 100;
4241 					statsp->mac_stats.link_duplex = 1;
4242 				} else if (an_common.bits.cap_100fdx) {
4243 					statsp->mac_stats.link_speed = 100;
4244 					statsp->mac_stats.link_duplex = 2;
4245 				} else if (an_common.bits.cap_100hdx) {
4246 					statsp->mac_stats.link_speed = 100;
4247 					statsp->mac_stats.link_duplex = 1;
4248 				} else if (an_common.bits.cap_10fdx) {
4249 					statsp->mac_stats.link_speed = 10;
4250 					statsp->mac_stats.link_duplex = 2;
4251 				} else if (an_common.bits.cap_10hdx) {
4252 					statsp->mac_stats.link_speed = 10;
4253 					statsp->mac_stats.link_duplex = 1;
4254 				} else {
4255 					goto fail;
4256 				}
4257 			}
4258 			if (statsp->mac_stats.link_duplex != 1) {
4259 				statsp->mac_stats.link_asmpause =
4260 					an_common.bits.cap_asmpause;
4261 				if (statsp->mac_stats.link_asmpause)
4262 				if ((statsp->mac_stats.cap_pause == 0) &&
4263 						(statsp->mac_stats.lp_cap_pause
4264 						== 1))
4265 						statsp->mac_stats.link_pause
4266 						= 0;
4267 					else
4268 						statsp->mac_stats.link_pause
4269 						= 1;
4270 				else
4271 					statsp->mac_stats.link_pause =
4272 						an_common.bits.cap_pause;
4273 			}
4274 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4275 			statsp->mac_stats.link_speed = 1000;
4276 			statsp->mac_stats.link_duplex = 2;
4277 		}
4278 		*link_up = LINK_IS_UP;
4279 	}
4280 
4281 	if (nxgep->link_notify) {
4282 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
4283 				LINK_IS_DOWN);
4284 		nxgep->link_notify = B_FALSE;
4285 	}
4286 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
4287 	return (NXGE_OK);
4288 fail:
4289 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4290 			"nxge_mii_check: Unable to check MII"));
4291 	return (status);
4292 }
4293 
4294 /* Check PCS to see if there is any link status change */
4295 nxge_status_t
4296 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
4297 {
4298 	p_nxge_stats_t	statsp;
4299 	nxge_status_t	status = NXGE_OK;
4300 	boolean_t	linkup;
4301 
4302 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
4303 
4304 	statsp = nxgep->statsp;
4305 	*link_up = LINK_NO_CHANGE;
4306 
4307 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
4308 	if (linkup) {
4309 		if (nxgep->link_notify ||
4310 		    nxgep->statsp->mac_stats.link_up == 0) {
4311 			statsp->mac_stats.link_up = 1;
4312 			statsp->mac_stats.link_speed = 1000;
4313 			statsp->mac_stats.link_duplex = 2;
4314 			*link_up = LINK_IS_UP;
4315 			nxgep->link_notify = B_FALSE;
4316 		}
4317 	} else {
4318 		if (nxgep->link_notify ||
4319 		    nxgep->statsp->mac_stats.link_up == 1) {
4320 			statsp->mac_stats.link_up = 0;
4321 			statsp->mac_stats.link_speed = 0;
4322 			statsp->mac_stats.link_duplex = 0;
4323 			*link_up = LINK_IS_DOWN;
4324 			nxgep->link_notify = B_FALSE;
4325 		}
4326 	}
4327 
4328 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
4329 	return (NXGE_OK);
4330 fail:
4331 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4332 	    "nxge_pcs_check: Unable to check PCS"));
4333 	return (status);
4334 }
4335 
4336 /* Add a multicast address entry into the HW hash table */
4337 
4338 nxge_status_t
4339 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
4340 {
4341 	uint32_t mchash;
4342 	p_hash_filter_t hash_filter;
4343 	uint16_t hash_bit;
4344 	boolean_t rx_init = B_FALSE;
4345 	uint_t j;
4346 	nxge_status_t status = NXGE_OK;
4347 
4348 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
4349 
4350 	RW_ENTER_WRITER(&nxgep->filter_lock);
4351 	mchash = crc32_mchash(addrp);
4352 	if (nxgep->hash_filter == NULL) {
4353 		NXGE_DEBUG_MSG((NULL, STR_CTL,
4354 			"Allocating hash filter storage."));
4355 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
4356 					KM_SLEEP);
4357 	}
4358 	hash_filter = nxgep->hash_filter;
4359 	j = mchash / HASH_REG_WIDTH;
4360 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
4361 	hash_filter->hash_filter_regs[j] |= hash_bit;
4362 	hash_filter->hash_bit_ref_cnt[mchash]++;
4363 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
4364 		hash_filter->hash_ref_cnt++;
4365 		rx_init = B_TRUE;
4366 	}
4367 	if (rx_init) {
4368 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
4369 			goto fail;
4370 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
4371 			goto fail;
4372 	}
4373 
4374 	RW_EXIT(&nxgep->filter_lock);
4375 
4376 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
4377 
4378 	return (NXGE_OK);
4379 fail:
4380 	RW_EXIT(&nxgep->filter_lock);
4381 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
4382 					"Unable to add multicast address"));
4383 	return (status);
4384 }
4385 
4386 /* Remove a multicast address entry from the HW hash table */
4387 
4388 nxge_status_t
4389 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
4390 {
4391 	uint32_t mchash;
4392 	p_hash_filter_t hash_filter;
4393 	uint16_t hash_bit;
4394 	boolean_t rx_init = B_FALSE;
4395 	uint_t j;
4396 	nxge_status_t status = NXGE_OK;
4397 
4398 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
4399 	RW_ENTER_WRITER(&nxgep->filter_lock);
4400 	mchash = crc32_mchash(addrp);
4401 	if (nxgep->hash_filter == NULL) {
4402 		NXGE_DEBUG_MSG((NULL, STR_CTL,
4403 			"Hash filter already de_allocated."));
4404 		RW_EXIT(&nxgep->filter_lock);
4405 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
4406 		return (NXGE_OK);
4407 	}
4408 	hash_filter = nxgep->hash_filter;
4409 	hash_filter->hash_bit_ref_cnt[mchash]--;
4410 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
4411 		j = mchash / HASH_REG_WIDTH;
4412 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
4413 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
4414 		hash_filter->hash_ref_cnt--;
4415 		rx_init = B_TRUE;
4416 	}
4417 	if (hash_filter->hash_ref_cnt == 0) {
4418 		NXGE_DEBUG_MSG((NULL, STR_CTL,
4419 			"De-allocating hash filter storage."));
4420 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
4421 		nxgep->hash_filter = NULL;
4422 	}
4423 
4424 	if (rx_init) {
4425 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
4426 			goto fail;
4427 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
4428 			goto fail;
4429 	}
4430 	RW_EXIT(&nxgep->filter_lock);
4431 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
4432 
4433 	return (NXGE_OK);
4434 fail:
4435 	RW_EXIT(&nxgep->filter_lock);
4436 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
4437 			"Unable to remove multicast address"));
4438 
4439 	return (status);
4440 }
4441 
4442 /* Set MAC address into MAC address HW registers */
4443 
4444 nxge_status_t
4445 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
4446 {
4447 	nxge_status_t status = NXGE_OK;
4448 
4449 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
4450 
4451 	MUTEX_ENTER(&nxgep->ouraddr_lock);
4452 	/*
4453 	 * Exit if the address is same as ouraddr or multicast or broadcast
4454 	 */
4455 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
4456 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
4457 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
4458 		goto nxge_set_mac_addr_exit;
4459 	}
4460 	nxgep->ouraddr = *addrp;
4461 	/*
4462 	 * Set new interface local address and re-init device.
4463 	 * This is destructive to any other streams attached
4464 	 * to this device.
4465 	 */
4466 	RW_ENTER_WRITER(&nxgep->filter_lock);
4467 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
4468 		goto fail;
4469 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
4470 		goto fail;
4471 
4472 	RW_EXIT(&nxgep->filter_lock);
4473 	MUTEX_EXIT(&nxgep->ouraddr_lock);
4474 	goto nxge_set_mac_addr_end;
4475 nxge_set_mac_addr_exit:
4476 	MUTEX_EXIT(&nxgep->ouraddr_lock);
4477 nxge_set_mac_addr_end:
4478 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
4479 
4480 	return (NXGE_OK);
4481 fail:
4482 	MUTEX_EXIT(&nxgep->ouraddr_lock);
4483 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
4484 			"Unable to set mac address"));
4485 	return (status);
4486 }
4487 
4488 static
4489 check_link_state_t
4490 nxge_check_link_stop(
4491 	nxge_t *nxge)
4492 {
4493 	/* If the poll has been cancelled, return STOP. */
4494 	MUTEX_ENTER(&nxge->poll_lock);
4495 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
4496 		nxge->poll_state = LINK_MONITOR_STOP;
4497 		nxge->nxge_link_poll_timerid = 0;
4498 		cv_broadcast(&nxge->poll_cv);
4499 		MUTEX_EXIT(&nxge->poll_lock);
4500 
4501 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
4502 		    "nxge_check_%s_link(port<%d>) stopped.",
4503 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
4504 		    nxge->mac.portnum));
4505 		return (CHECK_LINK_STOP);
4506 	}
4507 	MUTEX_EXIT(&nxge->poll_lock);
4508 
4509 	return (CHECK_LINK_RESCHEDULE);
4510 }
4511 
4512 /* Check status of MII (MIF or PCS) link */
4513 
4514 static nxge_status_t
4515 nxge_check_mii_link(p_nxge_t nxgep)
4516 {
4517 	mii_bmsr_t bmsr_ints, bmsr_data;
4518 	mii_anlpar_t anlpar;
4519 	mii_gsr_t gsr;
4520 	p_mii_regs_t mii_regs;
4521 	nxge_status_t status = NXGE_OK;
4522 	uint8_t portn;
4523 	nxge_link_state_t link_up;
4524 
4525 	if (nxgep->nxge_magic != NXGE_MAGIC)
4526 		return (NXGE_ERROR);
4527 
4528 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
4529 		return (NXGE_OK);
4530 
4531 	portn = nxgep->mac.portnum;
4532 
4533 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
4534 	    portn));
4535 
4536 	mii_regs = NULL;
4537 
4538 	RW_ENTER_WRITER(&nxgep->filter_lock);
4539 
4540 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
4541 		goto nxge_check_mii_link_exit;
4542 
4543 	switch (nxgep->mac.portmode) {
4544 	default:
4545 		bmsr_data.value = 0;
4546 		if ((status = nxge_mii_read(nxgep,
4547 		    nxgep->statsp->mac_stats.xcvr_portn,
4548 #if defined(__i386)
4549 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4550 #else
4551 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4552 #endif
4553 		    &bmsr_data.value)) != NXGE_OK) {
4554 			goto fail;
4555 		}
4556 
4557 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4558 		    "==> nxge_check_mii_link port<0x%x> "
4559 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
4560 		    portn, bmsr_data.value, nxgep->bmsr.value));
4561 
4562 		if (nxgep->param_arr[param_autoneg].value) {
4563 			if ((status = nxge_mii_read(nxgep,
4564 				nxgep->statsp->mac_stats.xcvr_portn,
4565 #if defined(__i386)
4566 				(uint8_t)(uint32_t)(&mii_regs->gsr),
4567 #else
4568 				(uint8_t)(uint64_t)(&mii_regs->gsr),
4569 #endif
4570 				&gsr.value)) != NXGE_OK)
4571 				goto fail;
4572 			if ((status = nxge_mii_read(nxgep,
4573 				nxgep->statsp->mac_stats.xcvr_portn,
4574 #if defined(__i386)
4575 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4576 #else
4577 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4578 #endif
4579 				&anlpar.value)) != NXGE_OK)
4580 				goto fail;
4581 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
4582 
4583 				if (nxgep->statsp->mac_stats.link_up &&
4584 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
4585 				    gsr.bits.link_1000fdx) ||
4586 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
4587 				    gsr.bits.link_1000hdx) ||
4588 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
4589 				    anlpar.bits.cap_100T4) ||
4590 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
4591 				    anlpar.bits.cap_100fdx) ||
4592 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
4593 				    anlpar.bits.cap_100hdx) ||
4594 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
4595 				    anlpar.bits.cap_10fdx) ||
4596 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
4597 				    anlpar.bits.cap_10hdx))) {
4598 					bmsr_data.bits.link_status = 0;
4599 				}
4600 			}
4601 		}
4602 
4603 		/* Workaround for link down issue */
4604 		if (bmsr_data.value == 0) {
4605 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
4606 			goto nxge_check_mii_link_exit;
4607 		}
4608 
4609 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4610 		    "==> nxge_check_mii_link port<0x%x> :"
4611 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
4612 		    portn, nxgep->bmsr.value, bmsr_data.value));
4613 
4614 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
4615 		nxgep->bmsr.value = bmsr_data.value;
4616 
4617 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4618 		    "==> nxge_check_mii_link port<0x%x> CALLING "
4619 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
4620 		    portn, bmsr_data.value, bmsr_ints.value));
4621 
4622 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
4623 		    &link_up)) != NXGE_OK) {
4624 			goto fail;
4625 		}
4626 		break;
4627 
4628 	case PORT_1G_SERDES:
4629 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4630 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
4631 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
4632 		    != NXGE_OK) {
4633 			goto fail;
4634 		}
4635 		break;
4636 	}
4637 
4638 nxge_check_mii_link_exit:
4639 	RW_EXIT(&nxgep->filter_lock);
4640 	if (link_up == LINK_IS_UP) {
4641 		nxge_link_is_up(nxgep);
4642 	} else if (link_up == LINK_IS_DOWN) {
4643 		nxge_link_is_down(nxgep);
4644 	}
4645 
4646 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
4647 
4648 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
4649 				portn));
4650 	return (NXGE_OK);
4651 
4652 fail:
4653 	RW_EXIT(&nxgep->filter_lock);
4654 
4655 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
4656 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4657 			"nxge_check_mii_link: Failed to check link port<%d>",
4658 			portn));
4659 	return (status);
4660 }
4661 
4662 
4663 /*ARGSUSED*/
4664 static nxge_status_t
4665 nxge_check_10g_link(p_nxge_t nxgep)
4666 {
4667 	uint8_t		portn;
4668 	nxge_status_t	status = NXGE_OK;
4669 	boolean_t	link_up;
4670 	uint32_t	val;
4671 	npi_status_t	rs;
4672 
4673 	if (nxgep->nxge_magic != NXGE_MAGIC)
4674 		return (NXGE_ERROR);
4675 
4676 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
4677 		return (NXGE_OK);
4678 
4679 	portn = nxgep->mac.portnum;
4680 	val = 0;
4681 	rs = NPI_SUCCESS;
4682 
4683 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
4684 	    portn));
4685 
4686 	switch (nxgep->mac.portmode) {
4687 	default:
4688 		/*
4689 		 * Check if the phy is present in case of hot swappable phy
4690 		 */
4691 		if (nxgep->hot_swappable_phy) {
4692 			boolean_t phy_present_now = B_FALSE;
4693 
4694 			/*
4695 			 * If this is the 2nd Goa port, then check 2 addresses
4696 			 * to take care of the Goa NEM card requirements.
4697 			 */
4698 			if (portn == 1) {
4699 				if (nxge_is_phy_present(nxgep,
4700 				    BCM8706_ALT_GOA_PORT1_ADDR,
4701 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
4702 					phy_present_now = B_TRUE;
4703 					nxgep->xcvr_addr =
4704 					    BCM8706_ALT_GOA_PORT1_ADDR;
4705 					goto phy_check_done;
4706 				}
4707 			}
4708 			if (nxge_is_phy_present(nxgep,
4709 			    (BCM8706_GOA_PORT_ADDR_BASE) + portn,
4710 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
4711 				nxgep->xcvr_addr =
4712 				    (BCM8706_GOA_PORT_ADDR_BASE) + portn;
4713 				phy_present_now = B_TRUE;
4714 			}
4715 
4716 phy_check_done:
4717 			if (nxgep->phy_absent) {
4718 				if (phy_present_now) {
4719 				/*
4720 				 * Detect, Initialize phy and do link up
4721 				 * set xcvr vals, link_init, nxge_init
4722 				 */
4723 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4724 					    "Hot swappable phy DETECTED!!"));
4725 					nxgep->phy_absent = B_FALSE;
4726 					(void) nxge_xcvr_find(nxgep);
4727 					(void) nxge_link_init(nxgep);
4728 					if (!(nxgep->drv_state &
4729 					    STATE_HW_INITIALIZED)) {
4730 						status = nxge_init(nxgep);
4731 						if (status != NXGE_OK) {
4732 							NXGE_ERROR_MSG((nxgep,
4733 							    NXGE_ERR_CTL,
4734 							    "Hot swappable "
4735 							    "phy present, but"
4736 							    " driver init"
4737 							    "  failed..."));
4738 							goto fail;
4739 						}
4740 					}
4741 				}
4742 
4743 				goto start_link_check;
4744 
4745 			} else if (!phy_present_now) {
4746 				/*
4747 				 * Phy gone, bring link down reset xcvr vals
4748 				 */
4749 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4750 				    "Hot swappable phy REMOVED!!"));
4751 				nxgep->phy_absent = B_TRUE;
4752 				nxgep->statsp->mac_stats.link_up = 0;
4753 				nxgep->statsp->mac_stats.link_speed = 0;
4754 				nxgep->statsp->mac_stats.link_duplex = 0;
4755 				nxge_link_is_down(nxgep);
4756 				nxgep->link_notify = B_FALSE;
4757 
4758 				(void) nxge_xcvr_find(nxgep);
4759 
4760 				goto start_link_check;
4761 
4762 			}
4763 		}
4764 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
4765 			status = nxge_mrvl88x2011_link(nxgep, &link_up);
4766 		} else {
4767 			status = nxge_check_bcm8704_link(nxgep, &link_up);
4768 		}
4769 		if (status != NXGE_OK)
4770 			goto fail;
4771 		break;
4772 	case PORT_10G_SERDES:
4773 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4774 		    XPCS_REG_STATUS, &val);
4775 		if (rs != 0)
4776 			goto fail;
4777 
4778 		link_up = B_FALSE;
4779 		if (val & XPCS_STATUS_LANE_ALIGN) {
4780 			link_up = B_TRUE;
4781 		}
4782 
4783 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4784 		    "==> nxge_check_10g_link port<%d> "
4785 		    "XPCS_REG_STATUS2 0x%x link_up %d",
4786 		    portn, val, link_up));
4787 
4788 		break;
4789 	}
4790 
4791 	if (link_up) {
4792 		if (nxgep->link_notify ||
4793 			nxgep->statsp->mac_stats.link_up == 0) {
4794 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
4795 				goto fail;
4796 			nxgep->statsp->mac_stats.link_up = 1;
4797 			nxgep->statsp->mac_stats.link_speed = 10000;
4798 			nxgep->statsp->mac_stats.link_duplex = 2;
4799 
4800 			nxge_link_is_up(nxgep);
4801 			nxgep->link_notify = B_FALSE;
4802 		}
4803 	} else {
4804 		if (nxgep->link_notify ||
4805 			nxgep->statsp->mac_stats.link_up == 1) {
4806 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
4807 				goto fail;
4808 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4809 					"Link down cable problem"));
4810 			nxgep->statsp->mac_stats.link_up = 0;
4811 			nxgep->statsp->mac_stats.link_speed = 0;
4812 			nxgep->statsp->mac_stats.link_duplex = 0;
4813 
4814 			nxge_link_is_down(nxgep);
4815 			nxgep->link_notify = B_FALSE;
4816 		}
4817 	}
4818 
4819 start_link_check:
4820 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
4821 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
4822 	    portn));
4823 	return (NXGE_OK);
4824 
4825 fail:
4826 	(void) nxge_check_link_stop(nxgep);
4827 
4828 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4829 	    "nxge_check_10g_link: Failed to check link port<%d>",
4830 	    portn));
4831 	return (status);
4832 }
4833 
4834 
4835 /* Declare link down */
4836 
4837 void
4838 nxge_link_is_down(p_nxge_t nxgep)
4839 {
4840 	p_nxge_stats_t statsp;
4841 	char link_stat_msg[64];
4842 
4843 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
4844 
4845 	statsp = nxgep->statsp;
4846 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
4847 	    statsp->mac_stats.xcvr_portn);
4848 
4849 	if (nxge_no_msg == B_FALSE) {
4850 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
4851 	}
4852 
4853 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
4854 
4855 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
4856 }
4857 
4858 /* Declare link up */
4859 
4860 void
4861 nxge_link_is_up(p_nxge_t nxgep)
4862 {
4863 	p_nxge_stats_t statsp;
4864 	char link_stat_msg[64];
4865 	uint32_t val;
4866 
4867 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
4868 
4869 	statsp = nxgep->statsp;
4870 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
4871 	    statsp->mac_stats.xcvr_portn,
4872 	    statsp->mac_stats.link_speed);
4873 
4874 	if (statsp->mac_stats.link_T4)
4875 		(void) strcat(link_stat_msg, "T4");
4876 	else if (statsp->mac_stats.link_duplex == 2)
4877 		(void) strcat(link_stat_msg, "full duplex");
4878 	else
4879 		(void) strcat(link_stat_msg, "half duplex");
4880 
4881 	(void) nxge_xif_init(nxgep);
4882 
4883 	/* Clean up symbol errors incurred during link transition */
4884 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
4885 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
4886 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4887 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
4888 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4889 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
4890 	}
4891 
4892 	if (nxge_no_msg == B_FALSE) {
4893 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
4894 	}
4895 
4896 	mac_link_update(nxgep->mach, LINK_STATE_UP);
4897 
4898 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
4899 }
4900 
4901 /*
4902  * Calculate the bit in the multicast address filter
4903  * that selects the given * address.
4904  * Note: For GEM, the last 8-bits are used.
4905  */
4906 uint32_t
4907 crc32_mchash(p_ether_addr_t addr)
4908 {
4909 	uint8_t *cp;
4910 	uint32_t crc;
4911 	uint32_t c;
4912 	int byte;
4913 	int bit;
4914 
4915 	cp = (uint8_t *)addr;
4916 	crc = (uint32_t)0xffffffff;
4917 	for (byte = 0; byte < 6; byte++) {
4918 		c = (uint32_t)cp[byte];
4919 		for (bit = 0; bit < 8; bit++) {
4920 			if ((c & 0x1) ^ (crc & 0x1))
4921 				crc = (crc >> 1)^0xedb88320;
4922 			else
4923 				crc = (crc >> 1);
4924 			c >>= 1;
4925 		}
4926 	}
4927 	return ((~crc) >> (32 - HASH_BITS));
4928 }
4929 
4930 /* Reset serdes */
4931 
4932 nxge_status_t
4933 nxge_serdes_reset(p_nxge_t nxgep)
4934 {
4935 	npi_handle_t		handle;
4936 
4937 	handle = nxgep->npi_handle;
4938 
4939 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
4940 	drv_usecwait(500);
4941 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
4942 
4943 	return (NXGE_OK);
4944 }
4945 
4946 /* Monitor link status using interrupt or polling */
4947 nxge_status_t
4948 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
4949 {
4950 	nxge_status_t status = NXGE_OK;
4951 
4952 	/* If we are a guest domain driver, don't bother. */
4953 	if (isLDOMguest(nxgep))
4954 		return (status);
4955 
4956 	/*
4957 	 * Return immediately if this is an imaginary XMAC port.
4958 	 * (At least, we don't have 4-port XMAC cards yet.)
4959 	 */
4960 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
4961 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
4962 	    (nxgep->mac.portnum > 1))
4963 		return (NXGE_OK);
4964 
4965 	if (nxgep->statsp == NULL) {
4966 		/* stats has not been allocated. */
4967 		return (NXGE_OK);
4968 	}
4969 	/* Don't check link if we're in internal loopback mode */
4970 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
4971 		return (NXGE_OK);
4972 
4973 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4974 	    "==> nxge_link_monitor port<%d> enable=%d",
4975 	    nxgep->mac.portnum, enable));
4976 	if (enable == LINK_MONITOR_START) {
4977 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
4978 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
4979 			    != NXGE_OK)
4980 				goto fail;
4981 		} else {
4982 			timeout_id_t timerid;
4983 
4984 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
4985 				return (NXGE_OK);
4986 
4987 			if (nxgep->xcvr.check_link) {
4988 				timerid = timeout(
4989 				    (fptrv_t)(nxgep->xcvr.check_link),
4990 				    nxgep,
4991 				    drv_usectohz(LINK_MONITOR_PERIOD));
4992 				MUTEX_ENTER(&nxgep->poll_lock);
4993 				nxgep->nxge_link_poll_timerid = timerid;
4994 				MUTEX_EXIT(&nxgep->poll_lock);
4995 			} else {
4996 				return (NXGE_ERROR);
4997 			}
4998 		}
4999 	} else {
5000 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
5001 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
5002 			    != NXGE_OK)
5003 				goto fail;
5004 		} else {
5005 			clock_t rv;
5006 
5007 			MUTEX_ENTER(&nxgep->poll_lock);
5008 
5009 			/* If <timerid> == 0, the link monitor has */
5010 			/* never been started, or just now stopped. */
5011 			if (nxgep->nxge_link_poll_timerid == 0) {
5012 				MUTEX_EXIT(&nxgep->poll_lock);
5013 				return (NXGE_OK);
5014 			}
5015 
5016 			nxgep->poll_state = LINK_MONITOR_STOPPING;
5017 			rv = cv_timedwait(&nxgep->poll_cv,
5018 			    &nxgep->poll_lock,
5019 			    ddi_get_lbolt() +
5020 			    drv_usectohz(LM_WAIT_MULTIPLIER *
5021 			    LINK_MONITOR_PERIOD));
5022 			if (rv == -1) {
5023 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5024 				    "==> stopping port %d: "
5025 				    "cv_timedwait(%d) timed out",
5026 				    nxgep->mac.portnum, nxgep->poll_state));
5027 				nxgep->poll_state = LINK_MONITOR_STOP;
5028 				nxgep->nxge_link_poll_timerid = 0;
5029 			}
5030 
5031 			MUTEX_EXIT(&nxgep->poll_lock);
5032 		}
5033 	}
5034 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5035 	    "<== nxge_link_monitor port<%d> enable=%d",
5036 	    nxgep->mac.portnum, enable));
5037 
5038 	return (NXGE_OK);
5039 fail:
5040 	return (status);
5041 }
5042 
5043 /* Set promiscous mode */
5044 
5045 nxge_status_t
5046 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
5047 {
5048 	nxge_status_t status = NXGE_OK;
5049 
5050 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
5051 
5052 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
5053 
5054 	RW_ENTER_WRITER(&nxgep->filter_lock);
5055 
5056 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
5057 		goto fail;
5058 	}
5059 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
5060 		goto fail;
5061 	}
5062 
5063 	RW_EXIT(&nxgep->filter_lock);
5064 
5065 	if (on)
5066 		nxgep->statsp->mac_stats.promisc = B_TRUE;
5067 	else
5068 		nxgep->statsp->mac_stats.promisc = B_FALSE;
5069 
5070 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
5071 
5072 	return (NXGE_OK);
5073 fail:
5074 	RW_EXIT(&nxgep->filter_lock);
5075 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
5076 	    "Unable to set promisc (%d)", on));
5077 
5078 	return (status);
5079 }
5080 
5081 /*ARGSUSED*/
5082 uint_t
5083 nxge_mif_intr(void *arg1, void *arg2)
5084 {
5085 #ifdef	NXGE_DEBUG
5086 	p_nxge_t		nxgep = (p_nxge_t)arg2;
5087 #endif
5088 #if NXGE_MIF
5089 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
5090 	uint32_t		status;
5091 	npi_handle_t		handle;
5092 	uint8_t			portn;
5093 	p_nxge_stats_t		statsp;
5094 #endif
5095 
5096 #ifdef	NXGE_MIF
5097 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
5098 		nxgep = ldvp->nxgep;
5099 	}
5100 	nxgep = ldvp->nxgep;
5101 #endif
5102 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
5103 
5104 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
5105 	return (DDI_INTR_CLAIMED);
5106 
5107 mif_intr_fail:
5108 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
5109 	return (DDI_INTR_UNCLAIMED);
5110 }
5111 
5112 /*ARGSUSED*/
5113 uint_t
5114 nxge_mac_intr(void *arg1, void *arg2)
5115 {
5116 	p_nxge_t		nxgep = (p_nxge_t)arg2;
5117 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
5118 	p_nxge_ldg_t		ldgp;
5119 	uint32_t		status;
5120 	npi_handle_t		handle;
5121 	uint8_t			portn;
5122 	p_nxge_stats_t		statsp;
5123 	npi_status_t		rs = NPI_SUCCESS;
5124 
5125 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
5126 		nxgep = ldvp->nxgep;
5127 	}
5128 
5129 	ldgp = ldvp->ldgp;
5130 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
5131 	    "group %d", ldgp->ldg));
5132 
5133 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
5134 	/*
5135 	 * This interrupt handler is for a specific
5136 	 * mac port.
5137 	 */
5138 	statsp = (p_nxge_stats_t)nxgep->statsp;
5139 	portn = nxgep->mac.portnum;
5140 
5141 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
5142 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
5143 
5144 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
5145 		rs = npi_xmac_tx_get_istatus(handle, portn,
5146 					(xmac_tx_iconfig_t *)&status);
5147 		if (rs != NPI_SUCCESS)
5148 			goto npi_fail;
5149 		if (status & ICFG_XMAC_TX_ALL) {
5150 			if (status & ICFG_XMAC_TX_UNDERRUN) {
5151 				statsp->xmac_stats.tx_underflow_err++;
5152 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5153 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
5154 			}
5155 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
5156 				statsp->xmac_stats.tx_maxpktsize_err++;
5157 				/*
5158 				 * Do not send FMA ereport because this
5159 				 * error does not indicate HW failure.
5160 				 */
5161 			}
5162 			if (status & ICFG_XMAC_TX_OVERFLOW) {
5163 				statsp->xmac_stats.tx_overflow_err++;
5164 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5165 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
5166 			}
5167 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
5168 				statsp->xmac_stats.tx_fifo_xfr_err++;
5169 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5170 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
5171 			}
5172 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
5173 				statsp->xmac_stats.tx_byte_cnt +=
5174 							XTXMAC_BYTE_CNT_MASK;
5175 			}
5176 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
5177 				statsp->xmac_stats.tx_frame_cnt +=
5178 							XTXMAC_FRM_CNT_MASK;
5179 			}
5180 		}
5181 
5182 		rs = npi_xmac_rx_get_istatus(handle, portn,
5183 					(xmac_rx_iconfig_t *)&status);
5184 		if (rs != NPI_SUCCESS)
5185 			goto npi_fail;
5186 		if (status & ICFG_XMAC_RX_ALL) {
5187 			if (status & ICFG_XMAC_RX_OVERFLOW)
5188 				statsp->xmac_stats.rx_overflow_err++;
5189 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
5190 				statsp->xmac_stats.rx_underflow_err++;
5191 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5192 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
5193 			}
5194 			/*
5195 			 * Do not send FMA ereport for the following 3 errors
5196 			 * because they do not indicate HW failures.
5197 			 */
5198 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
5199 				statsp->xmac_stats.rx_crc_err_cnt +=
5200 							XRXMAC_CRC_ER_CNT_MASK;
5201 			}
5202 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
5203 				statsp->xmac_stats.rx_len_err_cnt +=
5204 							MAC_LEN_ER_CNT_MASK;
5205 			}
5206 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
5207 				statsp->xmac_stats.rx_viol_err_cnt +=
5208 							XRXMAC_CD_VIO_CNT_MASK;
5209 			}
5210 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
5211 				statsp->xmac_stats.rx_byte_cnt +=
5212 							XRXMAC_BT_CNT_MASK;
5213 			}
5214 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
5215 				statsp->xmac_stats.rx_hist1_cnt +=
5216 							XRXMAC_HIST_CNT1_MASK;
5217 			}
5218 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
5219 				statsp->xmac_stats.rx_hist2_cnt +=
5220 							XRXMAC_HIST_CNT2_MASK;
5221 			}
5222 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
5223 				statsp->xmac_stats.rx_hist3_cnt +=
5224 							XRXMAC_HIST_CNT3_MASK;
5225 			}
5226 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
5227 				statsp->xmac_stats.rx_hist4_cnt +=
5228 							XRXMAC_HIST_CNT4_MASK;
5229 			}
5230 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
5231 				statsp->xmac_stats.rx_hist5_cnt +=
5232 							XRXMAC_HIST_CNT5_MASK;
5233 			}
5234 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
5235 				statsp->xmac_stats.rx_hist6_cnt +=
5236 							XRXMAC_HIST_CNT6_MASK;
5237 			}
5238 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
5239 				statsp->xmac_stats.rx_broadcast_cnt +=
5240 							XRXMAC_BC_FRM_CNT_MASK;
5241 			}
5242 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
5243 				statsp->xmac_stats.rx_mult_cnt +=
5244 							XRXMAC_MC_FRM_CNT_MASK;
5245 			}
5246 			/*
5247 			 * Do not send FMA ereport for the following 3 errors
5248 			 * because they do not indicate HW failures.
5249 			 */
5250 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
5251 				statsp->xmac_stats.rx_frag_cnt +=
5252 							XRXMAC_FRAG_CNT_MASK;
5253 			}
5254 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
5255 				statsp->xmac_stats.rx_frame_align_err_cnt +=
5256 							XRXMAC_AL_ER_CNT_MASK;
5257 			}
5258 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
5259 				statsp->xmac_stats.rx_linkfault_err_cnt +=
5260 							XMAC_LINK_FLT_CNT_MASK;
5261 			}
5262 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
5263 				statsp->xmac_stats.rx_remotefault_err++;
5264 			}
5265 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
5266 				statsp->xmac_stats.rx_localfault_err++;
5267 			}
5268 		}
5269 
5270 		rs = npi_xmac_ctl_get_istatus(handle, portn,
5271 						(xmac_ctl_iconfig_t *)&status);
5272 		if (rs != NPI_SUCCESS)
5273 			goto npi_fail;
5274 		if (status & ICFG_XMAC_CTRL_ALL) {
5275 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
5276 				statsp->xmac_stats.rx_pause_cnt++;
5277 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
5278 				statsp->xmac_stats.tx_pause_state++;
5279 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
5280 				statsp->xmac_stats.tx_nopause_state++;
5281 		}
5282 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
5283 		rs = npi_bmac_tx_get_istatus(handle, portn,
5284 						(bmac_tx_iconfig_t *)&status);
5285 		if (rs != NPI_SUCCESS)
5286 			goto npi_fail;
5287 		if (status & ICFG_BMAC_TX_ALL) {
5288 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
5289 				statsp->bmac_stats.tx_underrun_err++;
5290 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5291 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
5292 			}
5293 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
5294 				statsp->bmac_stats.tx_max_pkt_err++;
5295 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5296 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
5297 			}
5298 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
5299 				statsp->bmac_stats.tx_byte_cnt +=
5300 							BTXMAC_BYTE_CNT_MASK;
5301 			}
5302 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
5303 				statsp->bmac_stats.tx_frame_cnt +=
5304 							BTXMAC_FRM_CNT_MASK;
5305 			}
5306 		}
5307 
5308 		rs = npi_bmac_rx_get_istatus(handle, portn,
5309 						(bmac_rx_iconfig_t *)&status);
5310 		if (rs != NPI_SUCCESS)
5311 			goto npi_fail;
5312 		if (status & ICFG_BMAC_RX_ALL) {
5313 			if (status & ICFG_BMAC_RX_OVERFLOW) {
5314 				statsp->bmac_stats.rx_overflow_err++;
5315 			}
5316 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
5317 				statsp->bmac_stats.rx_frame_cnt +=
5318 							RXMAC_FRM_CNT_MASK;
5319 			}
5320 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
5321 				statsp->bmac_stats.rx_crc_err_cnt +=
5322 							BMAC_CRC_ER_CNT_MASK;
5323 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5324 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
5325 			}
5326 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
5327 				statsp->bmac_stats.rx_len_err_cnt +=
5328 							MAC_LEN_ER_CNT_MASK;
5329 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5330 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
5331 			}
5332 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
5333 				statsp->bmac_stats.rx_viol_err_cnt +=
5334 							BMAC_CD_VIO_CNT_MASK;
5335 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5336 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
5337 			}
5338 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
5339 				statsp->bmac_stats.rx_byte_cnt +=
5340 							BRXMAC_BYTE_CNT_MASK;
5341 			}
5342 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
5343 				statsp->bmac_stats.rx_align_err_cnt +=
5344 							BMAC_AL_ER_CNT_MASK;
5345 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
5346 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
5347 			}
5348 
5349 			rs = npi_bmac_ctl_get_istatus(handle, portn,
5350 						(bmac_ctl_iconfig_t *)&status);
5351 			if (rs != NPI_SUCCESS)
5352 				goto npi_fail;
5353 
5354 			if (status & ICFG_BMAC_CTL_ALL) {
5355 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
5356 					statsp->bmac_stats.rx_pause_cnt++;
5357 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
5358 					statsp->bmac_stats.tx_pause_state++;
5359 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
5360 					statsp->bmac_stats.tx_nopause_state++;
5361 			}
5362 		}
5363 
5364 	if (ldgp->nldvs == 1) {
5365 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
5366 			B_TRUE, ldgp->ldg_timer);
5367 	}
5368 
5369 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
5370 	return (DDI_INTR_CLAIMED);
5371 
5372 npi_fail:
5373 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
5374 	return (DDI_INTR_UNCLAIMED);
5375 }
5376 
5377 nxge_status_t
5378 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
5379 {
5380 	uint8_t		phy_port_addr;
5381 	nxge_status_t	status = NXGE_OK;
5382 	boolean_t	rx_sig_ok;
5383 	boolean_t	pcs_blk_lock;
5384 	boolean_t	link_align;
5385 	uint16_t	val1, val2, val3;
5386 #ifdef	NXGE_DEBUG_SYMBOL_ERR
5387 	uint16_t	val_debug;
5388 	uint16_t	val;
5389 #endif
5390 
5391 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
5392 
5393 #ifdef	NXGE_DEBUG_SYMBOL_ERR
5394 	/* Check Device 3 Register Device 3 0xC809 */
5395 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
5396 	if ((val_debug & ~0x200) != 0) {
5397 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
5398 				nxgep->mac.portnum, val_debug);
5399 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
5400 				&val_debug);
5401 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
5402 				nxgep->mac.portnum, val_debug);
5403 	}
5404 
5405 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5406 					XPCS_REG_DESCWERR_COUNTER, &val);
5407 	if (val != 0)
5408 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
5409 
5410 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5411 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
5412 	if (val != 0)
5413 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
5414 
5415 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5416 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
5417 	if (val != 0)
5418 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
5419 #endif
5420 
5421 	/* Check from BCM8704 if 10G link is up or down */
5422 
5423 	/* Check Device 1 Register 0xA bit0 */
5424 	status = nxge_mdio_read(nxgep, phy_port_addr,
5425 			BCM8704_PMA_PMD_DEV_ADDR,
5426 			BCM8704_PMD_RECEIVE_SIG_DETECT,
5427 			&val1);
5428 	if (status != NXGE_OK)
5429 		goto fail;
5430 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
5431 
5432 	/* Check Device 3 Register 0x20 bit0 */
5433 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
5434 			BCM8704_PCS_DEV_ADDR,
5435 			BCM8704_10GBASE_R_PCS_STATUS_REG,
5436 			&val2)) != NPI_SUCCESS)
5437 		goto fail;
5438 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
5439 
5440 	/* Check Device 4 Register 0x18 bit12 */
5441 	status = nxge_mdio_read(nxgep, phy_port_addr,
5442 			BCM8704_PHYXS_ADDR,
5443 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
5444 			&val3);
5445 	if (status != NXGE_OK)
5446 		goto fail;
5447 
5448 	switch (nxgep->chip_id) {
5449 	case BCM8704_CHIP_ID:
5450 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
5451 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
5452 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
5453 		break;
5454 	case BCM8706_CHIP_ID:
5455 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
5456 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
5457 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
5458 		    B_TRUE : B_FALSE;
5459 		break;
5460 	default:
5461 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
5462 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
5463 		goto fail;
5464 	}
5465 
5466 
5467 #ifdef	NXGE_DEBUG_ALIGN_ERR
5468 	/* Temp workaround for link down issue */
5469 	if (pcs_blk_lock == B_FALSE) {
5470 		if (val2 != 0x4) {
5471 			pcs_blk_lock = B_TRUE;
5472 			cmn_err(CE_NOTE,
5473 				"!LINK DEBUG: port%d PHY Dev3 "
5474 				"Reg 0x20 = 0x%x\n",
5475 				nxgep->mac.portnum, val2);
5476 		}
5477 	}
5478 
5479 	if (link_align == B_FALSE) {
5480 		if (val3 != 0x140f) {
5481 			link_align = B_TRUE;
5482 			cmn_err(CE_NOTE,
5483 				"!LINK DEBUG: port%d PHY Dev4 "
5484 				"Reg 0x18 = 0x%x\n",
5485 				nxgep->mac.portnum, val3);
5486 		}
5487 	}
5488 
5489 	if (rx_sig_ok == B_FALSE) {
5490 		if ((val2 == 0) || (val3 == 0)) {
5491 			rx_sig_ok = B_TRUE;
5492 			cmn_err(CE_NOTE,
5493 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
5494 				nxgep->mac.portnum);
5495 		}
5496 	}
5497 #endif
5498 
5499 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
5500 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
5501 
5502 	return (NXGE_OK);
5503 fail:
5504 	return (status);
5505 }
5506 
5507 static nxge_status_t
5508 nxge_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
5509 {
5510 	uint8_t		phy;
5511 	nxge_status_t   status = NXGE_OK;
5512 	boolean_t	pma_status;
5513 	boolean_t	pcs_status;
5514 	boolean_t	xgxs_status;
5515 	uint16_t	val;
5516 
5517 	phy = nxgep->statsp->mac_stats.xcvr_portn;
5518 
5519 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
5520 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
5521 
5522 	*link_up = B_FALSE;
5523 
5524 	/* Check from Marvell 88X2011 if 10G link is up or down */
5525 
5526 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
5527 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
5528 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
5529 
5530 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5531 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
5532 
5533 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
5534 
5535 	/* Check PMC Register : 3.0001.2 == 1: read twice */
5536 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
5537 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
5538 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
5539 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
5540 
5541 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5542 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
5543 
5544 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
5545 
5546 	/* Check XGXS Register : 4.0018.[0-3,12] */
5547 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
5548 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
5549 
5550 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5551 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
5552 
5553 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
5554 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
5555 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
5556 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
5557 
5558 	*link_up = (pma_status && pcs_status && xgxs_status) ?
5559 	    B_TRUE : B_FALSE;
5560 
5561 fail:
5562 
5563 	if (*link_up == B_FALSE) {
5564 		/* PCS OFF */
5565 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
5566 	} else {
5567 		/* PCS Activity */
5568 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
5569 	}
5570 
5571 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5572 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
5573 
5574 	return (status);
5575 }
5576 
5577 nxge_status_t
5578 nxge_10g_link_led_on(p_nxge_t nxgep)
5579 {
5580 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
5581 	    != NPI_SUCCESS)
5582 		return (NXGE_ERROR);
5583 	else
5584 		return (NXGE_OK);
5585 }
5586 
5587 nxge_status_t
5588 nxge_10g_link_led_off(p_nxge_t nxgep)
5589 {
5590 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
5591 	    != NPI_SUCCESS)
5592 		return (NXGE_ERROR);
5593 	else
5594 		return (NXGE_OK);
5595 }
5596 
5597 static boolean_t
5598 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
5599 {
5600 	uint32_t pma_pmd_id = 0;
5601 	uint32_t pcs_id = 0;
5602 	uint32_t phy_id = 0;
5603 
5604 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
5605 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5606 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
5607 	if ((pma_pmd_id & mask) == (id & mask))
5608 		goto found_phy;
5609 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
5610 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5611 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
5612 	if ((pcs_id & mask) == (id & mask))
5613 		goto found_phy;
5614 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
5615 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5616 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
5617 	if ((phy_id & mask) == (id & mask))
5618 		goto found_phy;
5619 
5620 	return (B_FALSE);
5621 
5622 found_phy:
5623 	return (B_TRUE);
5624 }
5625 
5626 /* Check if the given id read using the given MDIO Clause is supported */
5627 
5628 static boolean_t
5629 nxge_is_supported_phy(uint32_t id, uint8_t type)
5630 {
5631 	int		i;
5632 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
5633 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
5634 	boolean_t	found = B_FALSE;
5635 
5636 	switch (type) {
5637 	case CLAUSE_45_TYPE:
5638 		for (i = 0; i < cl45_arr_len; i++) {
5639 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
5640 			    (id & BCM_PHY_ID_MASK)) {
5641 				found = B_TRUE;
5642 				break;
5643 			}
5644 		}
5645 		break;
5646 	case CLAUSE_22_TYPE:
5647 		for (i = 0; i < cl22_arr_len; i++) {
5648 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
5649 			    (id & BCM_PHY_ID_MASK)) {
5650 				found = B_TRUE;
5651 				break;
5652 			}
5653 		}
5654 		break;
5655 	default:
5656 		break;
5657 	}
5658 
5659 	return (found);
5660 }
5661 
5662 static uint32_t
5663 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
5664 {
5665 	uint16_t	val1 = 0;
5666 	uint16_t	val2 = 0;
5667 	uint32_t	pma_pmd_dev_id = 0;
5668 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
5669 
5670 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5671 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
5672 	    NXGE_DEV_ID_REG_1, &val1);
5673 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
5674 	    NXGE_DEV_ID_REG_2, &val2);
5675 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5676 
5677 	pma_pmd_dev_id = val1;
5678 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
5679 	pma_pmd_dev_id |= val2;
5680 
5681 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
5682 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
5683 
5684 	return (pma_pmd_dev_id);
5685 }
5686 
5687 static uint32_t
5688 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
5689 {
5690 	uint16_t	val1 = 0;
5691 	uint16_t	val2 = 0;
5692 	uint32_t	pcs_dev_id = 0;
5693 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
5694 
5695 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5696 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
5697 	    NXGE_DEV_ID_REG_1, &val1);
5698 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
5699 	    NXGE_DEV_ID_REG_2, &val2);
5700 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5701 
5702 	pcs_dev_id = val1;
5703 	pcs_dev_id = (pcs_dev_id << 16);
5704 	pcs_dev_id |= val2;
5705 
5706 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
5707 	    "devid[0x%llx]", phy_port, pcs_dev_id));
5708 
5709 	return (pcs_dev_id);
5710 }
5711 
5712 static uint32_t
5713 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
5714 {
5715 	uint16_t	val1 = 0;
5716 	uint16_t	val2 = 0;
5717 	uint32_t	phy_id = 0;
5718 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
5719 	npi_status_t	npi_status = NPI_SUCCESS;
5720 
5721 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5722 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
5723 	    &val1);
5724 	if (npi_status != NPI_SUCCESS) {
5725 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
5726 		    "clause 22 read to reg 2 failed!!!"));
5727 		goto exit;
5728 	}
5729 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
5730 	    &val2);
5731 	if (npi_status != 0) {
5732 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
5733 		    "clause 22 read to reg 3 failed!!!"));
5734 		goto exit;
5735 	}
5736 	phy_id = val1;
5737 	phy_id = (phy_id << 16);
5738 	phy_id |= val2;
5739 
5740 exit:
5741 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5742 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
5743 	    phy_port, phy_id));
5744 
5745 	return (phy_id);
5746 }
5747 
5748 /*
5749  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
5750  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
5751  * read. Then use the values obtained to determine the phy type of each port
5752  * and the Neptune type.
5753  */
5754 
5755 nxge_status_t
5756 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
5757 {
5758 	int		i, j, l;
5759 	uint32_t	pma_pmd_dev_id = 0;
5760 	uint32_t	pcs_dev_id = 0;
5761 	uint32_t	phy_id = 0;
5762 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
5763 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
5764 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
5765 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
5766 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
5767 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
5768 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
5769 	uint8_t		total_port_fd, total_phy_fd;
5770 	nxge_status_t	status = NXGE_OK;
5771 
5772 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
5773 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5774 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
5775 	    nxgep->niu_type));
5776 
5777 	if (isLDOMguest(nxgep)) {
5778 		hw_p->niu_type = NIU_TYPE_NONE;
5779 		hw_p->platform_type = P_NEPTUNE_NONE;
5780 		return (NXGE_OK);
5781 	}
5782 
5783 	j = l = 0;
5784 	total_port_fd = total_phy_fd = 0;
5785 	/*
5786 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
5787 	 * for on chip serdes usages.
5788 	 */
5789 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
5790 
5791 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
5792 
5793 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
5794 			pma_pmd_dev_fd[i] = 1;
5795 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
5796 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
5797 			if (j < NXGE_PORTS_NEPTUNE) {
5798 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
5799 				    BCM_PHY_ID_MASK;
5800 				port_fd_arr[j] = (uint8_t)i;
5801 				j++;
5802 			}
5803 		} else {
5804 			pma_pmd_dev_fd[i] = 0;
5805 		}
5806 
5807 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
5808 
5809 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
5810 			pcs_dev_fd[i] = 1;
5811 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
5812 			    "dev %x found", i, pcs_dev_id));
5813 			if (pma_pmd_dev_fd[i] == 1) {
5814 				port_pcs_dev_id[j - 1] = pcs_dev_id &
5815 				    BCM_PHY_ID_MASK;
5816 			} else {
5817 				if (j < NXGE_PORTS_NEPTUNE) {
5818 					port_pcs_dev_id[j] = pcs_dev_id &
5819 					    BCM_PHY_ID_MASK;
5820 					port_fd_arr[j] = (uint8_t)i;
5821 					j++;
5822 				}
5823 			}
5824 		} else {
5825 			pcs_dev_fd[i] = 0;
5826 		}
5827 
5828 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
5829 			total_port_fd ++;
5830 		}
5831 
5832 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
5833 
5834 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
5835 			total_phy_fd ++;
5836 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
5837 			    "%x found", i, phy_id));
5838 			if (l < NXGE_PORTS_NEPTUNE) {
5839 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
5840 				phy_fd_arr[l] = (uint8_t)i;
5841 				l++;
5842 			}
5843 		}
5844 	}
5845 
5846 	switch (total_port_fd) {
5847 	case 2:
5848 		switch (total_phy_fd) {
5849 		case 2:
5850 			/* 2 10G, 2 1G RGMII Fiber */
5851 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
5852 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
5853 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
5854 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
5855 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
5856 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
5857 
5858 				hw_p->platform_type =
5859 					    P_NEPTUNE_GENERIC;
5860 
5861 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
5862 
5863 				hw_p->xcvr_addr[0] = port_fd_arr[0];
5864 				hw_p->xcvr_addr[1] = port_fd_arr[1];
5865 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
5866 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
5867 
5868 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5869 				    "ARTM card with 2 10G, 2 1G"));
5870 			} else {
5871 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5872 				    "Unsupported neptune type 1"));
5873 				goto error_exit;
5874 			}
5875 			break;
5876 
5877 		case 1:
5878 			/* TODO - 2 10G, 1 1G */
5879 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5880 			    "Unsupported neptune type 2 10G, 1 1G"));
5881 			goto error_exit;
5882 		case 0:
5883 			/* 2 10G */
5884 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
5885 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
5886 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
5887 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
5888 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
5889 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
5890 			    ((port_pma_pmd_dev_id[0] ==
5891 			    MARVELL_88X201X_PHY_ID) &&
5892 			    (port_pma_pmd_dev_id[1] ==
5893 			    MARVELL_88X201X_PHY_ID))) {
5894 
5895 				/*
5896 				 * Check the first phy port address against
5897 				 * the known phy start addresses to determine
5898 				 * the platform type.
5899 				 */
5900 
5901 				switch (port_fd_arr[0]) {
5902 				case BCM8704_NEPTUNE_PORT_ADDR_BASE:
5903 					/*
5904 					 * The Marvell case also falls into
5905 					 * this case as
5906 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
5907 					 * == BCM8704_NEPTUNE_PORT_ADDR_BASE.
5908 					 * This is OK for the 2 10G case.
5909 					 */
5910 					hw_p->niu_type = NEPTUNE_2_10GF;
5911 					hw_p->platform_type =
5912 					    P_NEPTUNE_ATLAS_2PORT;
5913 					break;
5914 				case BCM8706_GOA_PORT_ADDR_BASE:
5915 					if (hw_p->platform_type !=
5916 					    P_NEPTUNE_NIU) {
5917 						hw_p->platform_type =
5918 						    P_NEPTUNE_GENERIC;
5919 						hw_p->niu_type =
5920 						    NEPTUNE_2_10GF;
5921 					}
5922 					break;
5923 				default:
5924 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5925 					    "Unsupported neptune type 2 - 1"));
5926 					goto error_exit;
5927 				}
5928 
5929 				for (i = 0; i < 2; i++) {
5930 					hw_p->xcvr_addr[i] = port_fd_arr[i];
5931 				}
5932 			} else {
5933 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5934 				    "Unsupported neptune type 2"));
5935 				goto error_exit;
5936 			}
5937 			break;
5938 		case 4:
5939 			/* Maramba with 2 XAUI */
5940 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
5941 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
5942 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
5943 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
5944 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
5945 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
5946 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
5947 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
5948 
5949 				/*
5950 				 * Check the first phy port address against
5951 				 * the known phy start addresses to determine
5952 				 * the platform type.
5953 				 */
5954 				switch (phy_fd_arr[0]) {
5955 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
5956 					hw_p->platform_type =
5957 					    P_NEPTUNE_MARAMBA_P0;
5958 					break;
5959 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
5960 					hw_p->platform_type =
5961 					    P_NEPTUNE_MARAMBA_P1;
5962 					break;
5963 				default:
5964 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5965 					    "Unknown port %d...Cannot "
5966 					    "determine platform type", i));
5967 					goto error_exit;
5968 				}
5969 
5970 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
5971 
5972 				hw_p->xcvr_addr[0] = port_fd_arr[0];
5973 				hw_p->xcvr_addr[1] = port_fd_arr[1];
5974 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
5975 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
5976 
5977 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5978 				    "Maramba with 2 XAUI"));
5979 			} else {
5980 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5981 				    "Unsupported neptune type 3"));
5982 				goto error_exit;
5983 			}
5984 			break;
5985 		default:
5986 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5987 			    "Unsupported neptune type 5"));
5988 			goto error_exit;
5989 		}
5990 		break;
5991 	case 1:
5992 		switch (total_phy_fd) {
5993 		case 3:
5994 			/*
5995 			 * TODO 3 1G, 1 10G mode.
5996 			 * Differentiate between 1_1G_1_10G_2_1G and
5997 			 * 1_10G_3_1G
5998 			 */
5999 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6000 			    "Unsupported neptune type 7"));
6001 			goto error_exit;
6002 		case 2:
6003 			/*
6004 			 * TODO 2 1G, 1 10G mode.
6005 			 * Differentiate between 1_1G_1_10G_1_1G and
6006 			 * 1_10G_2_1G
6007 			 */
6008 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6009 			    "Unsupported neptune type 8"));
6010 			goto error_exit;
6011 		case 1:
6012 			/*
6013 			 * TODO 1 1G, 1 10G mode.
6014 			 * Differentiate between 1_1G_1_10G and
6015 			 * 1_10G_1_1G
6016 			 */
6017 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6018 			    "Unsupported neptune type 9"));
6019 			goto error_exit;
6020 		case 0:
6021 			/* 1 10G mode, N2 with 1 XAUI */
6022 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
6023 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
6024 
6025 				/*
6026 				 * Check the first phy port address against
6027 				 * the known phy start addresses to determine
6028 				 * the platform type.
6029 				 */
6030 
6031 				switch (port_fd_arr[0]) {
6032 				case BCM8704_N2_PORT_ADDR_BASE:
6033 				case (BCM8704_N2_PORT_ADDR_BASE + 1):
6034 				case BCM8706_ALT_GOA_PORT1_ADDR:
6035 					if (hw_p->platform_type !=
6036 					    P_NEPTUNE_NIU) {
6037 						hw_p->platform_type =
6038 						    P_NEPTUNE_GENERIC;
6039 						hw_p->niu_type =
6040 						    NEPTUNE_2_10GF;
6041 					}
6042 					break;
6043 				default:
6044 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6045 					    "Unsupported neptune type 10"));
6046 					goto error_exit;
6047 				}
6048 				/*
6049 				 * For GOA, which is a hot swappable PHY, the
6050 				 * phy address to function number mapping
6051 				 * should be preserved, i.e., addr 16 is
6052 				 * assigned to function 0 and 20 to function 1
6053 				 * But for Huron XAUI, the assignment should
6054 				 * be by function number, i.e., whichever
6055 				 * function number attaches should be
6056 				 * assigned the available PHY (this is required
6057 				 * primarily to support pre-production Huron
6058 				 * boards where function 0 is mapped to addr 17
6059 				 */
6060 				if (port_fd_arr[0] ==
6061 				    BCM8706_ALT_GOA_PORT1_ADDR) {
6062 					hw_p->xcvr_addr[1] = port_fd_arr[0];
6063 				} else {
6064 					hw_p->xcvr_addr[nxgep->function_num] =
6065 					    port_fd_arr[0];
6066 				}
6067 			} else {
6068 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6069 				    "Unsupported neptune type 10 - 1"));
6070 				goto error_exit;
6071 			}
6072 			break;
6073 		case 4:
6074 			/* Maramba with 1 XAUI */
6075 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
6076 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
6077 
6078 				/*
6079 				 * Check the first phy port address against
6080 				 * the known phy start addresses to determine
6081 				 * the platform type.
6082 				 */
6083 				switch (phy_fd_arr[0]) {
6084 				case BCM5464_MARAMBA_P0_PORT_ADDR_BASE:
6085 					hw_p->platform_type =
6086 					    P_NEPTUNE_MARAMBA_P0;
6087 					break;
6088 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
6089 					hw_p->platform_type =
6090 					    P_NEPTUNE_MARAMBA_P1;
6091 					break;
6092 				default:
6093 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6094 					    "Unknown port %d...Cannot "
6095 					    "determine platform type 10 - 2",
6096 					    i));
6097 					goto error_exit;
6098 				}
6099 
6100 				/*
6101 				 * Check the BCM8704 address to determine
6102 				 * if XAUI is in port 0 or port 1.
6103 				 */
6104 				switch (port_fd_arr[0]) {
6105 				case BCM8704_MARAMBA_PORT_ADDR_BASE:
6106 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
6107 					hw_p->xcvr_addr[0] = port_fd_arr[0];
6108 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
6109 						hw_p->xcvr_addr[i] =
6110 						    phy_fd_arr[i];
6111 					}
6112 					break;
6113 				case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1):
6114 					hw_p->niu_type =
6115 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
6116 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
6117 					hw_p->xcvr_addr[1] = port_fd_arr[0];
6118 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
6119 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
6120 					break;
6121 				default:
6122 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6123 					    "Unsupported neptune type 11"));
6124 					goto error_exit;
6125 				}
6126 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6127 				    "Maramba with 1 XAUI"));
6128 			} else {
6129 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6130 				    "Unsupported neptune type 12"));
6131 				goto error_exit;
6132 			}
6133 			break;
6134 		default:
6135 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6136 			    "Unsupported neptune type 13"));
6137 			goto error_exit;
6138 		}
6139 		break;
6140 	case 0:
6141 		switch (total_phy_fd) {
6142 		case 4:
6143 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
6144 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
6145 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
6146 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
6147 
6148 				/*
6149 				 * Check the first phy port address against
6150 				 * the known phy start addresses to determine
6151 				 * the platform type.
6152 				 */
6153 				switch (phy_fd_arr[0]) {
6154 				case BCM5464_MARAMBA_P1_PORT_ADDR_BASE:
6155 					hw_p->platform_type =
6156 					    P_NEPTUNE_MARAMBA_P1;
6157 					break;
6158 				case BCM5464_NEPTUNE_PORT_ADDR_BASE:
6159 					hw_p->platform_type =
6160 					    P_NEPTUNE_ATLAS_4PORT;
6161 					break;
6162 				default:
6163 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6164 					    "Unknown port %d...Cannot "
6165 					    "determine platform type", i));
6166 					goto error_exit;
6167 				}
6168 				hw_p->niu_type = NEPTUNE_4_1GC;
6169 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
6170 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
6171 				}
6172 			} else {
6173 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6174 				    "Unsupported neptune type 14"));
6175 				goto error_exit;
6176 			}
6177 			break;
6178 		case 3:
6179 			/* TODO 3 1G mode */
6180 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6181 			    "Unsupported neptune type 15"));
6182 			goto error_exit;
6183 		case 2:
6184 			/* TODO 2 1G mode */
6185 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
6186 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
6187 				hw_p->platform_type = P_NEPTUNE_GENERIC;
6188 				hw_p->niu_type = NEPTUNE_2_1GRF;
6189 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
6190 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
6191 			} else {
6192 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6193 				    "Unsupported neptune type 16"));
6194 				goto error_exit;
6195 			}
6196 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6197 			    "2 RGMII Fiber ports - RTM"));
6198 			break;
6199 
6200 		case 1:
6201 			/* TODO 1 1G mode */
6202 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6203 			    "Unsupported neptune type 17"));
6204 			goto error_exit;
6205 		default:
6206 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6207 			    "Unsupported neptune type 18, total phy fd %d",
6208 			    total_phy_fd));
6209 			goto error_exit;
6210 		}
6211 		break;
6212 	default:
6213 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6214 		    "Unsupported neptune type 19"));
6215 		goto error_exit;
6216 	}
6217 
6218 scan_exit:
6219 
6220 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
6221 	    "niu type [0x%x]\n", hw_p->niu_type));
6222 	return (status);
6223 
6224 error_exit:
6225 	return (NXGE_ERROR);
6226 }
6227 
6228 boolean_t
6229 nxge_is_valid_local_mac(ether_addr_st mac_addr)
6230 {
6231 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
6232 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
6233 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
6234 		return (B_FALSE);
6235 	else
6236 		return (B_TRUE);
6237 }
6238 
6239 static void
6240 nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
6241 
6242 	npi_status_t rs = NPI_SUCCESS;
6243 	uint8_t xcvr_portn;
6244 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6245 
6246 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
6247 
6248 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
6249 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
6250 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
6251 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
6252 	}
6253 	/*
6254 	 * For Altas 4-1G copper, Xcvr port numbers are
6255 	 * swapped with ethernet port number. This is
6256 	 * designed for better signal integrity in routing.
6257 	 */
6258 	switch (portn) {
6259 	case 0:
6260 		xcvr_portn += 3;
6261 		break;
6262 	case 1:
6263 		xcvr_portn += 2;
6264 		break;
6265 	case 2:
6266 		xcvr_portn += 1;
6267 		break;
6268 	case 3:
6269 	default:
6270 		break;
6271 	}
6272 
6273 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
6274 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
6275 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
6276 	if (rs != NPI_SUCCESS) {
6277 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6278 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
6279 		    "returned error 0x[%x]", rs));
6280 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
6281 		return;
6282 	}
6283 
6284 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
6285 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
6286 	if (rs != NPI_SUCCESS) {
6287 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6288 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
6289 		    "returned error 0x[%x]", rs));
6290 	}
6291 
6292 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
6293 }
6294 
6295 static nxge_status_t
6296 nxge_mii_get_link_mode(p_nxge_t nxgep)
6297 {
6298 	p_nxge_stats_t	statsp;
6299 	uint8_t		xcvr_portn;
6300 	p_mii_regs_t	mii_regs;
6301 	mii_mode_control_stat_t	mode;
6302 	int		status = NXGE_OK;
6303 
6304 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
6305 
6306 	statsp = nxgep->statsp;
6307 	xcvr_portn = statsp->mac_stats.xcvr_portn;
6308 	mii_regs = NULL;
6309 	mode.value = 0;
6310 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
6311 #if defined(__i386)
6312 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
6313 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
6314 	    mode.value)) != NXGE_OK) {
6315 		goto fail;
6316 #else
6317 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
6318 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
6319 	    mode.value)) != NXGE_OK) {
6320 		goto fail;
6321 #endif
6322 	}
6323 #if defined(__i386)
6324 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
6325 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
6326 	    &mode.value)) != NXGE_OK) {
6327 		goto fail;
6328 	}
6329 #else
6330 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
6331 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
6332 	    &mode.value)) != NXGE_OK) {
6333 		goto fail;
6334 	}
6335 #endif
6336 
6337 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
6338 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6339 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6340 		    "nxge_mii_get_link_mode: fiber mode"));
6341 	}
6342 
6343 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6344 	    "nxge_mii_get_link_mode: "
6345 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
6346 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
6347 	    mode.value, nxgep->mac.portmode));
6348 
6349 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6350 	    "<== nxge_mii_get_link_mode"));
6351 	return (status);
6352 fail:
6353 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6354 	    "<== nxge_mii_get_link_mode (failed)"));
6355 	return (NXGE_ERROR);
6356 }
6357 
6358 nxge_status_t
6359 nxge_mac_set_framesize(p_nxge_t nxgep)
6360 {
6361 	npi_attr_t		ap;
6362 	uint8_t			portn;
6363 	npi_handle_t		handle;
6364 	npi_status_t		rs = NPI_SUCCESS;
6365 
6366 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
6367 
6368 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6369 	handle = nxgep->npi_handle;
6370 
6371 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6372 	    "==> nxge_mac_sec_framesize: port<%d> "
6373 	    "min framesize %d max framesize %d ",
6374 	    portn,
6375 	    nxgep->mac.minframesize,
6376 	    nxgep->mac.maxframesize));
6377 
6378 	SET_MAC_ATTR2(handle, ap, portn,
6379 	    MAC_PORT_FRAME_SIZE,
6380 	    nxgep->mac.minframesize,
6381 	    nxgep->mac.maxframesize,
6382 	    rs);
6383 	if (rs != NPI_SUCCESS) {
6384 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6385 		    "<== nxge_mac_set_framesize: failed to configure "
6386 		    "max/min frame size port %d", portn));
6387 
6388 		return (NXGE_ERROR | rs);
6389 	}
6390 
6391 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6392 	    "<== nxge_mac_set_framesize: port<%d>", portn));
6393 
6394 	return (NXGE_OK);
6395 }
6396 
6397 #ifdef NXGE_DEBUG
6398 static void
6399 nxge_mii_dump(p_nxge_t nxgep)
6400 {
6401 	p_nxge_stats_t	statsp;
6402 	uint8_t		xcvr_portn;
6403 	p_mii_regs_t	mii_regs;
6404 	mii_bmcr_t	bmcr;
6405 	mii_bmsr_t	bmsr;
6406 	mii_idr1_t	idr1;
6407 	mii_idr2_t	idr2;
6408 	mii_mode_control_stat_t	mode;
6409 	p_nxge_param_t	param_arr;
6410 
6411 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
6412 
6413 	statsp = nxgep->statsp;
6414 	xcvr_portn = statsp->mac_stats.xcvr_portn;
6415 
6416 	mii_regs = NULL;
6417 
6418 #if defined(__i386)
6419 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
6420 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
6421 #else
6422 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
6423 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
6424 #endif
6425 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6426 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
6427 	    xcvr_portn, bmcr.value));
6428 
6429 #if defined(__i386)
6430 	(void) nxge_mii_read(nxgep,
6431 	    nxgep->statsp->mac_stats.xcvr_portn,
6432 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
6433 #else
6434 	(void) nxge_mii_read(nxgep,
6435 	    nxgep->statsp->mac_stats.xcvr_portn,
6436 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
6437 #endif
6438 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6439 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
6440 	    xcvr_portn, bmsr.value));
6441 
6442 #if defined(__i386)
6443 	(void) nxge_mii_read(nxgep,
6444 	    nxgep->statsp->mac_stats.xcvr_portn,
6445 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
6446 #else
6447 	(void) nxge_mii_read(nxgep,
6448 	    nxgep->statsp->mac_stats.xcvr_portn,
6449 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
6450 #endif
6451 
6452 
6453 #if defined(__i386)
6454 	(void) nxge_mii_read(nxgep,
6455 	    nxgep->statsp->mac_stats.xcvr_portn,
6456 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
6457 #else
6458 	(void) nxge_mii_read(nxgep,
6459 	    nxgep->statsp->mac_stats.xcvr_portn,
6460 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
6461 #endif
6462 
6463 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6464 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
6465 	    xcvr_portn, idr1.value));
6466 
6467 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6468 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
6469 	    xcvr_portn, idr2.value));
6470 
6471 	mode.value = 0;
6472 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
6473 
6474 #if defined(__i386)
6475 	(void) nxge_mii_write(nxgep, xcvr_portn,
6476 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
6477 
6478 	(void) nxge_mii_read(nxgep, xcvr_portn,
6479 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
6480 #else
6481 	(void) nxge_mii_write(nxgep, xcvr_portn,
6482 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
6483 
6484 	(void) nxge_mii_read(nxgep, xcvr_portn,
6485 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
6486 #endif
6487 
6488 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6489 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
6490 	    xcvr_portn, mode.value));
6491 }
6492 #endif
6493