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