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