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