xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/nxge/nxge_impl.h>
26 #include <sys/nxge/nxge_mac.h>
27 #include <sys/nxge/nxge_hio.h>
28 
29 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
30 #define	LM_WAIT_MULTIPLIER	8
31 
32 #define	SERDES_RDY_WT_INTERVAL	50
33 #define	MAX_SERDES_RDY_RETRIES	10
34 
35 #define	TN1010_SPEED_1G		1
36 #define	TN1010_SPEED_10G	0
37 #define	TN1010_AN_IN_PROG	0	/* Auto negotiation in progress */
38 #define	TN1010_AN_COMPLETE	1
39 #define	TN1010_AN_RSVD		2
40 #define	TN1010_AN_FAILED	3
41 
42 extern uint32_t nxge_no_link_notify;
43 extern boolean_t nxge_no_msg;
44 extern uint32_t nxge_lb_dbg;
45 extern uint32_t nxge_jumbo_mtu;
46 
47 typedef enum {
48 	CHECK_LINK_RESCHEDULE,
49 	CHECK_LINK_STOP
50 } check_link_state_t;
51 
52 static check_link_state_t nxge_check_link_stop(nxge_t *);
53 
54 /*
55  * Ethernet broadcast address definition.
56  */
57 static ether_addr_st etherbroadcastaddr =
58 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
59 /*
60  * Ethernet zero address definition.
61  */
62 static ether_addr_st etherzeroaddr =
63 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
64 /*
65  * Supported chip types
66  */
67 static uint32_t nxge_supported_cl45_ids[] = {
68 	BCM8704_DEV_ID,
69 	MARVELL_88X_201X_DEV_ID,
70 	BCM8706_DEV_ID,
71 	TN1010_DEV_ID
72 };
73 
74 static uint32_t nxge_supported_cl22_ids[] = {
75     BCM5464R_PHY_ID,
76     BCM5482_PHY_ID
77 };
78 
79 #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
80 				sizeof (uint32_t))
81 #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
82 				sizeof (uint32_t))
83 /*
84  * static functions
85  */
86 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
87 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
88 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
89 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
90 static boolean_t nxge_hswap_phy_present(p_nxge_t, uint8_t);
91 static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
92 static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
93 static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t);
94 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
95 static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
96 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
97 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
98 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
99 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
100 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
101 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
102 static nxge_status_t nxge_check_mii_link(p_nxge_t);
103 static nxge_status_t nxge_check_10g_link(p_nxge_t);
104 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
105 static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
106 static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
107 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
108 static void nxge_bcm5464_link_led_off(p_nxge_t);
109 static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
110 static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
111 static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *);
112 static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t);
113 static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t,
114 	    uint8_t *);
115 static boolean_t nxge_is_nlp2020_phy(p_nxge_t);
116 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t);
117 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t);
118 static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
119 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
120 static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
121 static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
122 static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
123 	nxge_link_state_t *link_up);
124 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
125 static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
126 
127 nxge_status_t nxge_mac_init(p_nxge_t);
128 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
129 
130 #ifdef NXGE_DEBUG
131 static void nxge_mii_dump(p_nxge_t);
132 static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
133 static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
134 #endif
135 
136 /*
137  * xcvr tables for supported transceivers
138  */
139 
140 /*
141  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
142  * The Teranetics TN1010 based copper XAUI card can also be used
143  * on N2-NIU systems in 10G mode, but it uses its own table
144  * nxge_n2_10G_tn1010_table below.
145  */
146 static nxge_xcvr_table_t nxge_n2_10G_table = {
147 	nxge_n2_serdes_init,
148 	nxge_10G_xcvr_init,
149 	nxge_10G_link_intr_stop,
150 	nxge_10G_link_intr_start,
151 	nxge_check_10g_link,
152 	PCS_XCVR
153 };
154 
155 /*
156  * For the Teranetics TN1010 based copper XAUI card
157  */
158 static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
159 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
160 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
161 	nxge_10G_link_intr_stop,
162 	nxge_10G_link_intr_start,
163 	nxge_check_tn1010_link,		/* Will figure out speed */
164 	XPCS_XCVR
165 };
166 
167 static nxge_xcvr_table_t nxge_n2_1G_table = {
168 	nxge_n2_serdes_init,
169 	nxge_1G_xcvr_init,
170 	nxge_1G_fiber_link_intr_stop,
171 	nxge_1G_fiber_link_intr_start,
172 	nxge_check_mii_link,
173 	PCS_XCVR
174 };
175 
176 static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
177 	nxge_n2_serdes_init,
178 	nxge_tn1010_xcvr_init,
179 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
180 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
181 	nxge_check_tn1010_link,
182 	PCS_XCVR
183 };
184 
185 static nxge_xcvr_table_t nxge_10G_tn1010_table = {
186 	nxge_neptune_10G_serdes_init,
187 	nxge_tn1010_xcvr_init,
188 	nxge_10G_link_intr_stop,
189 	nxge_10G_link_intr_start,
190 	nxge_check_tn1010_link,
191 	XPCS_XCVR
192 };
193 
194 static nxge_xcvr_table_t nxge_1G_tn1010_table = {
195 	nxge_1G_serdes_init,
196 	nxge_tn1010_xcvr_init,
197 	nxge_1G_fiber_link_intr_stop,
198 	nxge_1G_fiber_link_intr_start,
199 	nxge_check_tn1010_link,
200 	PCS_XCVR
201 };
202 
203 static nxge_xcvr_table_t nxge_10G_fiber_table = {
204 	nxge_neptune_10G_serdes_init,
205 	nxge_10G_xcvr_init,
206 	nxge_10G_link_intr_stop,
207 	nxge_10G_link_intr_start,
208 	nxge_check_10g_link,
209 	PCS_XCVR
210 };
211 
212 static nxge_xcvr_table_t nxge_1G_copper_table = {
213 	NULL,
214 	nxge_1G_xcvr_init,
215 	nxge_1G_copper_link_intr_stop,
216 	nxge_1G_copper_link_intr_start,
217 	nxge_check_mii_link,
218 	INT_MII_XCVR
219 };
220 
221 /* This table is for Neptune portmode == PORT_1G_SERDES cases */
222 static nxge_xcvr_table_t nxge_1G_fiber_table = {
223 	nxge_1G_serdes_init,
224 	nxge_1G_xcvr_init,
225 	nxge_1G_fiber_link_intr_stop,
226 	nxge_1G_fiber_link_intr_start,
227 	nxge_check_mii_link,
228 	PCS_XCVR
229 };
230 
231 static nxge_xcvr_table_t nxge_10G_copper_table = {
232 	nxge_neptune_10G_serdes_init,
233 	NULL,
234 	NULL,
235 	NULL,
236 	NULL,
237 	PCS_XCVR
238 };
239 
240 /*
241  * NXGE_PORT_TN1010 is defined as,
242  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
243  *	= 0 | 5 << 16 = 0x50000
244  *
245  * So NEPTUNE_2_TN1010 =
246  *      (NXGE_PORT_TN1010 |
247  *      (NXGE_PORT_TN1010 << 4) |
248  *      (NXGE_PORT_NONE << 8) |
249  *      (NXGE_PORT_NONE << 12)),
250  *      = 0x50000 | (0x50000 << 4)
251  *	= 0x550000
252  *
253  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
254  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
255  * = 0x50000
256  */
257 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
258 {
259 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
260 
261 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
262 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
263 		return (B_TRUE);
264 	} else {
265 		return (B_FALSE);
266 	}
267 }
268 
269 
270 /*
271  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
272  * serial EEPROM or VPD if possible.  Note that not all systems could get
273  * the portmode information by calling this function.  For example, the
274  * Maramba system figures out the portmode information by calling function
275  * nxge_setup_xcvr_table.
276  */
277 nxge_status_t
278 nxge_get_xcvr_type(p_nxge_t nxgep)
279 {
280 	nxge_status_t status = NXGE_OK;
281 	char *phy_type;
282 	char *prop_val;
283 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
284 	uint32_t	val;
285 	npi_status_t	rs;
286 
287 	/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
288 	if (nxgep->mac.portmode == PORT_10G_SERDES &&
289 	    nxgep->statsp->mac_stats.link_up) {
290 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
291 		return (status);
292 	}
293 
294 	nxgep->mac.portmode = 0;
295 	nxgep->xcvr_addr = 0;
296 
297 	/*
298 	 * First check for hot swappable phy property.
299 	 */
300 	if (nxgep->hot_swappable_phy == B_TRUE) {
301 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
302 		nxgep->mac.portmode = PORT_HSP_MODE;
303 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
304 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
305 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
306 	    "hot-swappable-phy") == 1) {
307 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
308 		nxgep->mac.portmode = PORT_HSP_MODE;
309 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
310 	} else if (nxgep->niu_type == N2_NIU &&
311 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
312 	    "hot-swappable-phy") == 1) {
313 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
314 		nxgep->mac.portmode = PORT_HSP_MODE;
315 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
316 	}
317 
318 	/*
319 	 * MDIO polling support for Monza RTM card, Goa NEM card
320 	 */
321 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
322 		nxgep->hot_swappable_phy = B_TRUE;
323 		if (portn > 1) {
324 			return (NXGE_ERROR);
325 		}
326 
327 		if (nxge_hswap_phy_present(nxgep, portn))
328 			goto found_phy;
329 
330 		nxgep->phy_absent = B_TRUE;
331 
332 		/* Check Serdes link to detect Opus NEM */
333 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
334 		    XPCS_REG_STATUS, &val);
335 
336 		if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
337 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
338 			nxgep->mac.portmode = PORT_10G_SERDES;
339 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
340 			    "HSP 10G Serdes FOUND!!"));
341 		}
342 		goto check_phy_done;
343 found_phy:
344 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
345 		nxgep->mac.portmode = PORT_10G_FIBER;
346 		nxgep->phy_absent = B_FALSE;
347 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
348 		    "found for hot swappable phy"));
349 check_phy_done:
350 		return (status);
351 	}
352 
353 	/* Get phy-type property (May have been set by nxge.conf) */
354 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
355 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
356 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
357 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
358 		    "found  conf file: phy-type %s", prop_val));
359 		if (strcmp("xgsd", prop_val) == 0) {
360 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
361 			nxgep->mac.portmode = PORT_10G_SERDES;
362 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
363 			    "found: 10G Serdes"));
364 		} else if (strcmp("gsd", prop_val) == 0) {
365 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
366 			nxgep->mac.portmode = PORT_1G_SERDES;
367 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
368 		} else if (strcmp("mif", prop_val) == 0) {
369 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
370 			nxgep->mac.portmode = PORT_1G_COPPER;
371 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
372 		} else if (strcmp("pcs", prop_val) == 0) {
373 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
374 			nxgep->mac.portmode = PORT_1G_FIBER;
375 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
376 		} else if (strcmp("xgf", prop_val) == 0) {
377 			/*
378 			 * Before OBP supports new phy-type property
379 			 * value "xgc", the 10G copper XAUI may carry
380 			 * "xgf" instead of "xgc". If the OBP is
381 			 * upgraded to a newer version which supports
382 			 * "xgc", then the TN1010 related code in this
383 			 * "xgf" case will not be used anymore.
384 			 */
385 			if (nxge_is_tn1010_phy(nxgep)) {
386 				if ((status = nxge_set_tn1010_param(nxgep))
387 				    != NXGE_OK) {
388 					return (status);
389 				}
390 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
391 			} else {  /* For Fiber XAUI */
392 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
393 				nxgep->mac.portmode = PORT_10G_FIBER;
394 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
395 				    "10G Fiber Xcvr"));
396 			}
397 		} else if (strcmp("xgc", prop_val) == 0) {
398 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
399 				return (status);
400 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
401 		}
402 
403 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
404 		    "phy-type", prop_val);
405 		ddi_prop_free(prop_val);
406 
407 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
408 		    "Got phy type [0x%x] from conf file",
409 		    nxgep->mac.portmode));
410 
411 		return (NXGE_OK);
412 	}
413 
414 	/* Get phy-type property from OBP */
415 	if (nxgep->niu_type == N2_NIU) {
416 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
417 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
418 			if (strcmp("xgf", prop_val) == 0) {
419 				/*
420 				 * Before OBP supports new phy-type property
421 				 * value "xgc", the 10G copper XAUI may carry
422 				 * "xgf" instead of "xgc". If the OBP is
423 				 * upgraded to a newer version which supports
424 				 * "xgc", then the TN1010 related code in this
425 				 * "xgf" case will not be used anymore.
426 				 */
427 				if (nxge_is_tn1010_phy(nxgep)) {
428 					if ((status =
429 					    nxge_set_tn1010_param(nxgep))
430 					    != NXGE_OK) {
431 						return (status);
432 					}
433 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
434 					    "TN1010 Xcvr"));
435 				} else if (nxge_is_nlp2020_phy(nxgep)) {
436 					if ((status =
437 					    nxge_set_nlp2020_param(nxgep))
438 					    != NXGE_OK) {
439 						return (status);
440 					}
441 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
442 					    "NLP2020 Xcvr"));
443 				} else { /* For Fiber XAUI */
444 					nxgep->statsp->mac_stats.xcvr_inuse
445 					    = XPCS_XCVR;
446 					nxgep->mac.portmode = PORT_10G_FIBER;
447 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
448 					    "10G Fiber Xcvr"));
449 				}
450 			} else if (strcmp("mif", prop_val) == 0) {
451 				nxgep->statsp->mac_stats.xcvr_inuse =
452 				    INT_MII_XCVR;
453 				nxgep->mac.portmode = PORT_1G_COPPER;
454 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
455 				    "1G Copper Xcvr"));
456 			} else if (strcmp("pcs", prop_val) == 0) {
457 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
458 				nxgep->mac.portmode = PORT_1G_FIBER;
459 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
460 				    "1G Fiber Xcvr"));
461 			} else if (strcmp("xgc", prop_val) == 0) {
462 				status = nxge_set_tn1010_param(nxgep);
463 				if (status != NXGE_OK)
464 					return (status);
465 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
466 			} else if (strcmp("xgsd", prop_val) == 0) {
467 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
468 				nxgep->mac.portmode = PORT_10G_SERDES;
469 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
470 				    "OBP: 10G Serdes"));
471 			} else if (strcmp("gsd", prop_val) == 0) {
472 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
473 				nxgep->mac.portmode = PORT_1G_SERDES;
474 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
475 				    "OBP: 1G Serdes"));
476 			} else {
477 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
478 				    "Unknown phy-type: %s", prop_val));
479 				ddi_prop_free(prop_val);
480 				return (NXGE_ERROR);
481 			}
482 			status = NXGE_OK;
483 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
484 			    nxgep->dip, "phy-type", prop_val);
485 			ddi_prop_free(prop_val);
486 
487 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
488 			    "Got phy type [0x%x] from OBP",
489 			    nxgep->mac.portmode));
490 
491 			return (status);
492 		} else {
493 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
494 			    "Exiting...phy-type property not found"));
495 			return (NXGE_ERROR);
496 		}
497 	}
498 
499 
500 	if (!nxgep->vpd_info.present) {
501 		return (NXGE_OK);
502 	}
503 
504 	if (!nxgep->vpd_info.ver_valid) {
505 		goto read_seeprom;
506 	}
507 
508 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
509 	    "Reading phy type from expansion ROM"));
510 	/*
511 	 * Try to read the phy type from the vpd data read off the
512 	 * expansion ROM.
513 	 */
514 	phy_type = nxgep->vpd_info.phy_type;
515 
516 	if (strncmp(phy_type, "mif", 3) == 0) {
517 		nxgep->mac.portmode = PORT_1G_COPPER;
518 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
519 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
520 		nxgep->mac.portmode = PORT_10G_FIBER;
521 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
522 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
523 		nxgep->mac.portmode = PORT_1G_FIBER;
524 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
525 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
526 		status = nxge_set_tn1010_param(nxgep);
527 		if (status != NXGE_OK) {
528 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
529 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
530 			goto read_seeprom;
531 		}
532 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
533 		nxgep->mac.portmode = PORT_10G_SERDES;
534 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
535 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
536 		nxgep->mac.portmode = PORT_1G_SERDES;
537 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
538 	} else {
539 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
540 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
541 		    phy_type[0], phy_type[1], phy_type[2]));
542 		goto read_seeprom;
543 	}
544 
545 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
546 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
547 
548 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
549 	return (status);
550 
551 read_seeprom:
552 	/*
553 	 * read the phy type from the SEEPROM - NCR registers
554 	 */
555 	status = nxge_espc_phy_type_get(nxgep);
556 	if (status != NXGE_OK) {
557 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
558 		    "Failed to get phy type"));
559 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
560 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
561 	}
562 
563 	return (status);
564 
565 }
566 
567 /* Set up the PHY specific values. */
568 
569 nxge_status_t
570 nxge_setup_xcvr_table(p_nxge_t nxgep)
571 {
572 	nxge_status_t	status = NXGE_OK;
573 	uint32_t	port_type;
574 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
575 	uint32_t	pcs_id = 0;
576 	uint32_t	pma_pmd_id = 0;
577 	uint32_t	phy_id = 0;
578 	uint16_t	chip_id = 0;
579 
580 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
581 	    portn));
582 
583 	switch (nxgep->niu_type) {
584 	case N2_NIU:
585 		switch (nxgep->mac.portmode) {
586 		case PORT_1G_FIBER:
587 		case PORT_1G_SERDES:
588 			nxgep->xcvr = nxge_n2_1G_table;
589 			nxgep->xcvr_addr = portn;
590 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
591 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
592 			    "Serdes"));
593 			break;
594 		case PORT_10G_FIBER:
595 		case PORT_10G_COPPER:
596 		case PORT_10G_SERDES:
597 			nxgep->xcvr = nxge_n2_10G_table;
598 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
599 				nxgep->xcvr_addr =
600 				    nxgep->nxge_hw_p->xcvr_addr[portn];
601 			}
602 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
603 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
604 			    ((nxgep->mac.portmode == PORT_10G_COPPER) ?
605 			    "Copper" : "Serdes")));
606 			break;
607 		case PORT_1G_TN1010:
608 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
609 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
610 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
611 			    "TN1010 Copper Xcvr in 1G"));
612 			break;
613 		case PORT_10G_TN1010:
614 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
615 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
616 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
617 			    "TN1010 Copper Xcvr in 10G"));
618 			break;
619 		case PORT_HSP_MODE:
620 			nxgep->xcvr = nxge_n2_10G_table;
621 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
622 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
623 			    "Swappable Xcvr (not present)"));
624 			break;
625 		default:
626 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
627 			    "<== nxge_setup_xcvr_table: "
628 			    "Unable to determine NIU portmode"));
629 			return (NXGE_ERROR);
630 		}
631 		break;
632 	default:
633 		if (nxgep->mac.portmode == 0) {
634 			/*
635 			 * Would be the case for platforms like Maramba
636 			 * in which the phy type could not be got from conf
637 			 * file, OBP, VPD or Serial PROM.
638 			 */
639 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
640 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
641 				    "<== nxge_setup_xcvr_table:"
642 				    " Invalid Neptune type [0x%x]",
643 				    nxgep->niu_type));
644 				return (NXGE_ERROR);
645 			}
646 
647 			port_type = nxgep->niu_type >>
648 			    (NXGE_PORT_TYPE_SHIFT * portn);
649 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
650 
651 			switch (port_type) {
652 
653 			case NXGE_PORT_1G_COPPER:
654 				nxgep->mac.portmode = PORT_1G_COPPER;
655 				break;
656 			case NXGE_PORT_10G_COPPER:
657 				nxgep->mac.portmode = PORT_10G_COPPER;
658 				break;
659 			case NXGE_PORT_1G_FIBRE:
660 				nxgep->mac.portmode = PORT_1G_FIBER;
661 				break;
662 			case NXGE_PORT_10G_FIBRE:
663 				nxgep->mac.portmode = PORT_10G_FIBER;
664 				break;
665 			case NXGE_PORT_1G_SERDES:
666 				nxgep->mac.portmode = PORT_1G_SERDES;
667 				break;
668 			case NXGE_PORT_10G_SERDES:
669 				nxgep->mac.portmode = PORT_10G_SERDES;
670 				break;
671 			/* Ports 2 and 3 of Alonso or ARTM */
672 			case NXGE_PORT_1G_RGMII_FIBER:
673 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
674 				break;
675 			case NXGE_PORT_TN1010:
676 				/*
677 				 * If this port uses the TN1010 copper
678 				 * PHY, then its speed is not known yet
679 				 * because nxge_scan_ports_phy could only
680 				 * figure out the vendor of the PHY but
681 				 * not its speed. nxge_set_tn1010_param
682 				 * will read the PHY speed and set
683 				 * portmode accordingly.
684 				 */
685 				if ((status = nxge_set_tn1010_param(nxgep))
686 				    != NXGE_OK) {
687 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
688 					    "nxge_set_tn1010_param failed"));
689 					return (status);
690 				}
691 				break;
692 			default:
693 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
694 				    "<== nxge_setup_xcvr_table: "
695 				    "Unknown port-type: 0x%x", port_type));
696 				return (NXGE_ERROR);
697 			}
698 		}
699 
700 		/*
701 		 * Above switch has figured out nxge->mac.portmode, now set
702 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
703 		 * to portmode.
704 		 */
705 		switch (nxgep->mac.portmode) {
706 		case PORT_1G_COPPER:
707 		case PORT_1G_RGMII_FIBER:
708 			nxgep->xcvr = nxge_1G_copper_table;
709 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
710 			/*
711 			 * For Altas 4-1G copper, Xcvr port numbers are
712 			 * swapped with ethernet port number. This is
713 			 * designed for better signal integrity in
714 			 * routing. This is also the case for the
715 			 * on-board Neptune copper ports on the Maramba
716 			 * platform.
717 			 */
718 			switch (nxgep->platform_type) {
719 			case P_NEPTUNE_ATLAS_4PORT:
720 			case P_NEPTUNE_MARAMBA_P0:
721 			case P_NEPTUNE_MARAMBA_P1:
722 				switch (portn) {
723 				case 0:
724 					nxgep->xcvr_addr += 3;
725 					break;
726 				case 1:
727 					nxgep->xcvr_addr += 1;
728 					break;
729 				case 2:
730 					nxgep->xcvr_addr -= 1;
731 					break;
732 				case 3:
733 					nxgep->xcvr_addr -= 3;
734 					break;
735 				default:
736 					return (NXGE_ERROR);
737 				}
738 				break;
739 			default:
740 				break;
741 			}
742 
743 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
744 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
745 			    "Copper" : "RGMII Fiber"));
746 			break;
747 
748 		case PORT_10G_COPPER:
749 			nxgep->xcvr = nxge_10G_copper_table;
750 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
751 			break;
752 
753 		case PORT_1G_TN1010:
754 			nxgep->xcvr = nxge_1G_tn1010_table;
755 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
756 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
757 			    "1G TN1010 copper Xcvr"));
758 			break;
759 
760 		case PORT_10G_TN1010:
761 			nxgep->xcvr = nxge_10G_tn1010_table;
762 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
763 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
764 			    "10G TN1010 copper Xcvr"));
765 			break;
766 
767 		case PORT_1G_FIBER:
768 		case PORT_1G_SERDES:
769 			nxgep->xcvr = nxge_1G_fiber_table;
770 			nxgep->xcvr_addr = portn;
771 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
772 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
773 			    "Fiber" : "Serdes"));
774 			break;
775 		case PORT_10G_FIBER:
776 		case PORT_10G_SERDES:
777 			nxgep->xcvr = nxge_10G_fiber_table;
778 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
779 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
780 			    "nxgep->xcvr_addr = [%d]",
781 			    nxgep->nxge_hw_p->xcvr_addr[portn],
782 			    nxgep->xcvr_addr));
783 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
784 				nxgep->xcvr_addr =
785 				    nxgep->nxge_hw_p->xcvr_addr[portn];
786 			}
787 			switch (nxgep->platform_type) {
788 			case P_NEPTUNE_MARAMBA_P0:
789 			case P_NEPTUNE_MARAMBA_P1:
790 				/*
791 				 * Switch off LED for corresponding copper
792 				 * port
793 				 */
794 				nxge_bcm5464_link_led_off(nxgep);
795 				break;
796 			default:
797 				break;
798 			}
799 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
800 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
801 			    "Fiber" : "Serdes"));
802 			break;
803 
804 		case PORT_HSP_MODE:
805 			nxgep->xcvr = nxge_10G_fiber_table;
806 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
807 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
808 			    "Swappable Xcvr (not present)"));
809 			break;
810 		default:
811 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
812 			    "Unknown port-type: 0x%x", port_type));
813 			return (NXGE_ERROR);
814 		}
815 	}
816 
817 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
818 	    nxgep->mac.portmode == PORT_10G_COPPER) {
819 		uint32_t pma_pmd_id;
820 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
821 		    nxgep->xcvr_addr);
822 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
823 			chip_id = MRVL88X201X_CHIP_ID;
824 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
825 			    "nxge_setup_xcvr_table: "
826 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
827 		} else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) ==
828 		    NLP2020_DEV_ID) {
829 			chip_id = NLP2020_CHIP_ID;
830 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
831 			    "nxge_setup_xcvr_table: "
832 			    "Chip ID  AEL2020 [0x%x] for 10G xcvr", chip_id));
833 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
834 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
835 		    &chip_id)) == NXGE_OK) {
836 
837 			switch (chip_id) {
838 			case BCM8704_CHIP_ID:
839 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
840 				    "nxge_setup_xcvr_table: "
841 				    "Chip ID 8704 [0x%x] for 10G xcvr",
842 				    chip_id));
843 				break;
844 			case BCM8706_CHIP_ID:
845 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
846 				    "nxge_setup_xcvr_table: "
847 				    "Chip ID 8706 [0x%x] for 10G xcvr",
848 				    chip_id));
849 				break;
850 			default:
851 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
852 				    "nxge_setup_xcvr_table: "
853 				    "Unknown Chip ID [0x%x] for 10G xcvr",
854 				    chip_id));
855 				break;
856 			}
857 		}
858 	}
859 
860 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
861 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
862 	nxgep->chip_id = chip_id;
863 
864 	/*
865 	 * Get the actual device ID value returned by MDIO read.
866 	 */
867 	nxgep->statsp->mac_stats.xcvr_id = 0;
868 
869 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
870 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
871 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
872 	} else {
873 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
874 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
875 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
876 		} else {
877 			phy_id = nxge_get_cl22_phy_id(nxgep,
878 			    nxgep->xcvr_addr);
879 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
880 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
881 			}
882 		}
883 	}
884 
885 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
886 
887 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
888 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
889 	    nxgep->platform_type, nxgep->xcvr_addr));
890 
891 	return (status);
892 }
893 
894 /* Initialize the entire MAC and physical layer */
895 
896 nxge_status_t
897 nxge_mac_init(p_nxge_t nxgep)
898 {
899 	uint8_t			portn;
900 	nxge_status_t		status = NXGE_OK;
901 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
902 
903 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
904 
905 	nxgep->mac.portnum = portn;
906 	nxgep->mac.porttype = PORT_TYPE_XMAC;
907 
908 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
909 		nxgep->mac.porttype = PORT_TYPE_BMAC;
910 
911 
912 	/* Initialize XIF to configure a network mode */
913 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
914 		goto fail;
915 	}
916 
917 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
918 		goto fail;
919 	}
920 
921 	/* Initialize TX and RX MACs */
922 	/*
923 	 * Always perform XIF init first, before TX and RX MAC init
924 	 */
925 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
926 		goto fail;
927 
928 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
929 		goto fail;
930 
931 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
932 		goto fail;
933 
934 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
935 		goto fail;
936 
937 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
938 		goto fail;
939 
940 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
941 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
942 			goto fail;
943 	}
944 
945 	/* Initialize MAC control configuration */
946 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
947 		goto fail;
948 	}
949 
950 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
951 
952 	/* The Neptune Serdes needs to be reinitialized again */
953 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
954 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
955 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
956 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
957 	    ((portn == 0) || (portn == 1))) {
958 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
959 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
960 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
961 			goto fail;
962 		}
963 	}
964 
965 
966 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
967 
968 	return (NXGE_OK);
969 fail:
970 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
971 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
972 	return (status);
973 }
974 
975 /* Initialize the Ethernet Link */
976 
977 nxge_status_t
978 nxge_link_init(p_nxge_t nxgep)
979 {
980 	nxge_status_t		status = NXGE_OK;
981 	nxge_port_mode_t	portmode;
982 #ifdef	NXGE_DEBUG
983 	uint8_t			portn;
984 
985 	portn = nxgep->mac.portnum;
986 
987 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
988 #endif
989 	/* For Opus NEM, Serdes always needs to be initialized */
990 
991 	portmode = nxgep->mac.portmode;
992 
993 	/*
994 	 * Workaround to get link up in both NIU ports. Some portmodes require
995 	 * that the xcvr be initialized twice, the first time before calling
996 	 * nxge_serdes_init.
997 	 */
998 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
999 	    (portmode != PORT_10G_TN1010) &&
1000 	    (portmode != PORT_1G_TN1010) &&
1001 	    (portmode != PORT_1G_SERDES)) {
1002 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
1003 			goto fail;
1004 		}
1005 	}
1006 
1007 	NXGE_DELAY(200000);
1008 	/* Initialize internal serdes */
1009 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
1010 		goto fail;
1011 	NXGE_DELAY(200000);
1012 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
1013 		goto fail;
1014 
1015 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
1016 
1017 	return (NXGE_OK);
1018 
1019 fail:
1020 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
1021 	    "failed to initialize Ethernet link on port<%d>", portn));
1022 
1023 	return (status);
1024 }
1025 
1026 
1027 /* Initialize the XIF sub-block within the MAC */
1028 
1029 nxge_status_t
1030 nxge_xif_init(p_nxge_t nxgep)
1031 {
1032 	uint32_t		xif_cfg = 0;
1033 	npi_attr_t		ap;
1034 	uint8_t			portn;
1035 	nxge_port_t		portt;
1036 	nxge_port_mode_t	portmode;
1037 	p_nxge_stats_t		statsp;
1038 	npi_status_t		rs = NPI_SUCCESS;
1039 	npi_handle_t		handle;
1040 
1041 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1042 
1043 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
1044 
1045 	handle = nxgep->npi_handle;
1046 	portmode = nxgep->mac.portmode;
1047 	portt = nxgep->mac.porttype;
1048 	statsp = nxgep->statsp;
1049 
1050 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1051 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
1052 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
1053 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1054 	    ((portn == 0) || (portn == 1))) {
1055 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1056 		    "nxge_xcvr_init: set ATCA mode"));
1057 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1058 	}
1059 
1060 	if (portt == PORT_TYPE_XMAC) {
1061 
1062 		/* Setup XIF Configuration for XMAC */
1063 
1064 		if ((portmode == PORT_10G_FIBER) ||
1065 		    (portmode == PORT_10G_COPPER) ||
1066 		    (portmode == PORT_10G_TN1010) ||
1067 		    (portmode == PORT_HSP_MODE) ||
1068 		    (portmode == PORT_10G_SERDES))
1069 			xif_cfg |= CFG_XMAC_XIF_LFS;
1070 
1071 		/* Bypass PCS so that RGMII will be used */
1072 		if (portmode == PORT_1G_COPPER) {
1073 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
1074 		}
1075 
1076 		/* Set MAC Internal Loopback if necessary */
1077 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
1078 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
1079 
1080 		if (statsp->mac_stats.link_speed == 100)
1081 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
1082 
1083 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
1084 
1085 		if ((portmode == PORT_10G_FIBER) ||
1086 		    (portmode == PORT_10G_COPPER) ||
1087 		    (portmode == PORT_10G_TN1010) ||
1088 		    (portmode == PORT_1G_TN1010) ||
1089 		    (portmode == PORT_HSP_MODE) ||
1090 		    (portmode == PORT_10G_SERDES)) {
1091 			/* Assume LED same for 1G and 10G */
1092 			if (statsp->mac_stats.link_up) {
1093 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
1094 			} else {
1095 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
1096 			}
1097 		}
1098 
1099 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
1100 		if (rs != NPI_SUCCESS)
1101 			goto fail;
1102 
1103 		nxgep->mac.xif_config = xif_cfg;
1104 
1105 		/* Set Port Mode */
1106 		if ((portmode == PORT_10G_FIBER) ||
1107 		    (portmode == PORT_10G_COPPER) ||
1108 		    (portmode == PORT_10G_TN1010) ||
1109 		    (portmode == PORT_HSP_MODE) ||
1110 		    (portmode == PORT_10G_SERDES)) {
1111 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1112 			    MAC_XGMII_MODE, rs);
1113 			if (rs != NPI_SUCCESS)
1114 				goto fail;
1115 			if (statsp->mac_stats.link_up) {
1116 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
1117 					goto fail;
1118 			} else {
1119 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1120 					goto fail;
1121 			}
1122 		} else if ((portmode == PORT_1G_FIBER) ||
1123 		    (portmode == PORT_1G_COPPER) ||
1124 		    (portmode == PORT_1G_SERDES) ||
1125 		    (portmode == PORT_1G_TN1010) ||
1126 		    (portmode == PORT_1G_RGMII_FIBER)) {
1127 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1128 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1129 			    portn, portmode, statsp->mac_stats.link_speed));
1130 			if (statsp->mac_stats.link_speed == 1000) {
1131 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1132 				    MAC_GMII_MODE, rs);
1133 			} else {
1134 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
1135 				    MAC_MII_MODE, rs);
1136 			}
1137 			if (rs != NPI_SUCCESS)
1138 				goto fail;
1139 		} else {
1140 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1141 			    "nxge_xif_init: Unknown port mode (%d)"
1142 			    " for port<%d>", portmode, portn));
1143 			goto fail;
1144 		}
1145 
1146 		/* Enable ATCA mode */
1147 
1148 	} else if (portt == PORT_TYPE_BMAC) {
1149 
1150 		/* Setup XIF Configuration for BMAC */
1151 
1152 		if ((portmode == PORT_1G_COPPER) ||
1153 		    (portmode == PORT_1G_RGMII_FIBER)) {
1154 			if (statsp->mac_stats.link_speed == 100)
1155 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
1156 		}
1157 
1158 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
1159 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
1160 
1161 		if (statsp->mac_stats.link_speed == 1000)
1162 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
1163 
1164 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
1165 
1166 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
1167 		if (rs != NPI_SUCCESS)
1168 			goto fail;
1169 		nxgep->mac.xif_config = xif_cfg;
1170 	}
1171 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
1172 	return (NXGE_OK);
1173 fail:
1174 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1175 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
1176 	return (NXGE_ERROR | rs);
1177 }
1178 
1179 
1180 /*
1181  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
1182  * support loopback like XPCS.
1183  */
1184 nxge_status_t
1185 nxge_pcs_init(p_nxge_t nxgep)
1186 {
1187 	pcs_cfg_t		pcs_cfg;
1188 	uint32_t		val;
1189 	uint8_t			portn;
1190 	nxge_port_mode_t	portmode;
1191 	npi_handle_t		handle;
1192 	p_nxge_stats_t		statsp;
1193 	pcs_ctrl_t		pcs_ctrl;
1194 	npi_status_t		rs = NPI_SUCCESS;
1195 	uint8_t i;
1196 
1197 	handle = nxgep->npi_handle;
1198 	portmode = nxgep->mac.portmode;
1199 	portn = nxgep->mac.portnum;
1200 	statsp = nxgep->statsp;
1201 
1202 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
1203 
1204 	if (portmode == PORT_1G_FIBER ||
1205 	    portmode == PORT_1G_TN1010 ||
1206 	    portmode == PORT_1G_SERDES) {
1207 		if (portmode == PORT_1G_TN1010) {
1208 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
1209 			for (i = 0; i < 6; i ++) {
1210 				if ((rs = npi_mac_pcs_reset(handle, portn))
1211 				    != NPI_SUCCESS) {
1212 					goto fail;
1213 				}
1214 			}
1215 		} else {
1216 			if ((rs = npi_mac_pcs_reset(handle, portn))
1217 			    != NPI_SUCCESS)
1218 				goto fail;
1219 		}
1220 
1221 		/* Initialize port's PCS */
1222 		pcs_cfg.value = 0;
1223 		pcs_cfg.bits.w0.enable = 1;
1224 		pcs_cfg.bits.w0.mask = 1;
1225 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
1226 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
1227 
1228 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1229 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
1230 		    portn, pcs_cfg.value));
1231 
1232 		if (portmode == PORT_1G_TN1010) {
1233 			/*
1234 			 * Must disable PCS auto-negotiation when the the driver
1235 			 * is driving the TN1010 based XAUI card  Otherwise the
1236 			 * autonegotiation between the PCS and the TN1010 PCS
1237 			 * will never complete and the Neptune/NIU will not work
1238 			 */
1239 			pcs_ctrl.value = 0;
1240 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
1241 			    pcs_ctrl.value);
1242 		}
1243 	} else if (portmode == PORT_10G_FIBER ||
1244 	    portmode == PORT_10G_COPPER ||
1245 	    portmode == PORT_10G_TN1010 ||
1246 	    portmode == PORT_HSP_MODE ||
1247 	    portmode == PORT_10G_SERDES) {
1248 		/* Use internal XPCS, bypass 1G PCS */
1249 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1250 		val &= ~XMAC_XIF_XPCS_BYPASS;
1251 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1252 
1253 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
1254 			goto fail;
1255 
1256 		/* Set XPCS Internal Loopback if necessary */
1257 		if ((rs = npi_xmac_xpcs_read(handle, portn,
1258 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
1259 			goto fail;
1260 
1261 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
1262 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
1263 			val |= XPCS_CTRL1_LOOPBK;
1264 		else
1265 			val &= ~XPCS_CTRL1_LOOPBK;
1266 		if ((rs = npi_xmac_xpcs_write(handle, portn,
1267 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
1268 			goto fail;
1269 
1270 		/* Clear descw errors */
1271 		if ((rs = npi_xmac_xpcs_write(handle, portn,
1272 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
1273 			goto fail;
1274 		/* Clear symbol errors */
1275 		if ((rs = npi_xmac_xpcs_read(handle, portn,
1276 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
1277 			goto fail;
1278 		if ((rs = npi_xmac_xpcs_read(handle, portn,
1279 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
1280 			goto fail;
1281 
1282 	} else if ((portmode == PORT_1G_COPPER) ||
1283 	    (portmode == PORT_1G_RGMII_FIBER)) {
1284 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1285 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
1286 		if (portn < 4) {
1287 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
1288 			    PCS_DATAPATH_MODE_MII);
1289 		}
1290 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
1291 			goto fail;
1292 
1293 	} else {
1294 		goto fail;
1295 	}
1296 pass:
1297 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
1298 	return (NXGE_OK);
1299 fail:
1300 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1301 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
1302 	return (NXGE_ERROR | rs);
1303 }
1304 
1305 /*
1306  * Initialize the MAC CTRL sub-block within the MAC
1307  * Only the receive-pause-cap is supported.
1308  */
1309 nxge_status_t
1310 nxge_mac_ctrl_init(p_nxge_t nxgep)
1311 {
1312 	uint8_t			portn;
1313 	nxge_port_t		portt;
1314 	p_nxge_stats_t		statsp;
1315 	npi_handle_t		handle;
1316 	uint32_t		val;
1317 
1318 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1319 
1320 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1321 	    portn));
1322 
1323 	handle = nxgep->npi_handle;
1324 	portt = nxgep->mac.porttype;
1325 	statsp = nxgep->statsp;
1326 
1327 	if (portt == PORT_TYPE_XMAC) {
1328 		/* Reading the current XMAC Config Register for XMAC */
1329 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1330 
1331 		/*
1332 		 * Setup XMAC Configuration for XMAC
1333 		 * XMAC only supports receive-pause
1334 		 */
1335 		if (statsp->mac_stats.adv_cap_asmpause) {
1336 			if (!statsp->mac_stats.adv_cap_pause) {
1337 				/*
1338 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1339 				 * is 0, enable receive pause.
1340 				 */
1341 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1342 			} else {
1343 				/*
1344 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1345 				 * is 1, disable receive pause.  Send pause is
1346 				 * not supported.
1347 				 */
1348 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1349 			}
1350 		} else {
1351 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1352 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
1353 			    portn));
1354 			if (statsp->mac_stats.adv_cap_pause) {
1355 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1356 				    "==> nxge_mac_ctrl_init: port<%d>: "
1357 				    "enable pause", portn));
1358 				/*
1359 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1360 				 * is 1, enable receive pause.
1361 				 */
1362 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1363 			} else {
1364 				/*
1365 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1366 				 * is 0, disable receive pause. Send pause is
1367 				 * not supported
1368 				 */
1369 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1370 				    "==> nxge_mac_ctrl_init: port<%d>: "
1371 				    "disable pause", portn));
1372 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1373 			}
1374 		}
1375 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1376 	} else if (portt == PORT_TYPE_BMAC) {
1377 		/* Reading the current MAC CTRL Config Register for BMAC */
1378 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1379 
1380 		/* Setup MAC CTRL Configuration for BMAC */
1381 		if (statsp->mac_stats.adv_cap_asmpause) {
1382 			if (statsp->mac_stats.adv_cap_pause) {
1383 				/*
1384 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1385 				 * is 1, disable receive pause. Send pause
1386 				 * is not supported
1387 				 */
1388 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1389 			} else {
1390 				/*
1391 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1392 				 * is 0, enable receive pause and disable
1393 				 * send pause.
1394 				 */
1395 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1396 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1397 			}
1398 		} else {
1399 			if (statsp->mac_stats.adv_cap_pause) {
1400 				/*
1401 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1402 				 * is 1, enable receive pause. Send pause is
1403 				 * not supported.
1404 				 */
1405 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1406 			} else {
1407 				/*
1408 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1409 				 * is 0, pause capability is not available in
1410 				 * either direction.
1411 				 */
1412 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1413 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
1414 			}
1415 		}
1416 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1417 	}
1418 
1419 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1420 	    portn));
1421 
1422 	return (NXGE_OK);
1423 }
1424 
1425 /* Initialize the Internal Serdes */
1426 
1427 nxge_status_t
1428 nxge_serdes_init(p_nxge_t nxgep)
1429 {
1430 	p_nxge_stats_t		statsp;
1431 #ifdef	NXGE_DEBUG
1432 	uint8_t			portn;
1433 #endif
1434 	nxge_status_t		status = NXGE_OK;
1435 
1436 #ifdef	NXGE_DEBUG
1437 	portn = nxgep->mac.portnum;
1438 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1439 	    "==> nxge_serdes_init port<%d>", portn));
1440 #endif
1441 
1442 	if (nxgep->xcvr.serdes_init) {
1443 		statsp = nxgep->statsp;
1444 		status = nxgep->xcvr.serdes_init(nxgep);
1445 		if (status != NXGE_OK)
1446 			goto fail;
1447 		statsp->mac_stats.serdes_inits++;
1448 	}
1449 
1450 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
1451 	    portn));
1452 
1453 	return (NXGE_OK);
1454 
1455 fail:
1456 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1457 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
1458 	    portn));
1459 
1460 	return (status);
1461 }
1462 
1463 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
1464 
1465 static nxge_status_t
1466 nxge_n2_serdes_init(p_nxge_t nxgep)
1467 {
1468 	uint8_t portn;
1469 	int chan;
1470 	esr_ti_cfgpll_l_t pll_cfg_l;
1471 	esr_ti_cfgpll_l_t pll_sts_l;
1472 	esr_ti_cfgrx_l_t rx_cfg_l;
1473 	esr_ti_cfgrx_h_t rx_cfg_h;
1474 	esr_ti_cfgtx_l_t tx_cfg_l;
1475 	esr_ti_cfgtx_h_t tx_cfg_h;
1476 #ifdef NXGE_DEBUG
1477 	esr_ti_testcfg_t cfg;
1478 #endif
1479 	esr_ti_testcfg_t test_cfg;
1480 	nxge_status_t status = NXGE_OK;
1481 
1482 	portn = nxgep->mac.portnum;
1483 
1484 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
1485 	    portn));
1486 	if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) {
1487 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1488 		    "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
1489 		return (nxge_n2_kt_serdes_init(nxgep));
1490 	}
1491 
1492 	tx_cfg_l.value = 0;
1493 	tx_cfg_h.value = 0;
1494 	rx_cfg_l.value = 0;
1495 	rx_cfg_h.value = 0;
1496 	pll_cfg_l.value = 0;
1497 	pll_sts_l.value = 0;
1498 	test_cfg.value = 0;
1499 
1500 	/*
1501 	 * If the nxge driver has been plumbed without a link, then it will
1502 	 * detect a link up when a cable connecting to an anto-negotiation
1503 	 * partner is plugged into the port. Because the TN1010 PHY supports
1504 	 * both 1G and 10G speeds, the driver must re-configure the
1505 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
1506 	 * is called at the post-link-up reconfiguration time. Here it calls
1507 	 * nxge_set_tn1010_param to set portmode before re-initializing
1508 	 * the serdes.
1509 	 */
1510 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
1511 	    nxgep->mac.portmode == PORT_10G_TN1010) {
1512 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
1513 			goto fail;
1514 		}
1515 	}
1516 
1517 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
1518 	    nxgep->mac.portmode == PORT_10G_COPPER ||
1519 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
1520 	    nxgep->mac.portmode == PORT_HSP_MODE ||
1521 	    nxgep->mac.portmode == PORT_10G_SERDES) {
1522 		/* 0x0E01 */
1523 		tx_cfg_l.bits.entx = 1;
1524 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
1525 
1526 		/* 0x9101 */
1527 		rx_cfg_l.bits.enrx = 1;
1528 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
1529 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
1530 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
1531 
1532 		/* 0x0008 */
1533 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
1534 
1535 		/* Set loopback mode if necessary */
1536 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1537 			tx_cfg_l.bits.entest = 1;
1538 			rx_cfg_l.bits.entest = 1;
1539 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1540 			if ((status = nxge_mdio_write(nxgep, portn,
1541 			    ESR_N2_DEV_ADDR,
1542 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
1543 			goto fail;
1544 		}
1545 
1546 		/* Initialize PLL for 10G */
1547 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
1548 		pll_cfg_l.bits.enpll = 1;
1549 		pll_sts_l.bits.enpll = 1;
1550 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1551 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1552 			goto fail;
1553 
1554 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1555 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
1556 			goto fail;
1557 
1558 #ifdef  NXGE_DEBUG
1559 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1560 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1561 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1562 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1563 		    portn, pll_cfg_l.value, cfg.value));
1564 
1565 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1566 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1567 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1568 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
1569 		    portn, pll_sts_l.value, cfg.value));
1570 #endif
1571 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
1572 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
1573 	    nxgep->mac.portmode == PORT_1G_SERDES) {
1574 		/* 0x0E21 */
1575 		tx_cfg_l.bits.entx = 1;
1576 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
1577 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
1578 
1579 		/* 0x9121 */
1580 		rx_cfg_l.bits.enrx = 1;
1581 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
1582 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
1583 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
1584 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
1585 
1586 		if (portn == 0) {
1587 			/* 0x8 */
1588 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
1589 		}
1590 
1591 		/* Initialize PLL for 1G */
1592 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
1593 		pll_cfg_l.bits.enpll = 1;
1594 		pll_sts_l.bits.enpll = 1;
1595 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1596 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1597 			goto fail;
1598 
1599 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1600 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
1601 			goto fail;
1602 
1603 #ifdef  NXGE_DEBUG
1604 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1605 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1606 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1607 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1608 		    portn, pll_cfg_l.value, cfg.value));
1609 
1610 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1611 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1612 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1613 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
1614 		    portn, pll_sts_l.value, cfg.value));
1615 #endif
1616 
1617 		/* Set loopback mode if necessary */
1618 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1619 			tx_cfg_l.bits.entest = 1;
1620 			rx_cfg_l.bits.entest = 1;
1621 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1622 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1623 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
1624 			    portn, test_cfg.value));
1625 			if ((status = nxge_mdio_write(nxgep, portn,
1626 			    ESR_N2_DEV_ADDR,
1627 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1628 				goto fail;
1629 			}
1630 		}
1631 	} else {
1632 		goto fail;
1633 	}
1634 
1635 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
1636 
1637 	NXGE_DELAY(20);
1638 
1639 	/* init TX channels */
1640 	for (chan = 0; chan < 4; chan++) {
1641 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1642 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
1643 			goto fail;
1644 
1645 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1646 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
1647 			goto fail;
1648 
1649 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1650 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
1651 		    portn, chan, tx_cfg_l.value));
1652 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1653 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
1654 		    portn, chan, tx_cfg_h.value));
1655 	}
1656 
1657 	/* init RX channels */
1658 	for (chan = 0; chan < 4; chan++) {
1659 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1660 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
1661 			goto fail;
1662 
1663 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1664 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
1665 			goto fail;
1666 
1667 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1668 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
1669 		    portn, chan, rx_cfg_l.value));
1670 
1671 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1672 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
1673 		    portn, chan, rx_cfg_h.value));
1674 	}
1675 
1676 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
1677 	    portn));
1678 
1679 	return (NXGE_OK);
1680 fail:
1681 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1682 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
1683 	    portn));
1684 
1685 	return (status);
1686 
1687 }
1688 
1689 /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */
1690 
1691 static nxge_status_t
1692 nxge_n2_kt_serdes_init(p_nxge_t nxgep)
1693 {
1694 	uint8_t portn;
1695 	int chan, i;
1696 	k_esr_ti_cfgpll_l_t pll_cfg_l;
1697 	k_esr_ti_cfgrx_l_t rx_cfg_l;
1698 	k_esr_ti_cfgrx_h_t rx_cfg_h;
1699 	k_esr_ti_cfgtx_l_t tx_cfg_l;
1700 	k_esr_ti_cfgtx_h_t tx_cfg_h;
1701 #ifdef NXGE_DEBUG
1702 	k_esr_ti_testcfg_t cfg;
1703 #endif
1704 	k_esr_ti_testcfg_t test_cfg;
1705 	nxge_status_t status = NXGE_OK;
1706 	boolean_t mode_1g = B_FALSE;
1707 	uint64_t val;
1708 	npi_handle_t handle;
1709 
1710 	portn = nxgep->mac.portnum;
1711 
1712 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1713 	    "==> nxge_n2_kt_serdes_init port<%d>", portn));
1714 	handle = nxgep->npi_handle;
1715 
1716 	tx_cfg_l.value = 0;
1717 	tx_cfg_h.value = 0;
1718 	rx_cfg_l.value = 0;
1719 	rx_cfg_h.value = 0;
1720 	pll_cfg_l.value = 0;
1721 	test_cfg.value = 0;
1722 
1723 	/*
1724 	 * The following setting assumes the reference clock frquency
1725 	 * is 156.25 MHz.
1726 	 */
1727 	/*
1728 	 * If the nxge driver has been plumbed without a link, then it will
1729 	 * detect a link up when a cable connecting to an anto-negotiation
1730 	 * partner is plugged into the port. Because the TN1010 PHY supports
1731 	 * both 1G and 10G speeds, the driver must re-configure the
1732 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
1733 	 * is called at the post-link-up reconfiguration time. Here it calls
1734 	 * nxge_set_tn1010_param to set portmode before re-initializing
1735 	 * the serdes.
1736 	 */
1737 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
1738 	    nxgep->mac.portmode == PORT_10G_TN1010) {
1739 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
1740 			goto fail;
1741 		}
1742 	}
1743 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
1744 	    nxgep->mac.portmode == PORT_10G_COPPER ||
1745 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
1746 	    nxgep->mac.portmode == PORT_10G_SERDES) {
1747 
1748 		/* Take tunables from OBP if present, otherwise use defaults */
1749 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGL) {
1750 			tx_cfg_l.value = nxgep->srds_prop.tx_cfg_l;
1751 		} else {
1752 			tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX;
1753 			/* 0x1e21 */
1754 			tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1755 			tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1756 		}
1757 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1758 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1759 		    portn, tx_cfg_l.value));
1760 
1761 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGH) {
1762 			tx_cfg_h.value = nxgep->srds_prop.tx_cfg_h;
1763 		} else {
1764 			/* channel 0: enable syn. master */
1765 			/* 0x40 */
1766 			tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1767 		}
1768 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1769 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1770 		    portn, tx_cfg_h.value));
1771 
1772 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGL) {
1773 			rx_cfg_l.value = nxgep->srds_prop.rx_cfg_l;
1774 		} else {
1775 			/* 0x4821 */
1776 			rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX;
1777 			rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1778 			rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1779 			rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1780 		}
1781 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1782 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1783 		    portn, rx_cfg_l.value));
1784 
1785 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGH) {
1786 			rx_cfg_h.value = nxgep->srds_prop.rx_cfg_h;
1787 		} else {
1788 			/* 0x0008 */
1789 			rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE;
1790 		}
1791 
1792 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1793 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
1794 		    portn, rx_cfg_h.value));
1795 
1796 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_PLLCFGL) {
1797 			pll_cfg_l.value = nxgep->srds_prop.pll_cfg_l;
1798 		} else {
1799 			/* 0xa1: Initialize PLL for 10G */
1800 			pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1801 			pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1802 		}
1803 
1804 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1805 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1806 		    portn, pll_cfg_l.value));
1807 
1808 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1809 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1810 			goto fail;
1811 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1812 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1813 		    portn, pll_cfg_l.value));
1814 
1815 		/* Set loopback mode if necessary */
1816 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1817 			tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1818 			rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1819 			rx_cfg_l.bits.los = 0;
1820 
1821 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1822 			    "==> nxge_n2_kt_serdes_init port<%d>: "
1823 			    "loopback 0x%x", portn, tx_cfg_h.value));
1824 		}
1825 #ifdef  NXGE_DEBUG
1826 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1827 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1828 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1829 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1830 		    "PLL cfg.l 0x%x (0x%x)",
1831 		    portn, pll_cfg_l.value, cfg.value));
1832 
1833 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1834 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1835 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1836 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1837 		    portn, cfg.value));
1838 #endif
1839 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
1840 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
1841 	    nxgep->mac.portmode == PORT_1G_SERDES) {
1842 		mode_1g = B_TRUE;
1843 		/* 0x1e41 */
1844 		tx_cfg_l.bits.entx = 1;
1845 		tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1846 		tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1847 
1848 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1849 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1850 		    portn, tx_cfg_l.value));
1851 
1852 
1853 		/* channel 0: enable syn. master */
1854 		tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1855 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1856 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1857 		    portn, tx_cfg_h.value));
1858 
1859 
1860 		/* 0x4841 */
1861 		rx_cfg_l.bits.enrx = 1;
1862 		rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1863 		rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1864 		rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1865 
1866 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1867 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1868 		    portn, rx_cfg_l.value));
1869 
1870 		/* 0x0008 */
1871 		rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF;
1872 
1873 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1874 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1875 		    portn, rx_cfg_h.value));
1876 
1877 		/* 0xa1: Initialize PLL for 1G */
1878 		pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1879 		pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1880 
1881 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1882 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1883 		    portn, pll_cfg_l.value));
1884 
1885 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1886 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
1887 		    != NXGE_OK)
1888 			goto fail;
1889 
1890 
1891 #ifdef  NXGE_DEBUG
1892 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1893 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1894 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1895 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1896 		    portn, pll_cfg_l.value, cfg.value));
1897 
1898 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1899 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1900 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1901 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1902 		    portn, cfg.value));
1903 #endif
1904 
1905 		/* Set loopback mode if necessary */
1906 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1907 			tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1908 
1909 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1910 			    "==> nxge_n2_kt_serdes_init port<%d>: "
1911 			    "loopback 0x%x", portn, test_cfg.value));
1912 			if ((status = nxge_mdio_write(nxgep, portn,
1913 			    ESR_N2_DEV_ADDR,
1914 			    ESR_N2_TX_CFG_L_REG_ADDR(0),
1915 			    tx_cfg_h.value)) != NXGE_OK) {
1916 				goto fail;
1917 			}
1918 		}
1919 	} else {
1920 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1921 		    "nxge_n2_kt_serdes_init:port<%d> - "
1922 		    "unsupported port mode %d",
1923 		    portn, nxgep->mac.portmode));
1924 		goto fail;
1925 	}
1926 
1927 	NXGE_DELAY(20);
1928 	/* Clear the test register (offset 0x8004) */
1929 	if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1930 	    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1931 		goto fail;
1932 	}
1933 	NXGE_DELAY(20);
1934 
1935 	/* init TX channels */
1936 	for (chan = 0; chan < 4; chan++) {
1937 		if (mode_1g)
1938 			tx_cfg_l.value = 0;
1939 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1940 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
1941 			goto fail;
1942 
1943 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1944 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
1945 			goto fail;
1946 
1947 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1948 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1949 		    "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value));
1950 
1951 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1952 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1953 		    "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value));
1954 	}
1955 
1956 	/* init RX channels */
1957 	/* 1G mode only write to the first channel */
1958 	for (chan = 0; chan < 4; chan++) {
1959 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1960 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
1961 		    != NXGE_OK)
1962 			goto fail;
1963 
1964 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1965 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
1966 		    != NXGE_OK)
1967 			goto fail;
1968 
1969 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1970 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1971 		    "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value));
1972 
1973 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1974 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1975 		    "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value));
1976 	}
1977 
1978 	if (portn == 0) {
1979 		/* Wait for serdes to be ready */
1980 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1981 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1982 			if ((val & ESR_SIG_P0_BITS_MASK) !=
1983 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1984 			    ESR_SIG_XSERDES_RDY_P0 |
1985 			    ESR_SIG_XDETECT_P0_CH3 |
1986 			    ESR_SIG_XDETECT_P0_CH2 |
1987 			    ESR_SIG_XDETECT_P0_CH1 |
1988 			    ESR_SIG_XDETECT_P0_CH0))
1989 
1990 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1991 			else
1992 				break;
1993 		}
1994 
1995 		if (i == MAX_SERDES_RDY_RETRIES) {
1996 			/*
1997 			 * RDY signal stays low may due to the absent of the
1998 			 * external PHY, it is not an error condition.
1999 			 * But still print the message for the debugging
2000 			 * purpose when link stays down
2001 			 */
2002 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2003 			    "nxge_n2_kt_serdes_init: "
2004 			    "Serdes/signal for port<%d> not ready", portn));
2005 				goto done;
2006 		}
2007 	} else if (portn == 1) {
2008 		/* Wait for serdes to be ready */
2009 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2010 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2011 			if ((val & ESR_SIG_P1_BITS_MASK) !=
2012 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
2013 			    ESR_SIG_XSERDES_RDY_P1 |
2014 			    ESR_SIG_XDETECT_P1_CH3 |
2015 			    ESR_SIG_XDETECT_P1_CH2 |
2016 			    ESR_SIG_XDETECT_P1_CH1 |
2017 			    ESR_SIG_XDETECT_P1_CH0))
2018 
2019 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2020 			else
2021 				break;
2022 		}
2023 
2024 		if (i == MAX_SERDES_RDY_RETRIES) {
2025 			/*
2026 			 * RDY signal stays low may due to the absent of the
2027 			 * external PHY, it is not an error condition.
2028 			 * But still print the message for the debugging
2029 			 * purpose when link stays down
2030 			 */
2031 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2032 			    "nxge_n2_kt_serdes_init: "
2033 			    "Serdes/signal for port<%d> not ready", portn));
2034 				goto done;
2035 		}
2036 	}
2037 done:
2038 
2039 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2040 	    "<== nxge_n2_kt_serdes_init port<%d>", portn));
2041 
2042 	return (NXGE_OK);
2043 fail:
2044 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2045 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
2046 	    portn));
2047 
2048 	return (status);
2049 }
2050 
2051 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
2052 
2053 static nxge_status_t
2054 nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
2055 {
2056 	npi_handle_t		handle;
2057 	uint8_t			portn;
2058 	int			chan, i;
2059 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
2060 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
2061 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
2062 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
2063 	uint64_t		val;
2064 	uint16_t		val16l;
2065 	uint16_t		val16h;
2066 	nxge_status_t		status = NXGE_OK;
2067 
2068 	portn = nxgep->mac.portnum;
2069 
2070 	if ((portn != 0) && (portn != 1))
2071 		return (NXGE_OK);
2072 
2073 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2074 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
2075 	handle = nxgep->npi_handle;
2076 	switch (portn) {
2077 	case 0:
2078 		/* Reset Serdes */
2079 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
2080 		NXGE_DELAY(20);
2081 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
2082 		NXGE_DELAY(2000);
2083 
2084 		/* Configure Serdes to 10G mode */
2085 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2086 		    ESR_PLL_CFG_10G_SERDES);
2087 
2088 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
2089 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
2090 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
2091 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
2092 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
2093 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
2094 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2095 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2096 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
2097 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
2098 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
2099 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
2100 
2101 		/* Set Serdes0 Internal Loopback if necessary */
2102 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
2103 			ESR_REG_WR(handle,
2104 			    ESR_0_TEST_CONFIG_REG,
2105 			    ESR_PAD_LOOPBACK_CH3 |
2106 			    ESR_PAD_LOOPBACK_CH2 |
2107 			    ESR_PAD_LOOPBACK_CH1 |
2108 			    ESR_PAD_LOOPBACK_CH0);
2109 		} else {
2110 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2111 		}
2112 		break;
2113 	case 1:
2114 		/* Reset Serdes */
2115 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
2116 		NXGE_DELAY(20);
2117 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
2118 		NXGE_DELAY(2000);
2119 
2120 		/* Configure Serdes to 10G mode */
2121 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2122 		    ESR_PLL_CFG_10G_SERDES);
2123 
2124 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
2125 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
2126 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
2127 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
2128 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
2129 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
2130 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2131 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
2132 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
2133 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
2134 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
2135 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
2136 
2137 		/* Set Serdes1 Internal Loopback if necessary */
2138 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
2139 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2140 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
2141 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
2142 		} else {
2143 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2144 		}
2145 		break;
2146 	default:
2147 		/* Nothing to do here */
2148 		goto done;
2149 	}
2150 
2151 	/* init TX RX channels */
2152 	for (chan = 0; chan < 4; chan++) {
2153 		if ((status = nxge_mdio_read(nxgep, portn,
2154 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2155 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
2156 			goto fail;
2157 		if ((status = nxge_mdio_read(nxgep, portn,
2158 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2159 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
2160 			goto fail;
2161 		if ((status = nxge_mdio_read(nxgep, portn,
2162 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2163 		    &glue_ctrl0_l.value)) != NXGE_OK)
2164 			goto fail;
2165 		if ((status = nxge_mdio_read(nxgep, portn,
2166 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2167 		    &glue_ctrl0_h.value)) != NXGE_OK)
2168 			goto fail;
2169 		rx_tx_ctrl_l.bits.enstretch = 1;
2170 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2171 		rx_tx_ctrl_h.bits.vpulselo = 2;
2172 		glue_ctrl0_l.bits.rxlosenable = 1;
2173 		glue_ctrl0_l.bits.samplerate = 0xF;
2174 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2175 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2176 		if ((status = nxge_mdio_write(nxgep, portn,
2177 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2178 		    rx_tx_ctrl_l.value)) != NXGE_OK)
2179 			goto fail;
2180 		if ((status = nxge_mdio_write(nxgep, portn,
2181 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2182 		    rx_tx_ctrl_h.value)) != NXGE_OK)
2183 			goto fail;
2184 		if ((status = nxge_mdio_write(nxgep, portn,
2185 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2186 		    glue_ctrl0_l.value)) != NXGE_OK)
2187 			goto fail;
2188 		if ((status = nxge_mdio_write(nxgep, portn,
2189 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2190 		    glue_ctrl0_h.value)) != NXGE_OK)
2191 			goto fail;
2192 		}
2193 
2194 	/* Apply Tx core reset */
2195 	if ((status = nxge_mdio_write(nxgep, portn,
2196 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
2197 	    (uint16_t)0)) != NXGE_OK)
2198 		goto fail;
2199 
2200 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2201 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2202 	    NXGE_OK)
2203 		goto fail;
2204 
2205 	NXGE_DELAY(200);
2206 
2207 	/* Apply Rx core reset */
2208 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2209 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2210 	    NXGE_OK)
2211 		goto fail;
2212 
2213 	NXGE_DELAY(200);
2214 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2215 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
2216 		goto fail;
2217 
2218 	NXGE_DELAY(200);
2219 	if ((status = nxge_mdio_read(nxgep, portn,
2220 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
2221 	    &val16l)) != NXGE_OK)
2222 		goto fail;
2223 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2224 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
2225 		goto fail;
2226 	if ((val16l != 0) || (val16h != 0)) {
2227 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2228 		    "Failed to reset port<%d> XAUI Serdes "
2229 		    "(val16l 0x%x val16h 0x%x)",
2230 		    portn, val16l, val16h));
2231 	}
2232 
2233 	if (portn == 0) {
2234 		/* Wait for serdes to be ready */
2235 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2236 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2237 			if ((val & ESR_SIG_P0_BITS_MASK) !=
2238 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
2239 			    ESR_SIG_XSERDES_RDY_P0 |
2240 			    ESR_SIG_XDETECT_P0_CH3 |
2241 			    ESR_SIG_XDETECT_P0_CH2 |
2242 			    ESR_SIG_XDETECT_P0_CH1 |
2243 			    ESR_SIG_XDETECT_P0_CH0))
2244 
2245 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2246 			else
2247 				break;
2248 		}
2249 
2250 		if (i == MAX_SERDES_RDY_RETRIES) {
2251 			/*
2252 			 * RDY signal stays low may due to the absent of the
2253 			 * external PHY, it is not an error condition. But still
2254 			 * print the message for the debugging purpose when link
2255 			 * stays down
2256 			 */
2257 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2258 			    "nxge_neptune_10G_serdes_init: "
2259 			    "Serdes/signal for port<%d> not ready", portn));
2260 				goto done;
2261 		}
2262 	} else if (portn == 1) {
2263 		/* Wait for serdes to be ready */
2264 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2265 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2266 			if ((val & ESR_SIG_P1_BITS_MASK) !=
2267 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
2268 			    ESR_SIG_XSERDES_RDY_P1 |
2269 			    ESR_SIG_XDETECT_P1_CH3 |
2270 			    ESR_SIG_XDETECT_P1_CH2 |
2271 			    ESR_SIG_XDETECT_P1_CH1 |
2272 			    ESR_SIG_XDETECT_P1_CH0))
2273 
2274 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2275 			else
2276 				break;
2277 		}
2278 
2279 		if (i == MAX_SERDES_RDY_RETRIES) {
2280 			/*
2281 			 * RDY signal stays low may due to the absent of the
2282 			 * external PHY, it is not an error condition. But still
2283 			 * print the message for the debugging purpose when link
2284 			 * stays down
2285 			 */
2286 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2287 			    "nxge_neptune_10G_serdes_init: "
2288 			    "Serdes/signal for port<%d> not ready", portn));
2289 				goto done;
2290 		}
2291 	}
2292 
2293 done:
2294 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2295 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
2296 
2297 	return (NXGE_OK);
2298 fail:
2299 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2300 	    "nxge_neptune_10G_serdes_init: "
2301 	    "Failed to initialize Neptune serdes for port<%d>", portn));
2302 
2303 	return (status);
2304 }
2305 
2306 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
2307 
2308 static nxge_status_t
2309 nxge_1G_serdes_init(p_nxge_t nxgep)
2310 {
2311 	npi_handle_t		handle;
2312 	uint8_t			portn;
2313 	int			chan;
2314 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
2315 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
2316 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
2317 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
2318 	uint64_t		val;
2319 	uint16_t		val16l;
2320 	uint16_t		val16h;
2321 	nxge_status_t		status = NXGE_OK;
2322 
2323 	portn = nxgep->mac.portnum;
2324 
2325 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2326 	    "==> nxge_1G_serdes_init port<%d>", portn));
2327 
2328 	handle = nxgep->npi_handle;
2329 
2330 	switch (portn) {
2331 	case 0:
2332 		/* Assert the reset register */
2333 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2334 		val |= ESR_RESET_0;
2335 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2336 
2337 		/* Set the PLL register to 0x79 */
2338 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2339 		    ESR_PLL_CFG_1G_SERDES);
2340 
2341 		/* Set the control register to 0x249249f */
2342 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
2343 
2344 		/* Set Serdes0 Internal Loopback if necessary */
2345 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2346 			/* Set pad loopback modes 0xaa */
2347 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
2348 			    ESR_TSTCFG_LBTEST_PAD);
2349 		} else {
2350 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2351 		}
2352 
2353 		/* Deassert the reset register */
2354 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2355 		val &= ~ESR_RESET_0;
2356 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2357 		break;
2358 
2359 	case 1:
2360 		/* Assert the reset register */
2361 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2362 		val |= ESR_RESET_1;
2363 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2364 
2365 		/* Set PLL register to 0x79 */
2366 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2367 		    ESR_PLL_CFG_1G_SERDES);
2368 
2369 		/* Set the control register to 0x249249f */
2370 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
2371 
2372 		/* Set Serdes1 Internal Loopback if necessary */
2373 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2374 			/* Set pad loopback mode 0xaa */
2375 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2376 			    ESR_TSTCFG_LBTEST_PAD);
2377 		} else {
2378 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2379 		}
2380 
2381 		/* Deassert the reset register */
2382 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2383 		val &= ~ESR_RESET_1;
2384 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2385 		break;
2386 
2387 	default:
2388 		/* Nothing to do here */
2389 		goto done;
2390 	}
2391 
2392 	/* init TX RX channels */
2393 	for (chan = 0; chan < 4; chan++) {
2394 		if ((status = nxge_mdio_read(nxgep, portn,
2395 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2396 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
2397 			goto fail;
2398 		}
2399 		if ((status = nxge_mdio_read(nxgep, portn,
2400 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2401 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
2402 			goto fail;
2403 		}
2404 		if ((status = nxge_mdio_read(nxgep, portn,
2405 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2406 		    &glue_ctrl0_l.value)) != NXGE_OK) {
2407 			goto fail;
2408 		}
2409 		if ((status = nxge_mdio_read(nxgep, portn,
2410 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2411 		    &glue_ctrl0_h.value)) != NXGE_OK) {
2412 			goto fail;
2413 		}
2414 
2415 		rx_tx_ctrl_l.bits.enstretch = 1;
2416 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2417 		rx_tx_ctrl_h.bits.vpulselo = 2;
2418 		glue_ctrl0_l.bits.rxlosenable = 1;
2419 		glue_ctrl0_l.bits.samplerate = 0xF;
2420 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2421 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2422 		if ((status = nxge_mdio_write(nxgep, portn,
2423 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2424 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
2425 			goto fail;
2426 		}
2427 		if ((status = nxge_mdio_write(nxgep, portn,
2428 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2429 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
2430 			goto fail;
2431 		}
2432 		if ((status = nxge_mdio_write(nxgep, portn,
2433 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2434 		    glue_ctrl0_l.value)) != NXGE_OK) {
2435 			goto fail;
2436 		}
2437 		if ((status = nxge_mdio_write(nxgep, portn,
2438 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2439 		    glue_ctrl0_h.value)) != NXGE_OK) {
2440 			goto fail;
2441 		}
2442 	}
2443 
2444 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2445 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2446 		goto fail;
2447 	}
2448 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2449 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2450 		goto fail;
2451 	}
2452 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2453 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2454 		goto fail;
2455 	}
2456 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2457 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2458 		goto fail;
2459 	}
2460 
2461 	/* Apply Tx core reset */
2462 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2463 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2464 		goto fail;
2465 	}
2466 
2467 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2468 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2469 	    NXGE_OK) {
2470 		goto fail;
2471 	}
2472 
2473 	NXGE_DELAY(200);
2474 
2475 	/* Apply Rx core reset */
2476 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2477 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2478 	    NXGE_OK) {
2479 		goto fail;
2480 	}
2481 
2482 	NXGE_DELAY(200);
2483 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2484 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2485 		goto fail;
2486 	}
2487 
2488 	NXGE_DELAY(200);
2489 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2490 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2491 		goto fail;
2492 	}
2493 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2494 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2495 		goto fail;
2496 	}
2497 	if ((val16l != 0) || (val16h != 0)) {
2498 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2499 		    "Failed to reset port<%d> XAUI Serdes "
2500 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2501 		status = NXGE_ERROR;
2502 		goto fail;
2503 	}
2504 
2505 	NXGE_DELAY(200);
2506 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2507 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2508 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2509 	    "val 0x%x", portn, val));
2510 	if (portn == 0) {
2511 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2512 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2513 			/*
2514 			 * RDY signal stays low may due to the absent of the
2515 			 * external PHY, it is not an error condition. But still
2516 			 * print the message for the debugging purpose when link
2517 			 * stays down
2518 			 */
2519 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2520 			    "nxge_neptune_1G_serdes_init: "
2521 			    "Serdes/signal for port<%d> not ready", portn));
2522 				goto done;
2523 		}
2524 	} else if (portn == 1) {
2525 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2526 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2527 			/*
2528 			 * RDY signal stays low may due to the absent of the
2529 			 * external PHY, it is not an error condition. But still
2530 			 * print the message for the debugging purpose when link
2531 			 * stays down
2532 			 */
2533 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2534 			    "nxge_neptune_1G_serdes_init: "
2535 			    "Serdes/signal for port<%d> not ready", portn));
2536 				goto done;
2537 
2538 		}
2539 	}
2540 done:
2541 
2542 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2543 	    "<== nxge_1G_serdes_init port<%d>", portn));
2544 	return (NXGE_OK);
2545 fail:
2546 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2547 	    "nxge_1G_serdes_init: "
2548 	    "Failed to initialize Neptune serdes for port<%d>",
2549 	    portn));
2550 
2551 	return (status);
2552 }
2553 
2554 #define	NXGE_SET_PHY_TUNABLES(nxgep, phy_port, stat)			\
2555 {									\
2556 	int i;								\
2557 									\
2558 	if (nxgep->phy_prop.cnt > 0) {					\
2559 		for (i = 0; i < nxgep->phy_prop.cnt; i++) {		\
2560 			if ((stat = nxge_mdio_write(nxgep, phy_port,	\
2561 			    nxgep->phy_prop.arr[i].dev,			\
2562 			    nxgep->phy_prop.arr[i].reg,			\
2563 			    nxgep->phy_prop.arr[i].val)) != NXGE_OK) {	\
2564 				break;					\
2565 			}						\
2566 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,			\
2567 			    "From OBP, write<dev.reg.val> = "		\
2568 			    "<0x%x.0x%x.0x%x>",				\
2569 			    nxgep->phy_prop.arr[i].dev,			\
2570 			    nxgep->phy_prop.arr[i].reg,			\
2571 			    nxgep->phy_prop.arr[i].val));		\
2572 		}							\
2573 	}								\
2574 }
2575 
2576 /* Initialize the BCM 8704 xcvr */
2577 
2578 static nxge_status_t
2579 nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
2580 {
2581 	uint16_t		val;
2582 #ifdef	NXGE_DEBUG
2583 	uint8_t			portn;
2584 	uint16_t		val1;
2585 #endif
2586 	uint8_t			phy_port_addr;
2587 	pmd_tx_control_t	tx_ctl;
2588 	control_t		ctl;
2589 	phyxs_control_t		phyxs_ctl;
2590 	pcs_control_t		pcs_ctl;
2591 	uint32_t		delay = 0;
2592 	optics_dcntr_t		op_ctr;
2593 	nxge_status_t		status = NXGE_OK;
2594 #ifdef	NXGE_DEBUG
2595 	portn = nxgep->mac.portnum;
2596 #endif
2597 
2598 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
2599 	    portn));
2600 
2601 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
2602 
2603 	/* Reset the transceiver */
2604 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2605 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
2606 		goto fail;
2607 
2608 	phyxs_ctl.bits.reset = 1;
2609 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2610 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
2611 		goto fail;
2612 
2613 	do {
2614 		drv_usecwait(500);
2615 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2616 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
2617 		    &phyxs_ctl.value)) != NXGE_OK)
2618 			goto fail;
2619 		delay++;
2620 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
2621 	if (delay == 100) {
2622 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2623 		    "failed to reset Transceiver on port<%d>", portn));
2624 		status = NXGE_ERROR;
2625 		goto fail;
2626 	}
2627 
2628 	/* Set to 0x7FBF */
2629 	ctl.value = 0;
2630 	ctl.bits.res1 = 0x3F;
2631 	ctl.bits.optxon_lvl = 1;
2632 	ctl.bits.oprxflt_lvl = 1;
2633 	ctl.bits.optrxlos_lvl = 1;
2634 	ctl.bits.optxflt_lvl = 1;
2635 	ctl.bits.opprflt_lvl = 1;
2636 	ctl.bits.obtmpflt_lvl = 1;
2637 	ctl.bits.opbiasflt_lvl = 1;
2638 	ctl.bits.optxrst_lvl = 1;
2639 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2640 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
2641 	    != NXGE_OK)
2642 		goto fail;
2643 
2644 	/* Set to 0x164 */
2645 	tx_ctl.value = 0;
2646 	tx_ctl.bits.tsck_lpwren = 1;
2647 	tx_ctl.bits.tx_dac_txck = 0x2;
2648 	tx_ctl.bits.tx_dac_txd = 0x1;
2649 	tx_ctl.bits.xfp_clken = 1;
2650 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2651 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
2652 	    tx_ctl.value)) != NXGE_OK)
2653 		goto fail;
2654 	/*
2655 	 * According to Broadcom's instruction, SW needs to read
2656 	 * back these registers twice after written.
2657 	 */
2658 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2659 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
2660 	    != NXGE_OK)
2661 		goto fail;
2662 
2663 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2664 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
2665 	    != NXGE_OK)
2666 		goto fail;
2667 
2668 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2669 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
2670 	    != NXGE_OK)
2671 		goto fail;
2672 
2673 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2674 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
2675 	    != NXGE_OK)
2676 		goto fail;
2677 
2678 	/* Enable Tx and Rx LEDs to be driven by traffic */
2679 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2680 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2681 	    &op_ctr.value)) != NXGE_OK)
2682 		goto fail;
2683 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2684 		op_ctr.bits.gpio_sel = 0x1;
2685 	} else {
2686 		op_ctr.bits.gpio_sel = 0x3;
2687 	}
2688 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2689 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2690 	    op_ctr.value)) != NXGE_OK)
2691 		goto fail;
2692 
2693 	NXGE_DELAY(1000000);
2694 
2695 	/*
2696 	 * Set XAUI link tunables from OBP if present.
2697 	 */
2698 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2699 	if (status != NXGE_OK) {
2700 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2701 		    "nxge_BCM8704_xcvr_init: Failed setting PHY tunables"));
2702 		goto fail;
2703 	}
2704 
2705 	/* Set BCM8704 Internal Loopback mode if necessary */
2706 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2707 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2708 	    != NXGE_OK)
2709 		goto fail;
2710 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2711 		pcs_ctl.bits.loopback = 1;
2712 	else
2713 		pcs_ctl.bits.loopback = 0;
2714 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2715 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2716 	    != NXGE_OK)
2717 		goto fail;
2718 
2719 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
2720 	if (status != NXGE_OK)
2721 		goto fail;
2722 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2723 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
2724 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
2725 	if (status != NXGE_OK)
2726 		goto fail;
2727 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2728 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
2729 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
2730 	if (status != NXGE_OK)
2731 		goto fail;
2732 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2733 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
2734 
2735 #ifdef	NXGE_DEBUG
2736 	/* Diagnose link issue if link is not up */
2737 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
2738 	    BCM8704_USER_ANALOG_STATUS0_REG,
2739 	    &val);
2740 	if (status != NXGE_OK)
2741 		goto fail;
2742 
2743 	status = nxge_mdio_read(nxgep, phy_port_addr,
2744 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
2745 	if (status != NXGE_OK)
2746 		goto fail;
2747 
2748 	status = nxge_mdio_read(nxgep, phy_port_addr,
2749 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
2750 	if (status != NXGE_OK)
2751 		goto fail;
2752 
2753 	status = nxge_mdio_read(nxgep, phy_port_addr,
2754 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
2755 	if (status != NXGE_OK)
2756 		goto fail;
2757 
2758 	if (val != 0x3FC) {
2759 		if ((val == 0x43BC) && (val1 != 0)) {
2760 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2761 			    "Cable not connected to peer or bad"
2762 			    " cable on port<%d>\n", portn));
2763 		} else if (val == 0x639C) {
2764 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2765 			    "Optical module (XFP) is bad or absent"
2766 			    " on port<%d>\n", portn));
2767 		}
2768 	}
2769 #endif
2770 
2771 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
2772 	    portn));
2773 	return (NXGE_OK);
2774 
2775 fail:
2776 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2777 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
2778 	    "port<%d>", nxgep->mac.portnum));
2779 	return (NXGE_ERROR);
2780 }
2781 
2782 /* Initialize the BCM 8706 Transceiver */
2783 
2784 static nxge_status_t
2785 nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
2786 {
2787 	uint8_t			phy_port_addr;
2788 	phyxs_control_t		phyxs_ctl;
2789 	pcs_control_t		pcs_ctl;
2790 	uint32_t		delay = 0;
2791 	optics_dcntr_t		op_ctr;
2792 	nxge_status_t		status = NXGE_OK;
2793 #ifdef	NXGE_DEBUG
2794 	uint8_t			portn = nxgep->mac.portnum;
2795 #endif
2796 
2797 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2798 	    portn));
2799 
2800 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
2801 
2802 	/* Reset the transceiver */
2803 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2804 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
2805 		goto fail;
2806 
2807 	phyxs_ctl.bits.reset = 1;
2808 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
2809 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
2810 		goto fail;
2811 	do {
2812 		drv_usecwait(500);
2813 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2814 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
2815 		    &phyxs_ctl.value)) != NXGE_OK)
2816 			goto fail;
2817 		delay++;
2818 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
2819 
2820 	if (delay == 100) {
2821 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
2822 		    "failed to reset Transceiver on port<%d>", portn));
2823 		status = NXGE_ERROR;
2824 		goto fail;
2825 	}
2826 
2827 	NXGE_DELAY(1000000);
2828 
2829 	/*
2830 	 * Set XAUI link tunables from OBP if present.
2831 	 */
2832 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2833 	if (status != NXGE_OK) {
2834 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2835 		    "nxge_BCM8706_xcvr_init: Failed setting PHY tunables"));
2836 		goto fail;
2837 	}
2838 
2839 	/* Set BCM8706 Internal Loopback mode if necessary */
2840 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2841 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
2842 	    != NXGE_OK)
2843 		goto fail;
2844 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
2845 		pcs_ctl.bits.loopback = 1;
2846 	else
2847 		pcs_ctl.bits.loopback = 0;
2848 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2849 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
2850 	    != NXGE_OK)
2851 		goto fail;
2852 
2853 	/* Enable Tx and Rx LEDs to be driven by traffic */
2854 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
2855 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2856 	    &op_ctr.value)) != NXGE_OK)
2857 		goto fail;
2858 	op_ctr.bits.gpio_sel = 0x3;
2859 	op_ctr.bits.res2 = 0x1;
2860 
2861 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
2862 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
2863 	    op_ctr.value)) != NXGE_OK)
2864 		goto fail;
2865 
2866 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
2867 	    portn));
2868 	return (NXGE_OK);
2869 
2870 fail:
2871 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2872 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
2873 	    "port<%d>", nxgep->mac.portnum));
2874 	return (status);
2875 }
2876 
2877 static int
2878 nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address,
2879     uint16_t reg, uint8_t *data)
2880 {
2881 	int  phy_dev, phy_reg;
2882 	uint16_t phy_data = 0;
2883 	uint16_t stat;
2884 	uint8_t count = 100;
2885 
2886 	/*
2887 	 * NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address
2888 	 * NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c
2889 	 */
2890 	phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR;
2891 	phy_reg = NLP2020_I2C_SNOOP_ADDR_REG;
2892 	phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg;
2893 	if (nxge_mdio_write(nxgep, ctrl_port,
2894 	    phy_dev, phy_reg, phy_data) != NXGE_OK)
2895 		goto fail;
2896 
2897 	phy_reg = NLP2020_I2C_SNOOP_STAT_REG;
2898 	(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat);
2899 	while ((stat != 0x01) && (count-- > 0)) {
2900 		(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
2901 		    &stat);
2902 	}
2903 	if (count) {
2904 		phy_reg = NLP2020_I2C_SNOOP_DATA_REG;
2905 		(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
2906 		    &phy_data);
2907 		*data = (phy_data >> 8);
2908 		return (0);
2909 	}
2910 fail:
2911 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2912 	    "nxge_nlp2020_i2c_read: FAILED"));
2913 	return (1);
2914 
2915 }
2916 
2917 /* Initialize the Netlogic AEL2020 Transceiver */
2918 
2919 #define	NLP_INI_WAIT	1
2920 #define	NLP_INI_STOP	0
2921 
2922 static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = {
2923 	{0x1C003, 0x3101},
2924 	{0x1CC01, 0x488a},
2925 	{0x1CB1B, 0x0200},
2926 	{0x1CB1C, 0x00f0},
2927 	{0x1CC06, 0x00e0},
2928 	{NLP_INI_STOP, 0},
2929 };
2930 
2931 static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = {
2932 
2933 	{0x1C003, 0x3101},
2934 	{0x1CD40, 0x0001},
2935 
2936 	{0x1CA12, 0x0100},
2937 	{0x1CA22, 0x0100},
2938 	{0x1CA42, 0x0100},
2939 	{0x1C20D, 0x0002},
2940 	{NLP_INI_WAIT, 100},
2941 
2942 	{0x1ff28, 0x4001},
2943 	{0x1ff2A, 0x004A},
2944 	{NLP_INI_WAIT, 500},
2945 
2946 	{0x1d000, 0x5200},
2947 	{NLP_INI_WAIT, 500},
2948 
2949 	{0x1d800, 0x4009},
2950 	{0x1d801, 0x2fff},
2951 	{0x1d802, 0x300f},
2952 	{0x1d803, 0x40aa},
2953 	{0x1d804, 0x401c},
2954 	{0x1d805, 0x401e},
2955 	{0x1d806, 0x20c5},
2956 	{0x1d807, 0x3c05},
2957 	{0x1d808, 0x6536},
2958 	{0x1d809, 0x2fe4},
2959 	{0x1d80a, 0x3dc4},
2960 	{0x1d80b, 0x6624},
2961 	{0x1d80c, 0x2ff4},
2962 	{0x1d80d, 0x3dc4},
2963 	{0x1d80e, 0x2035},
2964 	{0x1d80f, 0x30a5},
2965 	{0x1d810, 0x6524},
2966 	{0x1d811, 0x2ca2},
2967 	{0x1d812, 0x3012},
2968 	{0x1d813, 0x1002},
2969 	{0x1d814, 0x2882},
2970 	{0x1d815, 0x3022},
2971 	{0x1d816, 0x1002},
2972 	{0x1d817, 0x2972},
2973 	{0x1d818, 0x3022},
2974 	{0x1d819, 0x1002},
2975 	{0x1d81a, 0x2892},
2976 	{0x1d81b, 0x3012},
2977 	{0x1d81c, 0x1002},
2978 	{0x1d81d, 0x24e2},
2979 	{0x1d81e, 0x3022},
2980 	{0x1d81f, 0x1002},
2981 	{0x1d820, 0x27e2},
2982 	{0x1d821, 0x3012},
2983 	{0x1d822, 0x1002},
2984 	{0x1d823, 0x2422},
2985 	{0x1d824, 0x3022},
2986 	{0x1d825, 0x1002},
2987 	{0x1d826, 0x22cd},
2988 	{0x1d827, 0x301d},
2989 	{0x1d828, 0x2992},
2990 	{0x1d829, 0x3022},
2991 	{0x1d82a, 0x1002},
2992 	{0x1d82b, 0x5553},
2993 	{0x1d82c, 0x0307},
2994 	{0x1d82d, 0x2572},
2995 	{0x1d82e, 0x3022},
2996 	{0x1d82f, 0x1002},
2997 	{0x1d830, 0x21a2},
2998 	{0x1d831, 0x3012},
2999 	{0x1d832, 0x1002},
3000 	{0x1d833, 0x4016},
3001 	{0x1d834, 0x5e63},
3002 	{0x1d835, 0x0344},
3003 	{0x1d836, 0x21a2},
3004 	{0x1d837, 0x3012},
3005 	{0x1d838, 0x1002},
3006 	{0x1d839, 0x400e},
3007 	{0x1d83a, 0x2572},
3008 	{0x1d83b, 0x3022},
3009 	{0x1d83c, 0x1002},
3010 	{0x1d83d, 0x2b22},
3011 	{0x1d83e, 0x3012},
3012 	{0x1d83f, 0x1002},
3013 	{0x1d840, 0x28e2},
3014 	{0x1d841, 0x3022},
3015 	{0x1d842, 0x1002},
3016 	{0x1d843, 0x2782},
3017 	{0x1d844, 0x3022},
3018 	{0x1d845, 0x1002},
3019 	{0x1d846, 0x2fa4},
3020 	{0x1d847, 0x3dc4},
3021 	{0x1d848, 0x6624},
3022 	{0x1d849, 0x2e8b},
3023 	{0x1d84a, 0x303b},
3024 	{0x1d84b, 0x56b3},
3025 	{0x1d84c, 0x03c6},
3026 	{0x1d84d, 0x866b},
3027 	{0x1d84e, 0x400c},
3028 	{0x1d84f, 0x2782},
3029 	{0x1d850, 0x3012},
3030 	{0x1d851, 0x1002},
3031 	{0x1d852, 0x2c4b},
3032 	{0x1d853, 0x309b},
3033 	{0x1d854, 0x56b3},
3034 	{0x1d855, 0x03c3},
3035 	{0x1d856, 0x866b},
3036 	{0x1d857, 0x400c},
3037 	{0x1d858, 0x22a2},
3038 	{0x1d859, 0x3022},
3039 	{0x1d85a, 0x1002},
3040 	{0x1d85b, 0x28e2},
3041 	{0x1d85c, 0x3022},
3042 	{0x1d85d, 0x1002},
3043 	{0x1d85e, 0x2782},
3044 	{0x1d85f, 0x3022},
3045 	{0x1d860, 0x1002},
3046 	{0x1d861, 0x2fb4},
3047 	{0x1d862, 0x3dc4},
3048 	{0x1d863, 0x6624},
3049 	{0x1d864, 0x56b3},
3050 	{0x1d865, 0x03c3},
3051 	{0x1d866, 0x866b},
3052 	{0x1d867, 0x401c},
3053 	{0x1d868, 0x2c45},
3054 	{0x1d869, 0x3095},
3055 	{0x1d86a, 0x5b53},
3056 	{0x1d86b, 0x23d2},
3057 	{0x1d86c, 0x3012},
3058 	{0x1d86d, 0x13c2},
3059 	{0x1d86e, 0x5cc3},
3060 	{0x1d86f, 0x2782},
3061 	{0x1d870, 0x3012},
3062 	{0x1d871, 0x1312},
3063 	{0x1d872, 0x2b22},
3064 	{0x1d873, 0x3012},
3065 	{0x1d874, 0x1002},
3066 	{0x1d875, 0x28e2},
3067 	{0x1d876, 0x3022},
3068 	{0x1d877, 0x1002},
3069 	{0x1d878, 0x2672},
3070 	{0x1d879, 0x3022},
3071 	{0x1d87a, 0x1002},
3072 	{0x1d87b, 0x21a2},
3073 	{0x1d87c, 0x3012},
3074 	{0x1d87d, 0x1002},
3075 	{0x1d87e, 0x628f},
3076 	{0x1d87f, 0x2985},
3077 	{0x1d880, 0x33a5},
3078 	{0x1d881, 0x2782},
3079 	{0x1d882, 0x3022},
3080 	{0x1d883, 0x1002},
3081 	{0x1d884, 0x5653},
3082 	{0x1d885, 0x03d2},
3083 	{0x1d886, 0x401e},
3084 	{0x1d887, 0x6f72},
3085 	{0x1d888, 0x1002},
3086 	{0x1d889, 0x628f},
3087 	{0x1d88a, 0x2304},
3088 	{0x1d88b, 0x3c84},
3089 	{0x1d88c, 0x6436},
3090 	{0x1d88d, 0xdff4},
3091 	{0x1d88e, 0x6436},
3092 	{0x1d88f, 0x2ff5},
3093 	{0x1d890, 0x3005},
3094 	{0x1d891, 0x8656},
3095 	{0x1d892, 0xdfba},
3096 	{0x1d893, 0x56a3},
3097 	{0x1d894, 0xd05a},
3098 	{0x1d895, 0x29e2},
3099 	{0x1d896, 0x3012},
3100 	{0x1d897, 0x1392},
3101 	{0x1d898, 0xd05a},
3102 	{0x1d899, 0x56a3},
3103 	{0x1d89a, 0xdfba},
3104 	{0x1d89b, 0x0383},
3105 	{0x1d89c, 0x6f72},
3106 	{0x1d89d, 0x1002},
3107 	{0x1d89e, 0x2a64},
3108 	{0x1d89f, 0x3014},
3109 	{0x1d8a0, 0x2005},
3110 	{0x1d8a1, 0x3d75},
3111 	{0x1d8a2, 0xc451},
3112 	{0x1d8a3, 0x2a42},
3113 	{0x1d8a4, 0x3022},
3114 	{0x1d8a5, 0x1002},
3115 	{0x1d8a6, 0x178c},
3116 	{0x1d8a7, 0x1898},
3117 	{0x1d8a8, 0x19a4},
3118 	{0x1d8a9, 0x1ab0},
3119 	{0x1d8aa, 0x1bbc},
3120 	{0x1d8ab, 0x1cc8},
3121 	{0x1d8ac, 0x1dd3},
3122 	{0x1d8ad, 0x1ede},
3123 	{0x1d8ae, 0x1fe9},
3124 	{0x1d8af, 0x20f4},
3125 	{0x1d8b0, 0x21ff},
3126 	{0x1d8b1, 0x0000},
3127 	{0x1d8b2, 0x27e1},
3128 	{0x1d8b3, 0x3021},
3129 	{0x1d8b4, 0x1001},
3130 	{0x1d8b5, 0xc620},
3131 	{0x1d8b6, 0x0000},
3132 	{0x1d8b7, 0xc621},
3133 	{0x1d8b8, 0x0000},
3134 	{0x1d8b9, 0xc622},
3135 	{0x1d8ba, 0x00e2},
3136 	{0x1d8bb, 0xc623},
3137 	{0x1d8bc, 0x007f},
3138 	{0x1d8bd, 0xc624},
3139 	{0x1d8be, 0x00ce},
3140 	{0x1d8bf, 0xc625},
3141 	{0x1d8c0, 0x0000},
3142 	{0x1d8c1, 0xc627},
3143 	{0x1d8c2, 0x0000},
3144 	{0x1d8c3, 0xc628},
3145 	{0x1d8c4, 0x0000},
3146 	{0x1d8c5, 0xc90a},
3147 	{0x1d8c6, 0x3a7c},
3148 	{0x1d8c7, 0xc62c},
3149 	{0x1d8c8, 0x0000},
3150 	{0x1d8c9, 0x0000},
3151 	{0x1d8ca, 0x27e1},
3152 	{0x1d8cb, 0x3021},
3153 	{0x1d8cc, 0x1001},
3154 	{0x1d8cd, 0xc502},
3155 	{0x1d8ce, 0x53ac},
3156 	{0x1d8cf, 0xc503},
3157 	{0x1d8d0, 0x2cd3},
3158 	{0x1d8d1, 0xc600},
3159 	{0x1d8d2, 0x2a6e},
3160 	{0x1d8d3, 0xc601},
3161 	{0x1d8d4, 0x2a2c},
3162 	{0x1d8d5, 0xc605},
3163 	{0x1d8d6, 0x5557},
3164 	{0x1d8d7, 0xc60c},
3165 	{0x1d8d8, 0x5400},
3166 	{0x1d8d9, 0xc710},
3167 	{0x1d8da, 0x0700},
3168 	{0x1d8db, 0xc711},
3169 	{0x1d8dc, 0x0f06},
3170 	{0x1d8dd, 0xc718},
3171 	{0x1d8de, 0x0700},
3172 	{0x1d8df, 0xc719},
3173 	{0x1d8e0, 0x0f06},
3174 	{0x1d8e1, 0xc720},
3175 	{0x1d8e2, 0x4700},
3176 	{0x1d8e3, 0xc721},
3177 	{0x1d8e4, 0x0f06},
3178 	{0x1d8e5, 0xc728},
3179 	{0x1d8e6, 0x0700},
3180 	{0x1d8e7, 0xc729},
3181 	{0x1d8e8, 0x1207},
3182 	{0x1d8e9, 0xc801},
3183 	{0x1d8ea, 0x7f50},
3184 	{0x1d8eb, 0xc802},
3185 	{0x1d8ec, 0x7760},
3186 	{0x1d8ed, 0xc803},
3187 	{0x1d8ee, 0x7fce},
3188 	{0x1d8ef, 0xc804},
3189 	{0x1d8f0, 0x520e},
3190 	{0x1d8f1, 0xc805},
3191 	{0x1d8f2, 0x5c11},
3192 	{0x1d8f3, 0xc806},
3193 	{0x1d8f4, 0x3c51},
3194 	{0x1d8f5, 0xc807},
3195 	{0x1d8f6, 0x4061},
3196 	{0x1d8f7, 0xc808},
3197 	{0x1d8f8, 0x49c1},
3198 	{0x1d8f9, 0xc809},
3199 	{0x1d8fa, 0x3840},
3200 	{0x1d8fb, 0xc80a},
3201 	{0x1d8fc, 0x0000},
3202 	{0x1d8fd, 0xc821},
3203 	{0x1d8fe, 0x0002},
3204 	{0x1d8ff, 0xc822},
3205 	{0x1d900, 0x0046},
3206 	{0x1d901, 0xc844},
3207 	{0x1d902, 0x182f},
3208 	{0x1d903, 0xc849},
3209 	{0x1d904, 0x0400},
3210 	{0x1d905, 0xc84a},
3211 	{0x1d906, 0x0002},
3212 	{0x1d907, 0xc013},
3213 	{0x1d908, 0xf341},
3214 	{0x1d909, 0xc084},
3215 	{0x1d90a, 0x0030},
3216 	{0x1d90b, 0xc904},
3217 	{0x1d90c, 0x1401},
3218 	{0x1d90d, 0xcb0c},
3219 	{0x1d90e, 0x0004},
3220 	{0x1d90f, 0xcb0e},
3221 	{0x1d910, 0xa00a},
3222 	{0x1d911, 0xcb0f},
3223 	{0x1d912, 0xc0c0},
3224 	{0x1d913, 0xcb10},
3225 	{0x1d914, 0xc0c0},
3226 	{0x1d915, 0xcb11},
3227 	{0x1d916, 0x00a0},
3228 	{0x1d917, 0xcb12},
3229 	{0x1d918, 0x0007},
3230 	{0x1d919, 0xc241},
3231 	{0x1d91a, 0xa000},
3232 	{0x1d91b, 0xc243},
3233 	{0x1d91c, 0x7fe0},
3234 	{0x1d91d, 0xc604},
3235 	{0x1d91e, 0x000e},
3236 	{0x1d91f, 0xc609},
3237 	{0x1d920, 0x00f5},
3238 	{0x1d921, 0x0c61},
3239 	{0x1d922, 0x000e},
3240 	{0x1d923, 0xc660},
3241 	{0x1d924, 0x9600},
3242 	{0x1d925, 0xc687},
3243 	{0x1d926, 0x0004},
3244 	{0x1d927, 0xc60a},
3245 	{0x1d928, 0x04f5},
3246 	{0x1d929, 0x0000},
3247 	{0x1d92a, 0x27e1},
3248 	{0x1d92b, 0x3021},
3249 	{0x1d92c, 0x1001},
3250 	{0x1d92d, 0xc620},
3251 	{0x1d92e, 0x14e5},
3252 	{0x1d92f, 0xc621},
3253 	{0x1d930, 0xc53d},
3254 	{0x1d931, 0xc622},
3255 	{0x1d932, 0x3cbe},
3256 	{0x1d933, 0xc623},
3257 	{0x1d934, 0x4452},
3258 	{0x1d935, 0xc624},
3259 	{0x1d936, 0xc5c5},
3260 	{0x1d937, 0xc625},
3261 	{0x1d938, 0xe01e},
3262 	{0x1d939, 0xc627},
3263 	{0x1d93a, 0x0000},
3264 	{0x1d93b, 0xc628},
3265 	{0x1d93c, 0x0000},
3266 	{0x1d93d, 0xc62c},
3267 	{0x1d93e, 0x0000},
3268 	{0x1d93f, 0xc90a},
3269 	{0x1d940, 0x3a7c},
3270 	{0x1d941, 0x0000},
3271 	{0x1d942, 0x2b84},
3272 	{0x1d943, 0x3c74},
3273 	{0x1d944, 0x6435},
3274 	{0x1d945, 0xdff4},
3275 	{0x1d946, 0x6435},
3276 	{0x1d947, 0x2806},
3277 	{0x1d948, 0x3006},
3278 	{0x1d949, 0x8565},
3279 	{0x1d94a, 0x2b24},
3280 	{0x1d94b, 0x3c24},
3281 	{0x1d94c, 0x6436},
3282 	{0x1d94d, 0x1002},
3283 	{0x1d94e, 0x2b24},
3284 	{0x1d94f, 0x3c24},
3285 	{0x1d950, 0x6436},
3286 	{0x1d951, 0x4045},
3287 	{0x1d952, 0x8656},
3288 	{0x1d953, 0x5663},
3289 	{0x1d954, 0x0302},
3290 	{0x1d955, 0x401e},
3291 	{0x1d956, 0x1002},
3292 	{0x1d957, 0x2017},
3293 	{0x1d958, 0x3b17},
3294 	{0x1d959, 0x2084},
3295 	{0x1d95a, 0x3c14},
3296 	{0x1d95b, 0x6724},
3297 	{0x1d95c, 0x2807},
3298 	{0x1d95d, 0x31a7},
3299 	{0x1d95e, 0x20c4},
3300 	{0x1d95f, 0x3c24},
3301 	{0x1d960, 0x6724},
3302 	{0x1d961, 0x2ff7},
3303 	{0x1d962, 0x30f7},
3304 	{0x1d963, 0x20c4},
3305 	{0x1d964, 0x3c04},
3306 	{0x1d965, 0x6724},
3307 	{0x1d966, 0x1002},
3308 	{0x1d967, 0x2807},
3309 	{0x1d968, 0x3187},
3310 	{0x1d969, 0x20c4},
3311 	{0x1d96a, 0x3c24},
3312 	{0x1d96b, 0x6724},
3313 	{0x1d96c, 0x2fe4},
3314 	{0x1d96d, 0x3dc4},
3315 	{0x1d96e, 0x6437},
3316 	{0x1d96f, 0x20c4},
3317 	{0x1d970, 0x3c04},
3318 	{0x1d971, 0x6724},
3319 	{0x1d972, 0x2017},
3320 	{0x1d973, 0x3d17},
3321 	{0x1d974, 0x2084},
3322 	{0x1d975, 0x3c14},
3323 	{0x1d976, 0x6724},
3324 	{0x1d977, 0x1002},
3325 	{0x1d978, 0x24f4},
3326 	{0x1d979, 0x3c64},
3327 	{0x1d97a, 0x6436},
3328 	{0x1d97b, 0xdff4},
3329 	{0x1d97c, 0x6436},
3330 	{0x1d97d, 0x1002},
3331 	{0x1d97e, 0x2006},
3332 	{0x1d97f, 0x3d76},
3333 	{0x1d980, 0xc161},
3334 	{0x1d981, 0x6134},
3335 	{0x1d982, 0x6135},
3336 	{0x1d983, 0x5443},
3337 	{0x1d984, 0x0303},
3338 	{0x1d985, 0x6524},
3339 	{0x1d986, 0x00fb},
3340 	{0x1d987, 0x1002},
3341 	{0x1d988, 0x20d4},
3342 	{0x1d989, 0x3c24},
3343 	{0x1d98a, 0x2025},
3344 	{0x1d98b, 0x3005},
3345 	{0x1d98c, 0x6524},
3346 	{0x1d98d, 0x1002},
3347 	{0x1d98e, 0xd019},
3348 	{0x1d98f, 0x2104},
3349 	{0x1d990, 0x3c24},
3350 	{0x1d991, 0x2105},
3351 	{0x1d992, 0x3805},
3352 	{0x1d993, 0x6524},
3353 	{0x1d994, 0xdff4},
3354 	{0x1d995, 0x4005},
3355 	{0x1d996, 0x6524},
3356 	{0x1d997, 0x2e8d},
3357 	{0x1d998, 0x303d},
3358 	{0x1d999, 0x2408},
3359 	{0x1d99a, 0x35d8},
3360 	{0x1d99b, 0x5dd3},
3361 	{0x1d99c, 0x0307},
3362 	{0x1d99d, 0x8887},
3363 	{0x1d99e, 0x63a7},
3364 	{0x1d99f, 0x8887},
3365 	{0x1d9a0, 0x63a7},
3366 	{0x1d9a1, 0xdffd},
3367 	{0x1d9a2, 0x00f9},
3368 	{0x1d9a3, 0x1002},
3369 	{0x1d9a4, 0x866a},
3370 	{0x1d9a5, 0x6138},
3371 	{0x1d9a6, 0x5883},
3372 	{0x1d9a7, 0x2b42},
3373 	{0x1d9a8, 0x3022},
3374 	{0x1d9a9, 0x1302},
3375 	{0x1d9aa, 0x2ff7},
3376 	{0x1d9ab, 0x3007},
3377 	{0x1d9ac, 0x8785},
3378 	{0x1d9ad, 0xb887},
3379 	{0x1d9ae, 0x8786},
3380 	{0x1d9af, 0xb8c6},
3381 	{0x1d9b0, 0x5a53},
3382 	{0x1d9b1, 0x2a52},
3383 	{0x1d9b2, 0x3022},
3384 	{0x1d9b3, 0x13c2},
3385 	{0x1d9b4, 0x2474},
3386 	{0x1d9b5, 0x3c84},
3387 	{0x1d9b6, 0x64d7},
3388 	{0x1d9b7, 0x64d7},
3389 	{0x1d9b8, 0x2ff5},
3390 	{0x1d9b9, 0x3c05},
3391 	{0x1d9ba, 0x8757},
3392 	{0x1d9bb, 0xb886},
3393 	{0x1d9bc, 0x9767},
3394 	{0x1d9bd, 0x67c4},
3395 	{0x1d9be, 0x6f72},
3396 	{0x1d9bf, 0x1002},
3397 	{0x1d9c0, 0x0000},
3398 	{0x1d080, 0x0100},
3399 	{0x1d092, 0x0000},
3400 	{NLP_INI_STOP, 0},
3401 };
3402 
3403 static nxge_status_t
3404 nxge_nlp2020_xcvr_init(p_nxge_t nxgep)
3405 {
3406 	uint8_t			phy_port_addr;
3407 	nxge_status_t		status = NXGE_OK;
3408 	uint16_t		ctrl_reg, rst_val, pmd_ctl, rx_los;
3409 	int			i = 0, count = 1000;
3410 
3411 	uint8_t			connector = 0, len, lpm;
3412 	p_nxge_nlp_initseq_t	initseq;
3413 	uint16_t		dev, reg, val;
3414 
3415 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: "
3416 	    "port<%d>, phyaddr[0x%x]", nxgep->mac.portnum,
3417 	    nxgep->statsp->mac_stats.xcvr_portn));
3418 
3419 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
3420 
3421 	/* Reset the transceiver */
3422 	rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST;
3423 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3424 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val))
3425 	    != NXGE_OK)
3426 		goto fail;
3427 	while ((count--) && (ctrl_reg & rst_val)) {
3428 		drv_usecwait(1000);
3429 		(void) nxge_mdio_read(nxgep, phy_port_addr,
3430 		    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg);
3431 	}
3432 	if (count == 0) {
3433 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: "
3434 		    "PMA_PMD reset failed"));
3435 		goto fail;
3436 	}
3437 
3438 	/* Set loopback mode if required */
3439 	/* Set PMA PMD system loopback */
3440 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
3441 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl))
3442 	    != NXGE_OK)
3443 		goto fail;
3444 
3445 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
3446 		pmd_ctl |= 0x0001;
3447 	else
3448 		pmd_ctl &= 0xfffe;
3449 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3450 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl))
3451 	    != NXGE_OK)
3452 		goto fail;
3453 
3454 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: "
3455 	    "setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl));
3456 
3457 	/* Check connector details using I2c */
3458 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3459 	    QSFP_MSA_CONN_REG, &connector) == 1) {
3460 		goto fail;
3461 	}
3462 
3463 	switch (connector) {
3464 	case SFPP_FIBER:
3465 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3466 		    "nxge_nlp2020_xcvr_init: SFPP_FIBER detected"));
3467 		initseq = nlp2020_revC_fiber_init;
3468 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3469 		break;
3470 	case QSFP_FIBER:
3471 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3472 		    "nxge_nlp2020_xcvr_init: QSFP_FIBER detected"));
3473 		initseq = nlp2020_revC_fiber_init;
3474 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3475 		break;
3476 	case QSFP_COPPER_TWINAX:
3477 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3478 		    "nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/"
3479 		    "SFPP_COPPER_TWINAX detected"));
3480 
3481 		initseq = nlp2020_revC_copper_init;
3482 		nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M;
3483 		break;
3484 	default:
3485 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3486 		    "nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected",
3487 		    "...setting to QSFP_FIBER",
3488 		    connector));
3489 		initseq = nlp2020_revC_fiber_init;
3490 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
3491 		break;
3492 	}
3493 
3494 	/* Run appropriate init sequence */
3495 	for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) {
3496 		dev = initseq[i].dev_reg >> 16;
3497 		reg = initseq[i].dev_reg & 0xffff;
3498 		val = initseq[i].val;
3499 
3500 		if (reg == NLP_INI_WAIT) {
3501 			drv_usecwait(1000 * val);
3502 		} else {
3503 			if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3504 			    dev, reg, val)) != NXGE_OK)
3505 				goto fail;
3506 		}
3507 	}
3508 
3509 	/* rx_los inversion */
3510 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
3511 	    NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK)
3512 			goto fail;
3513 
3514 	rx_los &= ~(NLP2020_RXLOS_ACT_H);
3515 
3516 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
3517 	    NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK)
3518 			goto fail;
3519 
3520 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3521 	    QSFP_MSA_LEN_REG, &len) == 1) {
3522 		goto fail;
3523 	}
3524 
3525 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
3526 	    QSFP_MSA_LPM_REG, &lpm) == 1) {
3527 		goto fail;
3528 	}
3529 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3530 	    "nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm));
3531 
3532 	if (connector == QSFP_COPPER_TWINAX) {
3533 		if (len >= 7) {
3534 			nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE;
3535 			/* enable pre-emphasis */
3536 			(void) nxge_mdio_write(nxgep, phy_port_addr,
3537 			    NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG,
3538 			    NLP2020_TX_DRV_CTL1_PREEMP_EN);
3539 			/* write emphasis value */
3540 			(void) nxge_mdio_write(nxgep, phy_port_addr,
3541 			    NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG,
3542 			    NLP2020_TX_DRV_CTL2_EMP_VAL);
3543 			/* stop microcontroller */
3544 			(void) nxge_mdio_write(nxgep, phy_port_addr,
3545 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
3546 			    NLP2020_UC_CTL_STOP);
3547 			/* reset program counter */
3548 			(void) nxge_mdio_write(nxgep, phy_port_addr,
3549 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG,
3550 			    NLP2020_UC_PC_START_VAL);
3551 			/* start microcontroller */
3552 			(void) nxge_mdio_write(nxgep, phy_port_addr,
3553 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
3554 			    NLP2020_UC_CTL_START);
3555 		}
3556 	}
3557 	if (lpm & QSFP_MSA_LPM_HIGH) {
3558 		/* enable high power mode */
3559 		(void) nxge_mdio_write(nxgep, phy_port_addr,
3560 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
3561 		    NLP2020_GPIO_ACT);
3562 	} else {
3563 		/* revert to low power mode */
3564 		(void) nxge_mdio_write(nxgep, phy_port_addr,
3565 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
3566 		    NLP2020_GPIO_INACT);
3567 	}
3568 
3569 	/*
3570 	 * Set XAUI link tunables from OBP if present.
3571 	 */
3572 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
3573 	if (status != NXGE_OK) {
3574 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3575 		    "nxge_nlp2020_xcvr_init: Failed setting PHY tunables"));
3576 		goto fail;
3577 	}
3578 
3579 	/* It takes ~2s for EDC to settle */
3580 	drv_usecwait(2000000);
3581 
3582 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: "
3583 	    "port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr));
3584 
3585 	return (NXGE_OK);
3586 
3587 fail:
3588 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3589 	    "nxge_nlp2020_xcvr_init: failed to initialize transceiver for "
3590 	    "port<%d>", nxgep->mac.portnum));
3591 	return (status);
3592 }
3593 
3594 static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep)
3595 {
3596 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3597 	uint32_t	pcs_id = 0;
3598 	uint32_t	pma_pmd_id = 0;
3599 	uint8_t		xcvr_addr =  nxgep->nxge_hw_p->xcvr_addr[portn];
3600 
3601 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr);
3602 	pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr);
3603 
3604 	if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) ||
3605 	    ((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) {
3606 		return (B_TRUE);
3607 	} else {
3608 		return (B_FALSE);
3609 	}
3610 }
3611 
3612 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep)
3613 {
3614 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3615 	uint8_t xcvr_addr =  nxgep->nxge_hw_p->xcvr_addr[portn];
3616 	uint8_t	connector = 0;
3617 
3618 	(void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR,
3619 	    QSFP_MSA_CONN_REG, &connector);
3620 
3621 	return (connector);
3622 }
3623 
3624 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep)
3625 {
3626 	uint8_t connector = 0;
3627 
3628 	connector = nxge_get_nlp2020_connector_type(nxgep);
3629 
3630 	switch (connector) {
3631 	case SFPP_FIBER:
3632 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3633 		    "nxge_set_nlp2020_param: SFPP_FIBER detected"));
3634 		nxgep->mac.portmode = PORT_10G_FIBER;
3635 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3636 		break;
3637 	case QSFP_FIBER:
3638 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3639 		    "nxge_set_nlp2020_param: QSFP_FIBER detected"));
3640 		nxgep->mac.portmode = PORT_10G_FIBER;
3641 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3642 		break;
3643 	case QSFP_COPPER_TWINAX:
3644 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3645 		    "nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/"
3646 		    "SFPP_COPPER_TWINAX detected"));
3647 		nxgep->mac.portmode = PORT_10G_COPPER;
3648 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3649 		break;
3650 	default:
3651 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3652 		    "nxge_set_nlp2020_param: Unknown type [0x%x] detected"
3653 		    "...setting to QSFP_FIBER",
3654 		    connector));
3655 		nxgep->mac.portmode = PORT_10G_FIBER;
3656 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3657 		break;
3658 	}
3659 
3660 	return (NXGE_OK);
3661 }
3662 
3663 #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
3664 
3665 #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
3666 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
3667 
3668 #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
3669 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
3670 
3671 
3672 static void
3673 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
3674 {
3675 	uint16_t	value;
3676 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3677 
3678 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
3679 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
3680 		value &= ~MRVL_88X2011_LED_BLK_MASK;
3681 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
3682 		(void) nxge_mdio_write(nxgep, phy,
3683 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
3684 		    value);
3685 	}
3686 }
3687 
3688 static nxge_status_t
3689 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
3690 {
3691 	nxge_status_t	status;
3692 	pcs_control_t	pcs_ctl;
3693 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3694 
3695 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3696 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
3697 
3698 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
3699 		pcs_ctl.bits.loopback = 1;
3700 	else
3701 		pcs_ctl.bits.loopback = 0;
3702 
3703 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3704 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
3705 
3706 fail:
3707 	return (status);
3708 }
3709 
3710 
3711 static void
3712 nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
3713 {
3714 	uint16_t	val2;
3715 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
3716 
3717 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
3718 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
3719 	    MRVL_88X2011_LED_CTL_MASK);
3720 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
3721 
3722 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
3723 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
3724 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3725 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
3726 	}
3727 }
3728 
3729 
3730 static nxge_status_t
3731 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
3732 {
3733 	uint8_t		phy;
3734 	nxge_status_t	status;
3735 	uint16_t	clk;
3736 
3737 	phy = nxgep->statsp->mac_stats.xcvr_portn;
3738 
3739 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3740 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
3741 	    nxgep->mac.portnum, phy));
3742 
3743 	/* Set LED functions	*/
3744 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
3745 	/* PCS activity */
3746 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
3747 
3748 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3749 	    MRVL_88X2011_GEN_CTL, &clk);
3750 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
3751 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
3752 	    MRVL_88X2011_GEN_CTL, clk);
3753 
3754 	/* Set internal loopback mode if necessary */
3755 
3756 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
3757 
3758 	/* Enable PMD */
3759 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
3760 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
3761 
3762 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
3763 
3764 fail:
3765 	return (status);
3766 }
3767 
3768 
3769 
3770 /* Initialize the 10G Transceiver */
3771 
3772 static nxge_status_t
3773 nxge_10G_xcvr_init(p_nxge_t nxgep)
3774 {
3775 	p_nxge_stats_t		statsp;
3776 	p_nxge_param_t		param_arr = nxgep->param_arr;
3777 	nxge_status_t		status = NXGE_OK;
3778 #ifdef	NXGE_DEBUG
3779 	uint8_t			portn = nxgep->mac.portnum;
3780 #endif
3781 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
3782 	    portn));
3783 
3784 	statsp = nxgep->statsp;
3785 
3786 	/* Disable Link LEDs, with or without PHY */
3787 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
3788 		goto done;
3789 
3790 	/* Skip MDIO, if PHY absent */
3791 	if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
3792 		goto done;
3793 	}
3794 
3795 	/* Set Clause 45 */
3796 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
3797 
3798 	switch (nxgep->chip_id) {
3799 	case BCM8704_CHIP_ID:
3800 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3801 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
3802 		status = nxge_BCM8704_xcvr_init(nxgep);
3803 		break;
3804 	case BCM8706_CHIP_ID:
3805 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3806 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
3807 		status = nxge_BCM8706_xcvr_init(nxgep);
3808 		break;
3809 	case MRVL88X201X_CHIP_ID:
3810 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3811 		    "Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id));
3812 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
3813 		break;
3814 	case NLP2020_CHIP_ID:
3815 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
3816 		    "Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id));
3817 		status = nxge_nlp2020_xcvr_init(nxgep);
3818 		break;
3819 	default:
3820 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
3821 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
3822 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
3823 		goto fail;
3824 	}
3825 
3826 	if (status != NXGE_OK) {
3827 		goto fail;
3828 	}
3829 done:
3830 	statsp->mac_stats.cap_10gfdx = 1;
3831 	statsp->mac_stats.lp_cap_10gfdx = 1;
3832 	statsp->mac_stats.adv_cap_asmpause =
3833 	    param_arr[param_anar_asmpause].value;
3834 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3835 
3836 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
3837 	    portn));
3838 	return (NXGE_OK);
3839 
3840 fail:
3841 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3842 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
3843 	    "port<%d>", nxgep->mac.portnum));
3844 	return (NXGE_ERROR);
3845 }
3846 
3847 /* Initialize the 1G copper (BCM 5464) Transceiver */
3848 
3849 static nxge_status_t
3850 nxge_1G_xcvr_init(p_nxge_t nxgep)
3851 {
3852 	p_nxge_param_t		param_arr = nxgep->param_arr;
3853 	p_nxge_stats_t		statsp = nxgep->statsp;
3854 	nxge_status_t		status = NXGE_OK;
3855 
3856 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
3857 		statsp->mac_stats.cap_1000fdx =
3858 		    param_arr[param_anar_1000fdx].value;
3859 		goto done;
3860 	}
3861 
3862 	/* Set Clause 22 */
3863 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
3864 
3865 	/* Set capability flags */
3866 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
3867 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
3868 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
3869 		statsp->mac_stats.cap_100fdx =
3870 		    param_arr[param_anar_100fdx].value;
3871 		statsp->mac_stats.cap_10fdx =
3872 		    param_arr[param_anar_10fdx].value;
3873 	}
3874 
3875 	status = nxge_mii_xcvr_init(nxgep);
3876 done:
3877 	return (status);
3878 }
3879 
3880 /*
3881  * Although the Teranetics copper transceiver (TN1010) does not need
3882  * to be initialized by the driver for passing packets, this funtion
3883  * initializes the members of nxgep->statsp->mac_stats struct for
3884  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
3885  * It also configures the TN1010 for PHY loopback to support SunVTS.
3886  *
3887  * TN1010 only has the option to disable advertisement for the 10G
3888  * mode. So we can set it to either Dual Mode or 1G Only mode but
3889  * can't set it to 10G Only mode.
3890  *
3891  * ndd -set command can set the following 6 speed/duplex related parameters.
3892  *
3893  * ----------------------------------------------------------------
3894  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
3895  * ----------------------------------------------------------------
3896  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
3897  * adv_10gfdx_cap
3898  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
3899  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
3900  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
3901  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
3902  * ----------------------------------------------------------------
3903  */
3904 static nxge_status_t
3905 nxge_tn1010_xcvr_init(p_nxge_t nxgep)
3906 {
3907 	p_nxge_param_t		param_arr;
3908 	p_nxge_stats_t		statsp;
3909 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
3910 	uint16_t		speed;
3911 	uint8_t			phy_port_addr;
3912 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3913 	int			status = NXGE_OK;
3914 
3915 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
3916 
3917 	param_arr	= nxgep->param_arr;
3918 	statsp		= nxgep->statsp;
3919 
3920 	/*
3921 	 * Initialize the xcvr statistics which are NOT controlled by ndd
3922 	 */
3923 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
3924 	statsp->mac_stats.cap_100T4    = 0;
3925 
3926 	/*
3927 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
3928 	 * that function nxge_check_tn1010_link repeatedly invoked by the
3929 	 * timer will update link_speed real time.
3930 	 */
3931 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
3932 		goto fail;
3933 	}
3934 	if (speed == TN1010_SPEED_1G) {
3935 		statsp->mac_stats.cap_10gfdx = 0;
3936 	} else {
3937 		statsp->mac_stats.cap_10gfdx = 1;
3938 	}
3939 
3940 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
3941 	statsp->mac_stats.cap_1000fdx  = 1;
3942 
3943 	/* TN1010 is not able to operate in the following states */
3944 	statsp->mac_stats.cap_1000hdx  = 0;
3945 	statsp->mac_stats.cap_100fdx   = 0;
3946 	statsp->mac_stats.cap_100hdx   = 0;
3947 	statsp->mac_stats.cap_10fdx    = 0;
3948 	statsp->mac_stats.cap_10hdx    = 0;
3949 
3950 	/* param_anar_pause can be modified by ndd -set */
3951 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
3952 
3953 	/*
3954 	 * The following 4 lines actually overwrites what ever the ndd command
3955 	 * has set. For example, by command
3956 	 *	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
3957 	 * we could set param_arr[param_autoneg].value to n.  However, because
3958 	 * here we assign constants to these parameters, whatever we set with
3959 	 * the "ndd -set" command will be replaced. So command
3960 	 *	kstat nxge:X | grep param
3961 	 * will always show those constant values.  In other words, the
3962 	 * "ndd -set" command can NOT change the values of these 4 parameters
3963 	 * even though the command appears to be successful.
3964 	 *
3965 	 * Note: TN1010 auto negotiation is always enabled.
3966 	 */
3967 	statsp->mac_stats.adv_cap_autoneg
3968 	    = param_arr[param_autoneg].value = 1;
3969 	statsp->mac_stats.adv_cap_1000fdx
3970 	    = param_arr[param_anar_1000fdx].value = 1;
3971 	statsp->mac_stats.adv_cap_100fdx
3972 	    = param_arr[param_anar_100fdx].value = 0;
3973 	statsp->mac_stats.adv_cap_10fdx
3974 	    = param_arr[param_anar_10fdx].value = 0;
3975 
3976 	/*
3977 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
3978 	 * defined in nxge_param_arr[], therefore they are not seen by the
3979 	 * "ndd -get" command and can not be changed by ndd.  We just set
3980 	 * them (both ndd param and kstat values) to constant 0 because TN1010
3981 	 * does not support those speeds.
3982 	 */
3983 	statsp->mac_stats.adv_cap_100T4
3984 	    = param_arr[param_anar_100T4].value = 0;
3985 	statsp->mac_stats.adv_cap_1000hdx
3986 	    = param_arr[param_anar_1000hdx].value = 0;
3987 	statsp->mac_stats.adv_cap_100hdx
3988 	    = param_arr[param_anar_100hdx].value = 0;
3989 	statsp->mac_stats.adv_cap_10hdx
3990 	    = param_arr[param_anar_10hdx].value = 0;
3991 
3992 	/*
3993 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
3994 	 * by ndd
3995 	 */
3996 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
3997 
3998 	/*
3999 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
4000 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
4001 	 * "ndd -get" command and can not be changed by ndd. Here we do not
4002 	 * assign a constant to it so the default value defined in
4003 	 * nxge_param_arr[] will be used to set the parameter and
4004 	 * will be shown by the kstat.
4005 	 */
4006 	statsp->mac_stats.adv_cap_asmpause
4007 	    = param_arr[param_anar_asmpause].value;
4008 
4009 	/*
4010 	 * Initialize the link statistics.
4011 	 */
4012 	statsp->mac_stats.link_T4 = 0;
4013 	statsp->mac_stats.link_asmpause = 0;
4014 	statsp->mac_stats.link_pause = 0;
4015 	if (speed == TN1010_SPEED_1G) {
4016 		statsp->mac_stats.link_speed = 1000;
4017 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
4018 		statsp->mac_stats.link_up = 1;
4019 	} else {
4020 		statsp->mac_stats.link_speed = 10000;
4021 		statsp->mac_stats.link_duplex = 2;
4022 		statsp->mac_stats.link_up = 1;
4023 	}
4024 
4025 	/*
4026 	 * Because TN1010 does not have a link partner register, to
4027 	 * figure out the link partner's capabilities is tricky. Here we
4028 	 * just set the kstat based on our knowledge about the partner
4029 	 * (The partner must support auto-neg because auto-negotiation
4030 	 * has completed, it must support 1G or 10G because that is the
4031 	 * negotiated speed we are using.)
4032 	 *
4033 	 * Note: Current kstat does not show lp_cap_10gfdx and
4034 	 *	lp_cap_10ghdx.
4035 	 */
4036 	if (speed == TN1010_SPEED_1G) {
4037 		statsp->mac_stats.lp_cap_1000fdx  = 1;
4038 		statsp->mac_stats.lp_cap_10gfdx   = 0;
4039 	} else {
4040 		statsp->mac_stats.lp_cap_1000fdx  = 0;
4041 		statsp->mac_stats.lp_cap_10gfdx   = 1;
4042 	}
4043 	statsp->mac_stats.lp_cap_10ghdx   = 0;
4044 	statsp->mac_stats.lp_cap_1000hdx  = 0;
4045 	statsp->mac_stats.lp_cap_100fdx   = 0;
4046 	statsp->mac_stats.lp_cap_100hdx   = 0;
4047 	statsp->mac_stats.lp_cap_10fdx    = 0;
4048 	statsp->mac_stats.lp_cap_10hdx    = 0;
4049 	statsp->mac_stats.lp_cap_10gfdx   = 0;
4050 	statsp->mac_stats.lp_cap_10ghdx   = 0;
4051 	statsp->mac_stats.lp_cap_100T4    = 0;
4052 	statsp->mac_stats.lp_cap_autoneg  = 1;
4053 	statsp->mac_stats.lp_cap_asmpause = 0;
4054 	statsp->mac_stats.lp_cap_pause    = 0;
4055 
4056 	/* Handle PHY loopback for SunVTS loopback test */
4057 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
4058 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
4059 
4060 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
4061 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
4062 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
4063 		goto fail;
4064 	}
4065 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
4066 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
4067 		tn1010_pcs_ctrl.bits.loopback = 1;
4068 	} else {
4069 		tn1010_pcs_ctrl.bits.loopback = 0;
4070 	}
4071 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
4072 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
4073 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
4074 		goto fail;
4075 	}
4076 
4077 	statsp->mac_stats.xcvr_inits++;
4078 
4079 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4080 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
4081 	return (status);
4082 fail:
4083 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4084 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
4085 	return (status);
4086 }
4087 
4088 /* Initialize transceiver */
4089 
4090 nxge_status_t
4091 nxge_xcvr_init(p_nxge_t nxgep)
4092 {
4093 	p_nxge_stats_t		statsp;
4094 #ifdef	NXGE_DEBUG
4095 	uint8_t			portn;
4096 #endif
4097 
4098 	nxge_status_t		status = NXGE_OK;
4099 #ifdef	NXGE_DEBUG
4100 	portn = nxgep->mac.portnum;
4101 #endif
4102 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
4103 	statsp = nxgep->statsp;
4104 
4105 	/*
4106 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
4107 	 * modify mac_stats.
4108 	 */
4109 	statsp->mac_stats.cap_autoneg = 0;
4110 	statsp->mac_stats.cap_100T4 = 0;
4111 	statsp->mac_stats.cap_100fdx = 0;
4112 	statsp->mac_stats.cap_100hdx = 0;
4113 	statsp->mac_stats.cap_10fdx = 0;
4114 	statsp->mac_stats.cap_10hdx = 0;
4115 	statsp->mac_stats.cap_asmpause = 0;
4116 	statsp->mac_stats.cap_pause = 0;
4117 	statsp->mac_stats.cap_1000fdx = 0;
4118 	statsp->mac_stats.cap_1000hdx = 0;
4119 	statsp->mac_stats.cap_10gfdx = 0;
4120 	statsp->mac_stats.cap_10ghdx = 0;
4121 
4122 	/*
4123 	 * Initialize the link statistics.
4124 	 */
4125 	statsp->mac_stats.link_T4 = 0;
4126 	statsp->mac_stats.link_asmpause = 0;
4127 	statsp->mac_stats.link_pause = 0;
4128 
4129 	if (nxgep->xcvr.xcvr_init) {
4130 		status = nxgep->xcvr.xcvr_init(nxgep);
4131 		if (status != NXGE_OK)
4132 			goto fail;
4133 		statsp->mac_stats.xcvr_inits++;
4134 	}
4135 
4136 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
4137 	    portn));
4138 	return (NXGE_OK);
4139 
4140 fail:
4141 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4142 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
4143 	    portn));
4144 	return (status);
4145 }
4146 
4147 /* Look for transceiver type */
4148 
4149 nxge_status_t
4150 nxge_xcvr_find(p_nxge_t nxgep)
4151 {
4152 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
4153 	    nxgep->mac.portnum));
4154 
4155 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
4156 		return (NXGE_ERROR);
4157 
4158 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
4159 		return (NXGE_ERROR);
4160 
4161 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
4162 	    nxgep->statsp->mac_stats.xcvr_inuse));
4163 	return (NXGE_OK);
4164 }
4165 
4166 /* Initialize the TxMAC sub-block */
4167 
4168 nxge_status_t
4169 nxge_tx_mac_init(p_nxge_t nxgep)
4170 {
4171 	npi_attr_t		ap;
4172 	uint8_t			portn;
4173 	nxge_port_mode_t	portmode;
4174 	nxge_port_t		portt;
4175 	npi_handle_t		handle;
4176 	npi_status_t		rs = NPI_SUCCESS;
4177 
4178 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4179 	portt    = nxgep->mac.porttype;
4180 	handle   = nxgep->npi_handle;
4181 	portmode = nxgep->mac.portmode;
4182 
4183 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
4184 	    portn));
4185 	/* Set Max and Min Frame Size */
4186 	/*
4187 	 * Use maxframesize to configure the hardware maxframe size
4188 	 * and minframesize to configure the hardware minframe size.
4189 	 */
4190 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4191 	    "==> nxge_tx_mac_init: port<%d> "
4192 	    "min framesize %d max framesize %d ",
4193 	    nxgep->mac.minframesize,
4194 	    nxgep->mac.maxframesize,
4195 	    portn));
4196 
4197 	SET_MAC_ATTR2(handle, ap, portn,
4198 	    MAC_PORT_FRAME_SIZE,
4199 	    nxgep->mac.minframesize,
4200 	    nxgep->mac.maxframesize,
4201 	    rs);
4202 	if (rs != NPI_SUCCESS)
4203 		goto fail;
4204 
4205 	if (portt == PORT_TYPE_XMAC) {
4206 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
4207 		    0)) != NPI_SUCCESS)
4208 			goto fail;
4209 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
4210 		if ((portmode == PORT_10G_FIBER) ||
4211 		    (portmode == PORT_10G_COPPER) ||
4212 		    (portmode == PORT_10G_TN1010) ||
4213 		    (portmode == PORT_HSP_MODE) ||
4214 		    (portmode == PORT_10G_SERDES)) {
4215 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
4216 			    XGMII_IPG_12_15, rs);
4217 			if (rs != NPI_SUCCESS)
4218 				goto fail;
4219 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
4220 		} else {
4221 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
4222 			    MII_GMII_IPG_12, rs);
4223 			if (rs != NPI_SUCCESS)
4224 				goto fail;
4225 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
4226 		}
4227 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
4228 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
4229 			goto fail;
4230 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
4231 		nxgep->mac.maxburstsize = 0;	/* not programmable */
4232 		nxgep->mac.ctrltype = 0;	/* not programmable */
4233 		nxgep->mac.pa_size = 0;		/* not programmable */
4234 
4235 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
4236 		    != NPI_SUCCESS)
4237 			goto fail;
4238 
4239 	} else {
4240 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
4241 		    0)) != NPI_SUCCESS)
4242 			goto fail;
4243 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
4244 
4245 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
4246 		    rs);
4247 		if (rs != NPI_SUCCESS)
4248 			goto fail;
4249 		nxgep->mac.ctrltype = 0x8808;
4250 
4251 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
4252 		if (rs != NPI_SUCCESS)
4253 			goto fail;
4254 		nxgep->mac.pa_size = 0x7;
4255 
4256 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
4257 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
4258 			goto fail;
4259 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
4260 	}
4261 
4262 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
4263 	    portn));
4264 
4265 	return (NXGE_OK);
4266 fail:
4267 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4268 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
4269 
4270 	return (NXGE_ERROR | rs);
4271 }
4272 
4273 static npi_status_t
4274 nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)
4275 {
4276 	uint32_t		i;
4277 	uint16_t		hashtab_e;
4278 	p_hash_filter_t		hash_filter;
4279 	uint8_t			portn;
4280 	npi_handle_t		handle;
4281 	npi_status_t		rs = NPI_SUCCESS;
4282 
4283 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4284 	handle = nxgep->npi_handle;
4285 
4286 	/*
4287 	 * Load the multicast hash filter bits.
4288 	 */
4289 	hash_filter = nxgep->hash_filter;
4290 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
4291 		if (hash_filter != NULL) {
4292 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
4293 			    (NMCFILTER_REGS - 1) - i];
4294 		} else {
4295 			hashtab_e = 0;
4296 		}
4297 
4298 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
4299 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
4300 			return (rs);
4301 	}
4302 
4303 	return (NPI_SUCCESS);
4304 }
4305 
4306 /*
4307  * Initialize the RxMAC sub-block
4308  */
4309 nxge_status_t
4310 nxge_rx_mac_init(p_nxge_t nxgep)
4311 {
4312 	npi_attr_t		ap;
4313 	nxge_port_t		portt;
4314 	uint8_t			portn;
4315 	npi_handle_t		handle;
4316 	npi_status_t		rs = NPI_SUCCESS;
4317 	uint16_t		*addr16p;
4318 	uint16_t		addr0, addr1, addr2;
4319 	xmac_rx_config_t	xconfig;
4320 	bmac_rx_config_t	bconfig;
4321 
4322 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4323 
4324 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
4325 	    portn));
4326 	handle = nxgep->npi_handle;
4327 	portt = nxgep->mac.porttype;
4328 
4329 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
4330 	addr0 = ntohs(addr16p[2]);
4331 	addr1 = ntohs(addr16p[1]);
4332 	addr2 = ntohs(addr16p[0]);
4333 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR,
4334 	    addr0, addr1, addr2, rs);
4335 	if (rs != NPI_SUCCESS)
4336 		goto fail;
4337 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
4338 	if (rs != NPI_SUCCESS)
4339 		goto fail;
4340 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
4341 	if (rs != NPI_SUCCESS)
4342 		goto fail;
4343 
4344 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
4345 	if (rs != NPI_SUCCESS)
4346 		goto fail;
4347 
4348 	if (portt == PORT_TYPE_XMAC) {
4349 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
4350 		    0)) != NPI_SUCCESS)
4351 			goto fail;
4352 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
4353 
4354 		(void) nxge_fflp_init_hostinfo(nxgep);
4355 
4356 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
4357 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
4358 		    ~CFG_XMAC_RX_STRIP_CRC;
4359 
4360 		if (nxgep->filter.all_phys_cnt != 0)
4361 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
4362 		if (nxgep->filter.all_multicast_cnt != 0)
4363 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
4364 
4365 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
4366 
4367 		if ((rs = npi_xmac_rx_config(handle, INIT,
4368 		    portn, xconfig)) != NPI_SUCCESS)
4369 			goto fail;
4370 		nxgep->mac.rx_config = xconfig;
4371 
4372 		/*
4373 		 * Comparison of mac unique address is always
4374 		 * enabled on XMAC
4375 		 */
4376 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
4377 		    != NPI_SUCCESS)
4378 			goto fail;
4379 	} else {
4380 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
4381 		    0) != NPI_SUCCESS)
4382 			goto fail;
4383 
4384 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
4385 
4386 		(void) nxge_fflp_init_hostinfo(nxgep);
4387 
4388 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
4389 		    ~CFG_BMAC_RX_STRIP_CRC;
4390 
4391 		if (nxgep->filter.all_phys_cnt != 0)
4392 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
4393 		if (nxgep->filter.all_multicast_cnt != 0)
4394 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
4395 
4396 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
4397 		if ((rs = npi_bmac_rx_config(handle, INIT,
4398 		    portn, bconfig)) != NPI_SUCCESS)
4399 			goto fail;
4400 		nxgep->mac.rx_config = bconfig;
4401 
4402 		/*
4403 		 * Always enable comparison of mac unique address
4404 		 */
4405 		if ((rs = npi_mac_altaddr_enable(handle,
4406 		    portn, 0)) != NPI_SUCCESS)
4407 			goto fail;
4408 	}
4409 
4410 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
4411 	    portn));
4412 
4413 	return (NXGE_OK);
4414 
4415 fail:
4416 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4417 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
4418 
4419 	return (NXGE_ERROR | rs);
4420 }
4421 
4422 /* Enable TXMAC */
4423 
4424 nxge_status_t
4425 nxge_tx_mac_enable(p_nxge_t nxgep)
4426 {
4427 	npi_handle_t	handle;
4428 	npi_status_t	rs = NPI_SUCCESS;
4429 	nxge_status_t	status = NXGE_OK;
4430 
4431 	handle = nxgep->npi_handle;
4432 
4433 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
4434 	    nxgep->mac.portnum));
4435 
4436 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
4437 		goto fail;
4438 
4439 	/* based on speed */
4440 	nxgep->msg_min = ETHERMIN;
4441 
4442 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4443 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
4444 		    CFG_XMAC_TX)) != NPI_SUCCESS)
4445 			goto fail;
4446 	} else {
4447 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
4448 		    CFG_BMAC_TX)) != NPI_SUCCESS)
4449 			goto fail;
4450 	}
4451 
4452 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
4453 	    nxgep->mac.portnum));
4454 
4455 	return (NXGE_OK);
4456 fail:
4457 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4458 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
4459 	    nxgep->mac.portnum));
4460 	if (rs != NPI_SUCCESS)
4461 		return (NXGE_ERROR | rs);
4462 	else
4463 		return (status);
4464 }
4465 
4466 /* Disable TXMAC */
4467 
4468 nxge_status_t
4469 nxge_tx_mac_disable(p_nxge_t nxgep)
4470 {
4471 	npi_handle_t	handle;
4472 	npi_status_t	rs = NPI_SUCCESS;
4473 
4474 	if (isLDOMguest(nxgep))
4475 		return (NXGE_OK);
4476 
4477 	handle = nxgep->npi_handle;
4478 
4479 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
4480 	    nxgep->mac.portnum));
4481 
4482 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4483 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
4484 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
4485 			goto fail;
4486 	} else {
4487 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
4488 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
4489 			goto fail;
4490 	}
4491 
4492 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
4493 	    nxgep->mac.portnum));
4494 	return (NXGE_OK);
4495 fail:
4496 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4497 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
4498 	    nxgep->mac.portnum));
4499 	return (NXGE_ERROR | rs);
4500 }
4501 
4502 /* Enable RXMAC */
4503 
4504 nxge_status_t
4505 nxge_rx_mac_enable(p_nxge_t nxgep)
4506 {
4507 	npi_handle_t	handle;
4508 	uint8_t		portn;
4509 	npi_status_t	rs = NPI_SUCCESS;
4510 	nxge_status_t	status = NXGE_OK;
4511 
4512 	/* This is a service-domain-only activity. */
4513 	if (isLDOMguest(nxgep))
4514 		return (status);
4515 
4516 	handle = nxgep->npi_handle;
4517 	portn = nxgep->mac.portnum;
4518 
4519 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
4520 	    portn));
4521 
4522 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
4523 		goto fail;
4524 
4525 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4526 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
4527 		    CFG_XMAC_RX)) != NPI_SUCCESS)
4528 			goto fail;
4529 	} else {
4530 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
4531 		    CFG_BMAC_RX)) != NPI_SUCCESS)
4532 			goto fail;
4533 	}
4534 
4535 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4536 	    "<== nxge_rx_mac_enable: port<%d>", portn));
4537 
4538 	return (NXGE_OK);
4539 fail:
4540 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4541 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
4542 
4543 	if (rs != NPI_SUCCESS)
4544 		return (NXGE_ERROR | rs);
4545 	else
4546 		return (status);
4547 }
4548 
4549 /* Disable RXMAC */
4550 
4551 nxge_status_t
4552 nxge_rx_mac_disable(p_nxge_t nxgep)
4553 {
4554 	npi_handle_t	handle;
4555 	uint8_t		portn;
4556 	npi_status_t	rs = NPI_SUCCESS;
4557 
4558 	/* If we are a guest domain driver, don't bother. */
4559 	if (isLDOMguest(nxgep))
4560 		return (NXGE_OK);
4561 
4562 	handle = nxgep->npi_handle;
4563 	portn = nxgep->mac.portnum;
4564 
4565 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
4566 	    portn));
4567 
4568 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4569 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
4570 		    CFG_XMAC_RX)) != NPI_SUCCESS)
4571 			goto fail;
4572 	} else {
4573 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
4574 		    CFG_BMAC_RX)) != NPI_SUCCESS)
4575 			goto fail;
4576 	}
4577 
4578 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
4579 	    portn));
4580 	return (NXGE_OK);
4581 fail:
4582 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4583 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
4584 
4585 	return (NXGE_ERROR | rs);
4586 }
4587 
4588 /* Reset TXMAC */
4589 
4590 nxge_status_t
4591 nxge_tx_mac_reset(p_nxge_t nxgep)
4592 {
4593 	npi_handle_t	handle;
4594 	uint8_t		portn;
4595 	npi_status_t	rs = NPI_SUCCESS;
4596 
4597 	handle = nxgep->npi_handle;
4598 	portn = nxgep->mac.portnum;
4599 
4600 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
4601 	    portn));
4602 
4603 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4604 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
4605 		    != NPI_SUCCESS)
4606 			goto fail;
4607 	} else {
4608 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
4609 		    != NPI_SUCCESS)
4610 			goto fail;
4611 	}
4612 
4613 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
4614 	    portn));
4615 
4616 	return (NXGE_OK);
4617 fail:
4618 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4619 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
4620 
4621 	return (NXGE_ERROR | rs);
4622 }
4623 
4624 /* Reset RXMAC */
4625 
4626 nxge_status_t
4627 nxge_rx_mac_reset(p_nxge_t nxgep)
4628 {
4629 	npi_handle_t	handle;
4630 	uint8_t		portn;
4631 	npi_status_t	rs = NPI_SUCCESS;
4632 
4633 	handle = nxgep->npi_handle;
4634 	portn = nxgep->mac.portnum;
4635 
4636 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
4637 	    portn));
4638 
4639 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
4640 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
4641 		    != NPI_SUCCESS)
4642 		goto fail;
4643 	} else {
4644 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
4645 		    != NPI_SUCCESS)
4646 		goto fail;
4647 	}
4648 
4649 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
4650 	    portn));
4651 
4652 	return (NXGE_OK);
4653 fail:
4654 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4655 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
4656 	return (NXGE_ERROR | rs);
4657 }
4658 
4659 /* 10G fiber link interrupt start routine */
4660 
4661 static nxge_status_t
4662 nxge_10G_link_intr_start(p_nxge_t nxgep)
4663 {
4664 	npi_status_t	rs = NPI_SUCCESS;
4665 	uint8_t		portn = nxgep->mac.portnum;
4666 
4667 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
4668 
4669 	if (rs != NPI_SUCCESS)
4670 		return (NXGE_ERROR | rs);
4671 	else
4672 		return (NXGE_OK);
4673 }
4674 
4675 /* 10G fiber link interrupt stop routine */
4676 
4677 static nxge_status_t
4678 nxge_10G_link_intr_stop(p_nxge_t nxgep)
4679 {
4680 	npi_status_t	rs = NPI_SUCCESS;
4681 	uint8_t		portn = nxgep->mac.portnum;
4682 
4683 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
4684 
4685 	if (rs != NPI_SUCCESS)
4686 		return (NXGE_ERROR | rs);
4687 	else
4688 		return (NXGE_OK);
4689 }
4690 
4691 /* 1G fiber link interrupt start routine */
4692 
4693 static nxge_status_t
4694 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
4695 {
4696 	npi_status_t	rs = NPI_SUCCESS;
4697 	uint8_t		portn = nxgep->mac.portnum;
4698 
4699 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
4700 	if (rs != NPI_SUCCESS)
4701 		return (NXGE_ERROR | rs);
4702 	else
4703 		return (NXGE_OK);
4704 }
4705 
4706 /* 1G fiber link interrupt stop routine */
4707 
4708 static nxge_status_t
4709 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
4710 {
4711 	npi_status_t	rs = NPI_SUCCESS;
4712 	uint8_t		portn = nxgep->mac.portnum;
4713 
4714 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
4715 
4716 	if (rs != NPI_SUCCESS)
4717 		return (NXGE_ERROR | rs);
4718 	else
4719 		return (NXGE_OK);
4720 }
4721 
4722 /* 1G copper link interrupt start routine */
4723 
4724 static nxge_status_t
4725 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
4726 {
4727 	npi_status_t	rs = NPI_SUCCESS;
4728 	uint8_t		portn = nxgep->mac.portnum;
4729 
4730 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
4731 	    MII_STATUS, MII_STATUS_LINKUP);
4732 
4733 	if (rs != NPI_SUCCESS)
4734 		return (NXGE_ERROR | rs);
4735 	else
4736 		return (NXGE_OK);
4737 }
4738 
4739 /* 1G copper link interrupt stop routine */
4740 
4741 static nxge_status_t
4742 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
4743 {
4744 	npi_status_t	rs = NPI_SUCCESS;
4745 	uint8_t		portn = nxgep->mac.portnum;
4746 
4747 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
4748 
4749 	if (rs != NPI_SUCCESS)
4750 		return (NXGE_ERROR | rs);
4751 	else
4752 		return (NXGE_OK);
4753 }
4754 
4755 /* Enable/Disable Link Status change interrupt */
4756 
4757 nxge_status_t
4758 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
4759 {
4760 	uint8_t		portn;
4761 	nxge_status_t	status = NXGE_OK;
4762 
4763 	portn = nxgep->mac.portnum;
4764 
4765 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
4766 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
4767 		return (NXGE_OK);
4768 
4769 	if (enable == LINK_INTR_START)
4770 		status = nxgep->xcvr.link_intr_start(nxgep);
4771 	else if (enable == LINK_INTR_STOP)
4772 		status = nxgep->xcvr.link_intr_stop(nxgep);
4773 	if (status != NXGE_OK)
4774 		goto fail;
4775 
4776 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
4777 
4778 	return (NXGE_OK);
4779 fail:
4780 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4781 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
4782 
4783 	return (status);
4784 }
4785 
4786 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
4787 
4788 nxge_status_t
4789 nxge_mii_xcvr_init(p_nxge_t nxgep)
4790 {
4791 	p_nxge_param_t	param_arr;
4792 	p_nxge_stats_t	statsp;
4793 	uint8_t		xcvr_portn;
4794 	p_mii_regs_t	mii_regs;
4795 	mii_bmcr_t	bmcr;
4796 	mii_bmsr_t	bmsr;
4797 	mii_anar_t	anar;
4798 	mii_gcr_t	gcr;
4799 	mii_esr_t	esr;
4800 	mii_aux_ctl_t	bcm5464r_aux;
4801 	int		status = NXGE_OK;
4802 
4803 	uint_t delay;
4804 
4805 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
4806 
4807 	param_arr = nxgep->param_arr;
4808 	statsp = nxgep->statsp;
4809 	xcvr_portn = statsp->mac_stats.xcvr_portn;
4810 
4811 	mii_regs = NULL;
4812 
4813 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4814 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
4815 
4816 	/*
4817 	 * The mif phy mode may be connected to either a copper link
4818 	 * or fiber link. Read the mode control register to get the fiber
4819 	 * configuration if it is hard-wired to fiber link.
4820 	 */
4821 	(void) nxge_mii_get_link_mode(nxgep);
4822 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4823 		return (nxge_mii_xcvr_fiber_init(nxgep));
4824 	}
4825 
4826 	/*
4827 	 * Reset the transceiver.
4828 	 */
4829 	delay = 0;
4830 	bmcr.value = 0;
4831 	bmcr.bits.reset = 1;
4832 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4833 #if defined(__i386)
4834 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
4835 #else
4836 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
4837 #endif
4838 	    bmcr.value)) != NXGE_OK)
4839 		goto fail;
4840 	do {
4841 		drv_usecwait(500);
4842 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4843 #if defined(__i386)
4844 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
4845 #else
4846 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
4847 #endif
4848 		    &bmcr.value)) != NXGE_OK)
4849 			goto fail;
4850 		delay++;
4851 	} while ((bmcr.bits.reset) && (delay < 1000));
4852 	if (delay == 1000) {
4853 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4854 		goto fail;
4855 	}
4856 
4857 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4858 #if defined(__i386)
4859 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4860 #else
4861 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4862 #endif
4863 	    &bmsr.value)) != NXGE_OK)
4864 		goto fail;
4865 
4866 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4867 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
4868 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
4869 	param_arr[param_anar_100hdx].value = 0;
4870 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
4871 	param_arr[param_anar_10hdx].value = 0;
4872 
4873 	/*
4874 	 * Initialize the xcvr statistics.
4875 	 */
4876 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4877 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
4878 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
4879 	statsp->mac_stats.cap_100hdx = 0;
4880 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
4881 	statsp->mac_stats.cap_10hdx = 0;
4882 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4883 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4884 
4885 	/*
4886 	 * Initialize the xcvr advertised capability statistics.
4887 	 */
4888 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4889 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4890 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4891 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4892 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4893 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4894 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4895 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4896 	statsp->mac_stats.adv_cap_asmpause =
4897 	    param_arr[param_anar_asmpause].value;
4898 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4899 
4900 
4901 	/*
4902 	 * Check for extended status just in case we're
4903 	 * running a Gigibit phy.
4904 	 */
4905 	if (bmsr.bits.extend_status) {
4906 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4907 #if defined(__i386)
4908 		    (uint8_t)(uint32_t)(&mii_regs->esr),
4909 #else
4910 		    (uint8_t)(uint64_t)(&mii_regs->esr),
4911 #endif
4912 		    &esr.value)) != NXGE_OK)
4913 			goto fail;
4914 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
4915 		param_arr[param_anar_1000hdx].value = 0;
4916 
4917 		statsp->mac_stats.cap_1000fdx =
4918 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4919 		statsp->mac_stats.cap_1000hdx = 0;
4920 	} else {
4921 		param_arr[param_anar_1000fdx].value = 0;
4922 		param_arr[param_anar_1000hdx].value = 0;
4923 	}
4924 
4925 	/*
4926 	 * Initialize 1G Statistics once the capability is established.
4927 	 */
4928 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4929 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4930 
4931 	/*
4932 	 * Initialize the link statistics.
4933 	 */
4934 	statsp->mac_stats.link_T4 = 0;
4935 	statsp->mac_stats.link_asmpause = 0;
4936 	statsp->mac_stats.link_pause = 0;
4937 	statsp->mac_stats.link_speed = 0;
4938 	statsp->mac_stats.link_duplex = 0;
4939 	statsp->mac_stats.link_up = 0;
4940 
4941 	/*
4942 	 * Switch off Auto-negotiation, 100M and full duplex.
4943 	 */
4944 	bmcr.value = 0;
4945 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4946 #if defined(__i386)
4947 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4948 #else
4949 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4950 #endif
4951 	    bmcr.value)) != NXGE_OK)
4952 		goto fail;
4953 
4954 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4955 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4956 		bmcr.bits.loopback = 1;
4957 		bmcr.bits.enable_autoneg = 0;
4958 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4959 			bmcr.bits.speed_1000_sel = 1;
4960 		bmcr.bits.duplex_mode = 1;
4961 		param_arr[param_autoneg].value = 0;
4962 	} else {
4963 		bmcr.bits.loopback = 0;
4964 	}
4965 
4966 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
4967 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
4968 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
4969 		param_arr[param_autoneg].value = 0;
4970 		bcm5464r_aux.value = 0;
4971 		bcm5464r_aux.bits.ext_lb = 1;
4972 		bcm5464r_aux.bits.write_1 = 1;
4973 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4974 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4975 			goto fail;
4976 	}
4977 
4978 	/* If auto-negotiation is desired */
4979 	if (param_arr[param_autoneg].value) {
4980 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4981 		    "Restarting Auto-negotiation."));
4982 		/*
4983 		 * Setup our Auto-negotiation advertisement register.
4984 		 */
4985 		anar.value = 0;
4986 		anar.bits.selector = 1;
4987 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
4988 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
4989 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
4990 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
4991 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
4992 		anar.bits.cap_asmpause = 0;
4993 		anar.bits.cap_pause = 0;
4994 		if (param_arr[param_anar_1000fdx].value ||
4995 		    param_arr[param_anar_100fdx].value ||
4996 		    param_arr[param_anar_10fdx].value) {
4997 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
4998 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
4999 		}
5000 
5001 		/* Write to the auto-negotiation advertisement register */
5002 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5003 #if defined(__i386)
5004 		    (uint8_t)(uint32_t)(&mii_regs->anar),
5005 #else
5006 		    (uint8_t)(uint64_t)(&mii_regs->anar),
5007 #endif
5008 		    anar.value)) != NXGE_OK)
5009 			goto fail;
5010 		if (bmsr.bits.extend_status) {
5011 			gcr.value = 0;
5012 			gcr.bits.ms_mode_en =
5013 			    param_arr[param_master_cfg_enable].value;
5014 			gcr.bits.master =
5015 			    param_arr[param_master_cfg_value].value;
5016 			gcr.bits.link_1000fdx =
5017 			    param_arr[param_anar_1000fdx].value;
5018 			gcr.bits.link_1000hdx =
5019 			    param_arr[param_anar_1000hdx].value;
5020 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
5021 #if defined(__i386)
5022 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
5023 #else
5024 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
5025 #endif
5026 			    gcr.value)) != NXGE_OK)
5027 				goto fail;
5028 		}
5029 
5030 		bmcr.bits.enable_autoneg = 1;
5031 		bmcr.bits.restart_autoneg = 1;
5032 
5033 	} else {
5034 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
5035 		bmcr.bits.speed_1000_sel =
5036 		    param_arr[param_anar_1000fdx].value |
5037 		    param_arr[param_anar_1000hdx].value;
5038 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
5039 		    (param_arr[param_anar_100fdx].value |
5040 		    param_arr[param_anar_100hdx].value);
5041 
5042 		/* Force to 1G */
5043 		if (bmcr.bits.speed_1000_sel) {
5044 			statsp->mac_stats.link_speed = 1000;
5045 			gcr.value = 0;
5046 			gcr.bits.ms_mode_en =
5047 			    param_arr[param_master_cfg_enable].value;
5048 			gcr.bits.master =
5049 			    param_arr[param_master_cfg_value].value;
5050 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
5051 #if defined(__i386)
5052 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
5053 #else
5054 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
5055 #endif
5056 			    gcr.value)) != NXGE_OK)
5057 				goto fail;
5058 			if (param_arr[param_anar_1000fdx].value) {
5059 				bmcr.bits.duplex_mode = 1;
5060 				statsp->mac_stats.link_duplex = 2;
5061 			} else
5062 				statsp->mac_stats.link_duplex = 1;
5063 
5064 		/* Force to 100M */
5065 		} else if (bmcr.bits.speed_sel) {
5066 			statsp->mac_stats.link_speed = 100;
5067 			if (param_arr[param_anar_100fdx].value) {
5068 				bmcr.bits.duplex_mode = 1;
5069 				statsp->mac_stats.link_duplex = 2;
5070 			} else
5071 				statsp->mac_stats.link_duplex = 1;
5072 
5073 		/* Force to 10M */
5074 		} else {
5075 			statsp->mac_stats.link_speed = 10;
5076 			if (param_arr[param_anar_10fdx].value) {
5077 				bmcr.bits.duplex_mode = 1;
5078 				statsp->mac_stats.link_duplex = 2;
5079 			} else
5080 				statsp->mac_stats.link_duplex = 1;
5081 		}
5082 		if (statsp->mac_stats.link_duplex != 1) {
5083 			statsp->mac_stats.link_asmpause =
5084 			    statsp->mac_stats.cap_asmpause;
5085 			statsp->mac_stats.link_pause =
5086 			    statsp->mac_stats.cap_pause;
5087 		}
5088 
5089 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
5090 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
5091 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
5092 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
5093 				/* BCM5464R 1000mbps external loopback mode */
5094 				gcr.value = 0;
5095 				gcr.bits.ms_mode_en = 1;
5096 				gcr.bits.master = 1;
5097 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
5098 #if defined(__i386)
5099 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
5100 #else
5101 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
5102 #endif
5103 				    gcr.value)) != NXGE_OK)
5104 					goto fail;
5105 				bmcr.value = 0;
5106 				bmcr.bits.speed_1000_sel = 1;
5107 				statsp->mac_stats.link_speed = 1000;
5108 			} else if (statsp->port_stats.lb_mode
5109 			    == nxge_lb_ext100) {
5110 				/* BCM5464R 100mbps external loopback mode */
5111 				bmcr.value = 0;
5112 				bmcr.bits.speed_sel = 1;
5113 				bmcr.bits.duplex_mode = 1;
5114 				statsp->mac_stats.link_speed = 100;
5115 			} else if (statsp->port_stats.lb_mode
5116 			    == nxge_lb_ext10) {
5117 				/* BCM5464R 10mbps external loopback mode */
5118 				bmcr.value = 0;
5119 				bmcr.bits.duplex_mode = 1;
5120 				statsp->mac_stats.link_speed = 10;
5121 			}
5122 		}
5123 	}
5124 
5125 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5126 #if defined(__i386)
5127 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5128 #else
5129 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5130 #endif
5131 	    bmcr.value)) != NXGE_OK)
5132 		goto fail;
5133 
5134 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5135 #if defined(__i386)
5136 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5137 #else
5138 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5139 #endif
5140 	    &bmcr.value)) != NXGE_OK)
5141 		goto fail;
5142 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
5143 
5144 	/*
5145 	 * Initialize the xcvr status kept in the context structure.
5146 	 */
5147 	nxgep->soft_bmsr.value = 0;
5148 
5149 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5150 #if defined(__i386)
5151 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5152 #else
5153 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5154 #endif
5155 	    &nxgep->bmsr.value)) != NXGE_OK)
5156 		goto fail;
5157 
5158 	statsp->mac_stats.xcvr_inits++;
5159 	nxgep->bmsr.value = 0;
5160 
5161 fail:
5162 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5163 	    "<== nxge_mii_xcvr_init status 0x%x", status));
5164 	return (status);
5165 }
5166 
5167 nxge_status_t
5168 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
5169 {
5170 	p_nxge_param_t	param_arr;
5171 	p_nxge_stats_t	statsp;
5172 	uint8_t		xcvr_portn;
5173 	p_mii_regs_t	mii_regs;
5174 	mii_bmcr_t	bmcr;
5175 	mii_bmsr_t	bmsr;
5176 	mii_gcr_t	gcr;
5177 	mii_esr_t	esr;
5178 	mii_aux_ctl_t	bcm5464r_aux;
5179 	int		status = NXGE_OK;
5180 
5181 	uint_t delay;
5182 
5183 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
5184 
5185 	param_arr = nxgep->param_arr;
5186 	statsp = nxgep->statsp;
5187 	xcvr_portn = statsp->mac_stats.xcvr_portn;
5188 
5189 	mii_regs = NULL;
5190 
5191 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5192 	    "nxge_mii_xcvr_fiber_init: "
5193 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
5194 
5195 	/*
5196 	 * Reset the transceiver.
5197 	 */
5198 	delay = 0;
5199 	bmcr.value = 0;
5200 	bmcr.bits.reset = 1;
5201 
5202 #if defined(__i386)
5203 
5204 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5205 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5206 		goto fail;
5207 #else
5208 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5209 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5210 		goto fail;
5211 #endif
5212 	do {
5213 		drv_usecwait(500);
5214 #if defined(__i386)
5215 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5216 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
5217 		    != NXGE_OK)
5218 			goto fail;
5219 #else
5220 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5221 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
5222 		    != NXGE_OK)
5223 			goto fail;
5224 #endif
5225 		delay++;
5226 	} while ((bmcr.bits.reset) && (delay < 1000));
5227 	if (delay == 1000) {
5228 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
5229 		goto fail;
5230 	}
5231 
5232 #if defined(__i386)
5233 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5234 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5235 		goto fail;
5236 #else
5237 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5238 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5239 		goto fail;
5240 #endif
5241 
5242 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
5243 	param_arr[param_anar_100T4].value = 0;
5244 	param_arr[param_anar_100fdx].value = 0;
5245 	param_arr[param_anar_100hdx].value = 0;
5246 	param_arr[param_anar_10fdx].value = 0;
5247 	param_arr[param_anar_10hdx].value = 0;
5248 
5249 	/*
5250 	 * Initialize the xcvr statistics.
5251 	 */
5252 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
5253 	statsp->mac_stats.cap_100T4 = 0;
5254 	statsp->mac_stats.cap_100fdx = 0;
5255 	statsp->mac_stats.cap_100hdx = 0;
5256 	statsp->mac_stats.cap_10fdx = 0;
5257 	statsp->mac_stats.cap_10hdx = 0;
5258 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
5259 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
5260 
5261 	/*
5262 	 * Initialize the xcvr advertised capability statistics.
5263 	 */
5264 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
5265 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5266 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5267 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
5268 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
5269 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
5270 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
5271 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
5272 	statsp->mac_stats.adv_cap_asmpause =
5273 	    param_arr[param_anar_asmpause].value;
5274 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
5275 
5276 	/*
5277 	 * Check for extended status just in case we're
5278 	 * running a Gigibit phy.
5279 	 */
5280 	if (bmsr.bits.extend_status) {
5281 #if defined(__i386)
5282 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5283 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
5284 		    NXGE_OK)
5285 			goto fail;
5286 #else
5287 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5288 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
5289 		    NXGE_OK)
5290 			goto fail;
5291 #endif
5292 		param_arr[param_anar_1000fdx].value &=
5293 		    esr.bits.link_1000fdx;
5294 		param_arr[param_anar_1000hdx].value = 0;
5295 
5296 		statsp->mac_stats.cap_1000fdx =
5297 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
5298 		statsp->mac_stats.cap_1000hdx = 0;
5299 	} else {
5300 		param_arr[param_anar_1000fdx].value = 0;
5301 		param_arr[param_anar_1000hdx].value = 0;
5302 	}
5303 
5304 	/*
5305 	 * Initialize 1G Statistics once the capability is established.
5306 	 */
5307 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5308 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5309 
5310 	/*
5311 	 * Initialize the link statistics.
5312 	 */
5313 	statsp->mac_stats.link_T4 = 0;
5314 	statsp->mac_stats.link_asmpause = 0;
5315 	statsp->mac_stats.link_pause = 0;
5316 	statsp->mac_stats.link_speed = 0;
5317 	statsp->mac_stats.link_duplex = 0;
5318 	statsp->mac_stats.link_up = 0;
5319 
5320 	/*
5321 	 * Switch off Auto-negotiation, 100M and full duplex.
5322 	 */
5323 	bmcr.value = 0;
5324 #if defined(__i386)
5325 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5326 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5327 		goto fail;
5328 #else
5329 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5330 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5331 		goto fail;
5332 #endif
5333 
5334 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
5335 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
5336 		bmcr.bits.loopback = 1;
5337 		bmcr.bits.enable_autoneg = 0;
5338 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
5339 			bmcr.bits.speed_1000_sel = 1;
5340 		bmcr.bits.duplex_mode = 1;
5341 		param_arr[param_autoneg].value = 0;
5342 	} else {
5343 		bmcr.bits.loopback = 0;
5344 	}
5345 
5346 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
5347 		param_arr[param_autoneg].value = 0;
5348 		bcm5464r_aux.value = 0;
5349 		bcm5464r_aux.bits.ext_lb = 1;
5350 		bcm5464r_aux.bits.write_1 = 1;
5351 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5352 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
5353 			goto fail;
5354 	}
5355 
5356 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
5357 	bmcr.bits.speed_1000_sel = 1;
5358 	bmcr.bits.speed_sel = 0;
5359 	bmcr.bits.duplex_mode = 1;
5360 	statsp->mac_stats.link_speed = 1000;
5361 	statsp->mac_stats.link_duplex = 2;
5362 
5363 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
5364 		/* BCM5464R 1000mbps external loopback mode */
5365 		gcr.value = 0;
5366 		gcr.bits.ms_mode_en = 1;
5367 		gcr.bits.master = 1;
5368 #if defined(__i386)
5369 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5370 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
5371 		    gcr.value)) != NXGE_OK)
5372 			goto fail;
5373 #else
5374 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5375 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
5376 		    gcr.value)) != NXGE_OK)
5377 			goto fail;
5378 #endif
5379 		bmcr.value = 0;
5380 		bmcr.bits.speed_1000_sel = 1;
5381 		statsp->mac_stats.link_speed = 1000;
5382 	}
5383 
5384 #if defined(__i386)
5385 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5386 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5387 	    bmcr.value)) != NXGE_OK)
5388 		goto fail;
5389 #else
5390 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5391 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5392 	    bmcr.value)) != NXGE_OK)
5393 		goto fail;
5394 #endif
5395 
5396 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5397 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
5398 	    bmcr.value));
5399 
5400 #if defined(__i386)
5401 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5402 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5403 		goto fail;
5404 #else
5405 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5406 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5407 		goto fail;
5408 #endif
5409 
5410 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5411 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
5412 
5413 	/*
5414 	 * Initialize the xcvr status kept in the context structure.
5415 	 */
5416 	nxgep->soft_bmsr.value = 0;
5417 #if defined(__i386)
5418 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5419 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5420 	    &nxgep->bmsr.value)) != NXGE_OK)
5421 		goto fail;
5422 #else
5423 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5424 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5425 	    &nxgep->bmsr.value)) != NXGE_OK)
5426 		goto fail;
5427 #endif
5428 
5429 	statsp->mac_stats.xcvr_inits++;
5430 	nxgep->bmsr.value = 0;
5431 
5432 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5433 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5434 	return (status);
5435 
5436 fail:
5437 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5438 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5439 	return (status);
5440 }
5441 
5442 /* Read from a MII compliant register */
5443 
5444 nxge_status_t
5445 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
5446     uint16_t *value)
5447 {
5448 	npi_status_t rs = NPI_SUCCESS;
5449 
5450 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
5451 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
5452 
5453 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5454 
5455 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5456 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
5457 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
5458 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5459 			goto fail;
5460 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
5461 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
5462 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
5463 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5464 			goto fail;
5465 	} else
5466 		goto fail;
5467 
5468 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5469 
5470 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
5471 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
5472 	return (NXGE_OK);
5473 fail:
5474 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5475 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5476 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
5477 
5478 	return (NXGE_ERROR | rs);
5479 }
5480 
5481 /* Write to a MII compliant Register */
5482 
5483 nxge_status_t
5484 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
5485     uint16_t value)
5486 {
5487 	npi_status_t rs = NPI_SUCCESS;
5488 
5489 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
5490 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
5491 
5492 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5493 
5494 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5495 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
5496 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
5497 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5498 			goto fail;
5499 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
5500 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
5501 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
5502 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
5503 			goto fail;
5504 	} else
5505 		goto fail;
5506 
5507 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5508 
5509 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
5510 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
5511 	return (NXGE_OK);
5512 fail:
5513 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5514 
5515 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5516 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
5517 
5518 	return (NXGE_ERROR | rs);
5519 }
5520 
5521 /*
5522  * Perform write to Clause45 serdes / transceiver device
5523  * Arguments:
5524  *	xcvr_portn:	The IEEE 802.3 Clause45 PHYAD, it is the same as port
5525  *			number if nxge_mdio_write is used for accessing the
5526  *			internal LSIL serdes. Otherwise PHYAD is different
5527  *			for different platforms.
5528  *	device:		With each PHYAD, the driver can use MDIO to control
5529  *			multiple devices inside the PHY, here "device" is an
5530  *			MMD (MDIO managable device).
5531  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
5532  *			the register which the driver will write value to.
5533  *	value:		The register value will be filled in.
5534  */
5535 nxge_status_t
5536 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
5537     uint16_t xcvr_reg, uint16_t *value)
5538 {
5539 	npi_status_t rs = NPI_SUCCESS;
5540 
5541 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
5542 	    xcvr_portn));
5543 
5544 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5545 
5546 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
5547 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
5548 		goto fail;
5549 
5550 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5551 
5552 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
5553 	    xcvr_portn));
5554 	return (NXGE_OK);
5555 fail:
5556 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5557 
5558 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5559 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
5560 
5561 	return (NXGE_ERROR | rs);
5562 }
5563 
5564 /* Perform write to Clause45 serdes / transceiver device */
5565 
5566 nxge_status_t
5567 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
5568     uint16_t xcvr_reg, uint16_t value)
5569 {
5570 	npi_status_t rs = NPI_SUCCESS;
5571 
5572 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
5573 	    xcvr_portn));
5574 
5575 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
5576 
5577 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
5578 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
5579 		goto fail;
5580 
5581 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5582 
5583 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
5584 	    xcvr_portn));
5585 	return (NXGE_OK);
5586 fail:
5587 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
5588 
5589 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5590 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
5591 
5592 	return (NXGE_ERROR | rs);
5593 }
5594 
5595 
5596 /* Check MII to see if there is any link status change */
5597 
5598 nxge_status_t
5599 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
5600     nxge_link_state_t *link_up)
5601 {
5602 	p_nxge_param_t	param_arr;
5603 	p_nxge_stats_t	statsp;
5604 	p_mii_regs_t	mii_regs;
5605 	p_mii_bmsr_t	soft_bmsr;
5606 	mii_anar_t	anar;
5607 	mii_anlpar_t	anlpar;
5608 	mii_anar_t	an_common;
5609 	mii_aner_t	aner;
5610 	mii_gsr_t	gsr;
5611 	nxge_status_t	status = NXGE_OK;
5612 
5613 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
5614 
5615 	mii_regs = NULL;
5616 	param_arr = nxgep->param_arr;
5617 	statsp = nxgep->statsp;
5618 	soft_bmsr = &nxgep->soft_bmsr;
5619 	*link_up = LINK_NO_CHANGE;
5620 
5621 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5622 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
5623 	    bmsr.value, bmsr_ints.value));
5624 
5625 	if (bmsr_ints.bits.link_status) {
5626 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5627 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
5628 		    bmsr.value, bmsr_ints.value));
5629 		if (bmsr.bits.link_status) {
5630 			soft_bmsr->bits.link_status = 1;
5631 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5632 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
5633 		    "0x%x", bmsr.value, bmsr_ints.value));
5634 		} else {
5635 			/* Only status change will update *link_up */
5636 			if (statsp->mac_stats.link_up == 1) {
5637 				*link_up = LINK_IS_DOWN;
5638 				/* Will notify, turn off further msg */
5639 				nxgep->link_notify = B_FALSE;
5640 			}
5641 			statsp->mac_stats.link_up = 0;
5642 			soft_bmsr->bits.link_status = 0;
5643 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5644 			    "Link down cable problem"));
5645 		}
5646 	}
5647 
5648 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
5649 	    param_arr[param_autoneg].value) {
5650 		if (bmsr_ints.bits.auto_neg_complete) {
5651 			if (bmsr.bits.auto_neg_complete)
5652 				soft_bmsr->bits.auto_neg_complete = 1;
5653 			else
5654 				soft_bmsr->bits.auto_neg_complete = 0;
5655 		}
5656 		if (soft_bmsr->bits.link_status == 0) {
5657 			statsp->mac_stats.link_T4 = 0;
5658 			statsp->mac_stats.link_speed = 0;
5659 			statsp->mac_stats.link_duplex = 0;
5660 			statsp->mac_stats.link_asmpause = 0;
5661 			statsp->mac_stats.link_pause = 0;
5662 			statsp->mac_stats.lp_cap_autoneg = 0;
5663 			statsp->mac_stats.lp_cap_100T4 = 0;
5664 			statsp->mac_stats.lp_cap_1000fdx = 0;
5665 			statsp->mac_stats.lp_cap_1000hdx = 0;
5666 			statsp->mac_stats.lp_cap_100fdx = 0;
5667 			statsp->mac_stats.lp_cap_100hdx = 0;
5668 			statsp->mac_stats.lp_cap_10fdx = 0;
5669 			statsp->mac_stats.lp_cap_10hdx = 0;
5670 			statsp->mac_stats.lp_cap_10gfdx = 0;
5671 			statsp->mac_stats.lp_cap_10ghdx = 0;
5672 			statsp->mac_stats.lp_cap_asmpause = 0;
5673 			statsp->mac_stats.lp_cap_pause = 0;
5674 		}
5675 	} else
5676 		soft_bmsr->bits.auto_neg_complete = 1;
5677 
5678 	if ((bmsr_ints.bits.link_status ||
5679 	    bmsr_ints.bits.auto_neg_complete) &&
5680 	    soft_bmsr->bits.link_status &&
5681 	    soft_bmsr->bits.auto_neg_complete) {
5682 		if (statsp->mac_stats.link_up == 0) {
5683 			*link_up = LINK_IS_UP;
5684 			nxgep->link_notify = B_FALSE;
5685 		}
5686 		statsp->mac_stats.link_up = 1;
5687 
5688 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5689 		    "==> nxge_mii_check "
5690 		    "(auto negotiation complete or link up) "
5691 		    "soft bmsr 0x%x bmsr_int 0x%x",
5692 		    bmsr.value, bmsr_ints.value));
5693 
5694 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
5695 		    param_arr[param_autoneg].value) {
5696 			if ((status = nxge_mii_read(nxgep,
5697 			    statsp->mac_stats.xcvr_portn,
5698 #if defined(__i386)
5699 			    (uint8_t)(uint32_t)(&mii_regs->anar),
5700 #else
5701 			    (uint8_t)(uint64_t)(&mii_regs->anar),
5702 #endif
5703 			    &anar.value)) != NXGE_OK)
5704 				goto fail;
5705 			if ((status = nxge_mii_read(nxgep,
5706 			    statsp->mac_stats.xcvr_portn,
5707 #if defined(__i386)
5708 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
5709 #else
5710 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
5711 #endif
5712 			    &anlpar.value)) != NXGE_OK)
5713 				goto fail;
5714 			if ((status = nxge_mii_read(nxgep,
5715 			    statsp->mac_stats.xcvr_portn,
5716 #if defined(__i386)
5717 			    (uint8_t)(uint32_t)(&mii_regs->aner),
5718 #else
5719 			    (uint8_t)(uint64_t)(&mii_regs->aner),
5720 #endif
5721 			    &aner.value)) != NXGE_OK)
5722 				goto fail;
5723 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
5724 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
5725 			statsp->mac_stats.lp_cap_100fdx =
5726 			    anlpar.bits.cap_100fdx;
5727 			statsp->mac_stats.lp_cap_100hdx =
5728 			    anlpar.bits.cap_100hdx;
5729 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
5730 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
5731 			statsp->mac_stats.lp_cap_asmpause =
5732 			    anlpar.bits.cap_asmpause;
5733 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
5734 			an_common.value = anar.value & anlpar.value;
5735 			if (param_arr[param_anar_1000fdx].value ||
5736 			    param_arr[param_anar_1000hdx].value) {
5737 				if ((status = nxge_mii_read(nxgep,
5738 				    statsp->mac_stats.xcvr_portn,
5739 #if defined(__i386)
5740 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
5741 #else
5742 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
5743 #endif
5744 				    &gsr.value)) != NXGE_OK)
5745 					goto fail;
5746 				statsp->mac_stats.lp_cap_1000fdx =
5747 				    gsr.bits.link_1000fdx;
5748 				statsp->mac_stats.lp_cap_1000hdx =
5749 				    gsr.bits.link_1000hdx;
5750 				if (param_arr[param_anar_1000fdx].value &&
5751 				    gsr.bits.link_1000fdx) {
5752 					statsp->mac_stats.link_speed = 1000;
5753 					statsp->mac_stats.link_duplex = 2;
5754 				} else if (
5755 				    param_arr[param_anar_1000hdx].value &&
5756 				    gsr.bits.link_1000hdx) {
5757 					statsp->mac_stats.link_speed = 1000;
5758 					statsp->mac_stats.link_duplex = 1;
5759 				}
5760 			}
5761 			if ((an_common.value != 0) &&
5762 			    !(statsp->mac_stats.link_speed)) {
5763 				if (an_common.bits.cap_100T4) {
5764 					statsp->mac_stats.link_T4 = 1;
5765 					statsp->mac_stats.link_speed = 100;
5766 					statsp->mac_stats.link_duplex = 1;
5767 				} else if (an_common.bits.cap_100fdx) {
5768 					statsp->mac_stats.link_speed = 100;
5769 					statsp->mac_stats.link_duplex = 2;
5770 				} else if (an_common.bits.cap_100hdx) {
5771 					statsp->mac_stats.link_speed = 100;
5772 					statsp->mac_stats.link_duplex = 1;
5773 				} else if (an_common.bits.cap_10fdx) {
5774 					statsp->mac_stats.link_speed = 10;
5775 					statsp->mac_stats.link_duplex = 2;
5776 				} else if (an_common.bits.cap_10hdx) {
5777 					statsp->mac_stats.link_speed = 10;
5778 					statsp->mac_stats.link_duplex = 1;
5779 				} else {
5780 					goto fail;
5781 				}
5782 			}
5783 			if (statsp->mac_stats.link_duplex != 1) {
5784 				int	link_pause;
5785 				int	cp, lcp;
5786 
5787 				statsp->mac_stats.link_asmpause =
5788 				    an_common.bits.cap_asmpause;
5789 				cp = statsp->mac_stats.cap_pause;
5790 				lcp = statsp->mac_stats.lp_cap_pause;
5791 				if (statsp->mac_stats.link_asmpause) {
5792 					if ((cp == 0) && (lcp == 1)) {
5793 						link_pause = 0;
5794 					} else {
5795 						link_pause = 1;
5796 					}
5797 				} else {
5798 					link_pause = an_common.bits.cap_pause;
5799 				}
5800 				statsp->mac_stats.link_pause = link_pause;
5801 			}
5802 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
5803 			statsp->mac_stats.link_speed = 1000;
5804 			statsp->mac_stats.link_duplex = 2;
5805 		}
5806 	}
5807 	/* Initial link_notify, delay link down msg */
5808 	if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
5809 	    (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) {
5810 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
5811 		    LINK_IS_DOWN);
5812 		nxgep->link_notify = B_FALSE;
5813 	}
5814 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
5815 	return (NXGE_OK);
5816 fail:
5817 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5818 	    "nxge_mii_check: Unable to check MII"));
5819 	return (status);
5820 }
5821 
5822 /*
5823  * Check PCS to see if there is any link status change.
5824  * This function is called by PORT_1G_SERDES only.
5825  */
5826 void
5827 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
5828 {
5829 	p_nxge_stats_t	statsp;
5830 	boolean_t	linkup;
5831 
5832 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
5833 
5834 	statsp = nxgep->statsp;
5835 	*link_up = LINK_NO_CHANGE;
5836 
5837 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
5838 	if (linkup) {
5839 		if ((nxgep->link_notify &&
5840 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5841 		    nxgep->statsp->mac_stats.link_up == 0) {
5842 			statsp->mac_stats.link_up = 1;
5843 			statsp->mac_stats.link_speed = 1000;
5844 			statsp->mac_stats.link_duplex = 2;
5845 			*link_up = LINK_IS_UP;
5846 			nxgep->link_notify = B_FALSE;
5847 		}
5848 	} else {
5849 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
5850 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5851 		    nxgep->statsp->mac_stats.link_up == 1) {
5852 			statsp->mac_stats.link_up = 0;
5853 			statsp->mac_stats.link_speed = 0;
5854 			statsp->mac_stats.link_duplex = 0;
5855 			*link_up = LINK_IS_DOWN;
5856 			nxgep->link_notify = B_FALSE;
5857 		}
5858 	}
5859 
5860 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
5861 }
5862 
5863 /* Add a multicast address entry into the HW hash table */
5864 
5865 nxge_status_t
5866 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5867 {
5868 	uint32_t mchash;
5869 	p_hash_filter_t hash_filter;
5870 	uint16_t hash_bit;
5871 	uint_t j;
5872 	nxge_status_t status = NXGE_OK;
5873 	npi_status_t rs;
5874 
5875 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
5876 
5877 	RW_ENTER_WRITER(&nxgep->filter_lock);
5878 	mchash = crc32_mchash(addrp);
5879 	if (nxgep->hash_filter == NULL) {
5880 		NXGE_DEBUG_MSG((NULL, STR_CTL,
5881 		    "Allocating hash filter storage."));
5882 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
5883 		    KM_SLEEP);
5884 	}
5885 
5886 	hash_filter = nxgep->hash_filter;
5887 	j = mchash / HASH_REG_WIDTH;
5888 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
5889 	hash_filter->hash_filter_regs[j] |= hash_bit;
5890 	hash_filter->hash_bit_ref_cnt[mchash]++;
5891 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
5892 		hash_filter->hash_ref_cnt++;
5893 	}
5894 
5895 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
5896 	if (rs != NPI_SUCCESS)
5897 		goto fail;
5898 
5899 	RW_EXIT(&nxgep->filter_lock);
5900 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
5901 	return (NXGE_OK);
5902 fail:
5903 	RW_EXIT(&nxgep->filter_lock);
5904 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
5905 	    "Unable to add multicast address"));
5906 	return (status);
5907 }
5908 
5909 /* Remove a multicast address entry from the HW hash table */
5910 
5911 nxge_status_t
5912 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5913 {
5914 	uint32_t mchash;
5915 	p_hash_filter_t hash_filter;
5916 	uint16_t hash_bit;
5917 	uint_t j;
5918 	nxge_status_t status = NXGE_OK;
5919 	npi_status_t rs;
5920 
5921 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
5922 	RW_ENTER_WRITER(&nxgep->filter_lock);
5923 	mchash = crc32_mchash(addrp);
5924 	if (nxgep->hash_filter == NULL) {
5925 		NXGE_DEBUG_MSG((NULL, STR_CTL,
5926 		    "Hash filter already de_allocated."));
5927 		RW_EXIT(&nxgep->filter_lock);
5928 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
5929 		return (NXGE_OK);
5930 	}
5931 	hash_filter = nxgep->hash_filter;
5932 	hash_filter->hash_bit_ref_cnt[mchash]--;
5933 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
5934 		j = mchash / HASH_REG_WIDTH;
5935 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
5936 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
5937 		hash_filter->hash_ref_cnt--;
5938 	}
5939 
5940 	if (hash_filter->hash_ref_cnt == 0) {
5941 		NXGE_DEBUG_MSG((NULL, STR_CTL,
5942 		    "De-allocating hash filter storage."));
5943 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
5944 		nxgep->hash_filter = NULL;
5945 	}
5946 
5947 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
5948 	if (rs != NPI_SUCCESS)
5949 		goto fail;
5950 
5951 	RW_EXIT(&nxgep->filter_lock);
5952 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
5953 
5954 	return (NXGE_OK);
5955 fail:
5956 	RW_EXIT(&nxgep->filter_lock);
5957 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
5958 	    "Unable to remove multicast address"));
5959 
5960 	return (status);
5961 }
5962 
5963 /* Set MAC address into MAC address HW registers */
5964 
5965 nxge_status_t
5966 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5967 {
5968 	nxge_status_t status = NXGE_OK;
5969 
5970 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
5971 
5972 	MUTEX_ENTER(&nxgep->ouraddr_lock);
5973 	/*
5974 	 * Exit if the address is same as ouraddr or multicast or broadcast
5975 	 */
5976 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
5977 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
5978 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
5979 		goto nxge_set_mac_addr_exit;
5980 	}
5981 	nxgep->ouraddr = *addrp;
5982 	/*
5983 	 * Set new interface local address and re-init device.
5984 	 * This is destructive to any other streams attached
5985 	 * to this device.
5986 	 */
5987 	RW_ENTER_WRITER(&nxgep->filter_lock);
5988 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
5989 		goto fail;
5990 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
5991 		goto fail;
5992 
5993 	RW_EXIT(&nxgep->filter_lock);
5994 	MUTEX_EXIT(&nxgep->ouraddr_lock);
5995 	goto nxge_set_mac_addr_end;
5996 nxge_set_mac_addr_exit:
5997 	MUTEX_EXIT(&nxgep->ouraddr_lock);
5998 nxge_set_mac_addr_end:
5999 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
6000 
6001 	return (NXGE_OK);
6002 fail:
6003 	MUTEX_EXIT(&nxgep->ouraddr_lock);
6004 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
6005 	    "Unable to set mac address"));
6006 	return (status);
6007 }
6008 
6009 static
6010 check_link_state_t
6011 nxge_check_link_stop(nxge_t *nxge)
6012 {
6013 	/* If the poll has been cancelled, return STOP. */
6014 	MUTEX_ENTER(&nxge->poll_lock);
6015 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
6016 		nxge->poll_state = LINK_MONITOR_STOP;
6017 		nxge->nxge_link_poll_timerid = 0;
6018 		cv_broadcast(&nxge->poll_cv);
6019 		MUTEX_EXIT(&nxge->poll_lock);
6020 
6021 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
6022 		    "nxge_check_%s_link(port<%d>) stopped.",
6023 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
6024 		    nxge->mac.portnum));
6025 		return (CHECK_LINK_STOP);
6026 	}
6027 	MUTEX_EXIT(&nxge->poll_lock);
6028 
6029 	return (CHECK_LINK_RESCHEDULE);
6030 }
6031 
6032 /*
6033  * Check status of MII (MIF or PCS) link.
6034  * This function is called once per second, that is because this function
6035  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
6036  * call this function recursively.
6037  */
6038 static nxge_status_t
6039 nxge_check_mii_link(p_nxge_t nxgep)
6040 {
6041 	mii_bmsr_t bmsr_ints, bmsr_data;
6042 	mii_anlpar_t anlpar;
6043 	mii_gsr_t gsr;
6044 	p_mii_regs_t mii_regs;
6045 	nxge_status_t status = NXGE_OK;
6046 	uint8_t portn;
6047 	nxge_link_state_t link_up;
6048 
6049 	if (nxgep->nxge_magic != NXGE_MAGIC)
6050 		return (NXGE_ERROR);
6051 
6052 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6053 		return (NXGE_OK);
6054 
6055 	portn = nxgep->mac.portnum;
6056 
6057 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
6058 	    portn));
6059 
6060 	mii_regs = NULL;
6061 
6062 	RW_ENTER_WRITER(&nxgep->filter_lock);
6063 
6064 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
6065 		goto nxge_check_mii_link_exit;
6066 
6067 	switch (nxgep->mac.portmode) {
6068 	default:
6069 		bmsr_data.value = 0;
6070 		if ((status = nxge_mii_read(nxgep,
6071 		    nxgep->statsp->mac_stats.xcvr_portn,
6072 #if defined(__i386)
6073 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
6074 #else
6075 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
6076 #endif
6077 		    &bmsr_data.value)) != NXGE_OK) {
6078 			goto fail;
6079 		}
6080 
6081 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6082 		    "==> nxge_check_mii_link port<0x%x> "
6083 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
6084 		    portn, bmsr_data.value, nxgep->bmsr.value));
6085 
6086 		if (nxgep->param_arr[param_autoneg].value) {
6087 			if ((status = nxge_mii_read(nxgep,
6088 			    nxgep->statsp->mac_stats.xcvr_portn,
6089 #if defined(__i386)
6090 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
6091 #else
6092 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
6093 #endif
6094 			    &gsr.value)) != NXGE_OK)
6095 				goto fail;
6096 			if ((status = nxge_mii_read(nxgep,
6097 			    nxgep->statsp->mac_stats.xcvr_portn,
6098 #if defined(__i386)
6099 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
6100 #else
6101 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
6102 #endif
6103 			    &anlpar.value)) != NXGE_OK)
6104 				goto fail;
6105 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
6106 
6107 				if (nxgep->statsp->mac_stats.link_up &&
6108 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
6109 				    gsr.bits.link_1000fdx) ||
6110 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
6111 				    gsr.bits.link_1000hdx) ||
6112 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
6113 				    anlpar.bits.cap_100T4) ||
6114 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
6115 				    anlpar.bits.cap_100fdx) ||
6116 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
6117 				    anlpar.bits.cap_100hdx) ||
6118 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
6119 				    anlpar.bits.cap_10fdx) ||
6120 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
6121 				    anlpar.bits.cap_10hdx))) {
6122 					bmsr_data.bits.link_status = 0;
6123 				}
6124 			}
6125 		}
6126 
6127 		/* Workaround for link down issue */
6128 		if (bmsr_data.value == 0) {
6129 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
6130 			goto nxge_check_mii_link_exit;
6131 		}
6132 
6133 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6134 		    "==> nxge_check_mii_link port<0x%x> :"
6135 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
6136 		    portn, nxgep->bmsr.value, bmsr_data.value));
6137 
6138 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
6139 		nxgep->bmsr.value = bmsr_data.value;
6140 
6141 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6142 		    "==> nxge_check_mii_link port<0x%x> CALLING "
6143 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
6144 		    portn, bmsr_data.value, bmsr_ints.value));
6145 
6146 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
6147 		    &link_up)) != NXGE_OK) {
6148 			goto fail;
6149 		}
6150 		break;
6151 
6152 	case PORT_1G_SERDES:
6153 		/*
6154 		 * Above default is for all cases except PORT_1G_SERDES.
6155 		 * The default case gets information from the PHY, but a
6156 		 * nxge whose portmode equals PORT_1G_SERDES does not
6157 		 * have a PHY.
6158 		 */
6159 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6160 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
6161 		nxge_pcs_check(nxgep, portn, &link_up);
6162 		break;
6163 	}
6164 
6165 nxge_check_mii_link_exit:
6166 	RW_EXIT(&nxgep->filter_lock);
6167 	if (link_up == LINK_IS_UP) {
6168 		nxge_link_is_up(nxgep);
6169 	} else if (link_up == LINK_IS_DOWN) {
6170 		nxge_link_is_down(nxgep);
6171 	}
6172 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6173 
6174 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
6175 	    portn));
6176 	return (NXGE_OK);
6177 
6178 fail:
6179 	RW_EXIT(&nxgep->filter_lock);
6180 
6181 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6182 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6183 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
6184 	return (status);
6185 }
6186 
6187 /*ARGSUSED*/
6188 static nxge_status_t
6189 nxge_check_10g_link(p_nxge_t nxgep)
6190 {
6191 	uint8_t		portn;
6192 	nxge_status_t	status = NXGE_OK;
6193 	boolean_t	link_up;
6194 	uint32_t	val;
6195 	npi_status_t	rs;
6196 
6197 	if (nxgep->nxge_magic != NXGE_MAGIC)
6198 		return (NXGE_ERROR);
6199 
6200 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6201 		return (NXGE_OK);
6202 
6203 	portn = nxgep->mac.portnum;
6204 	val = 0;
6205 	rs = NPI_SUCCESS;
6206 
6207 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
6208 	    portn));
6209 
6210 	switch (nxgep->mac.portmode) {
6211 	default:
6212 		/*
6213 		 * Check if the phy is present in case of hot swappable phy
6214 		 */
6215 		if (nxgep->hot_swappable_phy) {
6216 			boolean_t phy_present_now = B_FALSE;
6217 
6218 			if (nxge_hswap_phy_present(nxgep, portn))
6219 				phy_present_now = B_TRUE;
6220 
6221 			/* Check back-to-back XAUI connect to detect Opus NEM */
6222 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
6223 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
6224 			if (rs != 0)
6225 				goto fail;
6226 
6227 			link_up = B_FALSE;
6228 			if (val & XPCS_STATUS_LANE_ALIGN) {
6229 				link_up = B_TRUE;
6230 			}
6231 
6232 			if (nxgep->phy_absent) {
6233 				if (phy_present_now) {
6234 				/*
6235 				 * Detect, Initialize phy and do link up
6236 				 * set xcvr vals, link_init, nxge_init
6237 				 */
6238 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6239 					    "Hot swappable phy DETECTED!!"));
6240 					nxgep->phy_absent = B_FALSE;
6241 					(void) nxge_xcvr_find(nxgep);
6242 					(void) nxge_link_init(nxgep);
6243 					if (!(nxgep->drv_state &
6244 					    STATE_HW_INITIALIZED)) {
6245 						status = nxge_init(nxgep);
6246 						if (status != NXGE_OK) {
6247 							NXGE_ERROR_MSG((nxgep,
6248 							    NXGE_ERR_CTL,
6249 							    "Hot swappable "
6250 							    "phy present, but"
6251 							    " driver init"
6252 							    "  failed..."));
6253 							goto fail;
6254 						}
6255 					}
6256 				} else if (link_up) { /* XAUI linkup, no PHY */
6257 					/*
6258 					 * This is the back-to-back XAUI
6259 					 * connect case for Opus NEM.
6260 					 */
6261 					nxgep->statsp->mac_stats.xcvr_inuse =
6262 					    XPCS_XCVR;
6263 					nxgep->mac.portmode = PORT_10G_SERDES;
6264 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6265 					    "HSP 10G Serdes DETECTED!!"));
6266 					break;
6267 				}
6268 
6269 				if (nxgep->link_notify &&
6270 				    nxgep->link_check_count > 3 &&
6271 				    nxgep->nxge_mac_state == NXGE_MAC_STARTED ||
6272 				    nxgep->statsp->mac_stats.link_up == 1) {
6273 					nxgep->statsp->mac_stats.link_up = 0;
6274 					nxgep->statsp->mac_stats.link_speed = 0;
6275 					nxgep->statsp->mac_stats.link_duplex =
6276 					    0;
6277 
6278 					nxge_link_is_down(nxgep);
6279 					nxgep->link_notify = B_FALSE;
6280 				}
6281 
6282 				goto start_link_check;
6283 
6284 			} else if (!phy_present_now) {
6285 				/*
6286 				 * Phy gone, bring link down reset xcvr vals
6287 				 */
6288 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6289 				    "Hot swappable phy REMOVED!!"));
6290 				nxgep->phy_absent = B_TRUE;
6291 				nxgep->statsp->mac_stats.link_up = 0;
6292 				nxgep->statsp->mac_stats.link_speed = 0;
6293 				nxgep->statsp->mac_stats.link_duplex = 0;
6294 				nxge_link_is_down(nxgep);
6295 				nxgep->link_notify = B_FALSE;
6296 
6297 				(void) nxge_xcvr_find(nxgep);
6298 
6299 				goto start_link_check;
6300 
6301 			}
6302 		}
6303 
6304 		switch (nxgep->chip_id) {
6305 		case MRVL88X201X_CHIP_ID:
6306 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
6307 			break;
6308 		case NLP2020_CHIP_ID:
6309 			status = nxge_check_nlp2020_link(nxgep, &link_up);
6310 			break;
6311 		default:
6312 			status = nxge_check_bcm8704_link(nxgep, &link_up);
6313 			break;
6314 		}
6315 
6316 		if (status != NXGE_OK)
6317 			goto fail;
6318 		break;
6319 	case PORT_10G_SERDES:
6320 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6321 		    XPCS_REG_STATUS, &val);
6322 		if (rs != 0)
6323 			goto fail;
6324 
6325 		link_up = B_FALSE;
6326 		if (val & XPCS_STATUS_LANE_ALIGN) {
6327 			link_up = B_TRUE;
6328 		}
6329 
6330 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6331 		    "==> nxge_check_10g_link port<%d> "
6332 		    "XPCS_REG_STATUS2 0x%x link_up %d",
6333 		    portn, val, link_up));
6334 
6335 		break;
6336 	}
6337 
6338 	if (link_up) {
6339 		if ((nxgep->link_notify &&
6340 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6341 		    nxgep->statsp->mac_stats.link_up == 0) {
6342 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
6343 				goto fail;
6344 			nxgep->statsp->mac_stats.link_up = 1;
6345 			nxgep->statsp->mac_stats.link_speed = 10000;
6346 			nxgep->statsp->mac_stats.link_duplex = 2;
6347 
6348 			nxge_link_is_up(nxgep);
6349 			nxgep->link_notify = B_FALSE;
6350 		}
6351 	} else {
6352 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6353 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6354 		    nxgep->statsp->mac_stats.link_up == 1) {
6355 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
6356 				goto fail;
6357 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6358 			    "Link down cable problem"));
6359 			nxgep->statsp->mac_stats.link_up = 0;
6360 			nxgep->statsp->mac_stats.link_speed = 0;
6361 			nxgep->statsp->mac_stats.link_duplex = 0;
6362 
6363 			nxge_link_is_down(nxgep);
6364 			nxgep->link_notify = B_FALSE;
6365 
6366 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
6367 				/*
6368 				 * NEM was unplugged, set up xcvr table
6369 				 * to find another xcvr in the future.
6370 				 */
6371 				(void) nxge_xcvr_find(nxgep);
6372 			}
6373 		}
6374 	}
6375 
6376 start_link_check:
6377 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6378 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
6379 	    portn));
6380 	return (NXGE_OK);
6381 
6382 fail:
6383 	(void) nxge_check_link_stop(nxgep);
6384 
6385 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6386 	    "nxge_check_10g_link: Failed to check link port<%d>",
6387 	    portn));
6388 	return (status);
6389 }
6390 
6391 
6392 /* Declare link down */
6393 
6394 void
6395 nxge_link_is_down(p_nxge_t nxgep)
6396 {
6397 	p_nxge_stats_t statsp;
6398 	char link_stat_msg[64];
6399 
6400 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
6401 
6402 	statsp = nxgep->statsp;
6403 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
6404 	    statsp->mac_stats.xcvr_portn);
6405 
6406 	if (nxge_no_msg == B_FALSE) {
6407 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
6408 	}
6409 
6410 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
6411 
6412 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
6413 }
6414 
6415 /* Declare link up */
6416 
6417 void
6418 nxge_link_is_up(p_nxge_t nxgep)
6419 {
6420 	p_nxge_stats_t statsp;
6421 	char link_stat_msg[64];
6422 	uint32_t val;
6423 
6424 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
6425 
6426 	statsp = nxgep->statsp;
6427 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
6428 	    statsp->mac_stats.xcvr_portn,
6429 	    statsp->mac_stats.link_speed);
6430 
6431 	if (statsp->mac_stats.link_T4)
6432 		(void) strcat(link_stat_msg, "T4");
6433 	else if (statsp->mac_stats.link_duplex == 2)
6434 		(void) strcat(link_stat_msg, "full duplex");
6435 	else
6436 		(void) strcat(link_stat_msg, "half duplex");
6437 
6438 
6439 	/* Clean up symbol errors incurred during link transition */
6440 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
6441 	    (nxgep->mac.portmode == PORT_10G_COPPER) ||
6442 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
6443 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6444 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
6445 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6446 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
6447 	}
6448 
6449 	/*
6450 	 * If the driver was plumbed without a link (therefore auto-negotiation
6451 	 * could not complete), the driver will detect a link up when a cable
6452 	 * conneting to a link partner is plugged into the port. By the time
6453 	 * link-up is detected, auto-negotiation should have completed (The
6454 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
6455 	 * configure the Neptune/NIU according to the newly negotiated speed.
6456 	 * This is necessary only for the TN1010 basad device because only the
6457 	 * TN1010 supports dual speeds.
6458 	 */
6459 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
6460 	    nxgep->mac.portmode == PORT_10G_TN1010) {
6461 
6462 		(void) nxge_set_tn1010_param(nxgep);
6463 
6464 		/*
6465 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
6466 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
6467 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
6468 		 */
6469 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
6470 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6471 			    "nxge_link_is_up: nxge_xcvr_find failed"));
6472 		}
6473 
6474 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
6475 		if (nxge_link_init(nxgep) != NXGE_OK) {
6476 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6477 			    "nxge_link_is_up: nxge_link_init failed"));
6478 		}
6479 
6480 		/*
6481 		 * nxge_mac_init calls many subroutines including
6482 		 * nxge_xif_init which sets XGMII or GMII mode
6483 		 */
6484 		if (nxge_mac_init(nxgep) != NXGE_OK) {
6485 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6486 			    "nxge_link_is_up: nxge_mac_init failed"));
6487 		}
6488 	} else {
6489 		(void) nxge_xif_init(nxgep);
6490 	}
6491 
6492 	if (nxge_no_msg == B_FALSE) {
6493 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
6494 	}
6495 
6496 	mac_link_update(nxgep->mach, LINK_STATE_UP);
6497 
6498 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
6499 }
6500 
6501 #ifdef NXGE_DEBUG
6502 /* Dump all TN1010 Status registers */
6503 static void
6504 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
6505 {
6506 	uint16_t val;
6507 
6508 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6509 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
6510 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
6511 
6512 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6513 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
6514 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
6515 
6516 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6517 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
6518 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
6519 
6520 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6521 	    TN1010_PCS_DEV_ADDR, 1, &val);
6522 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
6523 
6524 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6525 	    TN1010_PCS_DEV_ADDR, 8, &val);
6526 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
6527 
6528 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6529 	    TN1010_PCS_DEV_ADDR, 32, &val);
6530 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
6531 
6532 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6533 	    TN1010_PCS_DEV_ADDR, 33, &val);
6534 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
6535 
6536 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6537 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
6538 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
6539 
6540 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6541 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
6542 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
6543 
6544 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6545 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
6546 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
6547 
6548 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6549 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
6550 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
6551 
6552 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6553 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
6554 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
6555 
6556 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6557 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
6558 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
6559 
6560 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6561 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
6562 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
6563 
6564 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6565 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
6566 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
6567 
6568 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6569 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
6570 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
6571 
6572 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
6573 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
6574 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
6575 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
6576 }
6577 #endif
6578 
6579 /*
6580  * Calculate the bit in the multicast address filter
6581  * that selects the given * address.
6582  * Note: For GEM, the last 8-bits are used.
6583  */
6584 uint32_t
6585 crc32_mchash(p_ether_addr_t addr)
6586 {
6587 	uint8_t *cp;
6588 	uint32_t crc;
6589 	uint32_t c;
6590 	int byte;
6591 	int bit;
6592 
6593 	cp = (uint8_t *)addr;
6594 	crc = (uint32_t)0xffffffff;
6595 	for (byte = 0; byte < 6; byte++) {
6596 		c = (uint32_t)cp[byte];
6597 		for (bit = 0; bit < 8; bit++) {
6598 			if ((c & 0x1) ^ (crc & 0x1))
6599 				crc = (crc >> 1)^0xedb88320;
6600 			else
6601 				crc = (crc >> 1);
6602 			c >>= 1;
6603 		}
6604 	}
6605 	return ((~crc) >> (32 - HASH_BITS));
6606 }
6607 
6608 /* Reset serdes */
6609 
6610 nxge_status_t
6611 nxge_serdes_reset(p_nxge_t nxgep)
6612 {
6613 	npi_handle_t		handle;
6614 
6615 	handle = nxgep->npi_handle;
6616 
6617 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
6618 	drv_usecwait(500);
6619 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
6620 
6621 	return (NXGE_OK);
6622 }
6623 
6624 /*
6625  * This function monitors link status using interrupt or polling.
6626  * It calls nxgep->xcvr.check_link, a member function of
6627  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
6628  * function back, that is why the check_link routine is
6629  * executed periodically.
6630  */
6631 nxge_status_t
6632 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
6633 {
6634 	nxge_status_t status = NXGE_OK;
6635 
6636 	/* If we are a guest domain driver, don't bother. */
6637 	if (isLDOMguest(nxgep))
6638 		return (status);
6639 
6640 	/*
6641 	 * Return immediately if this is an imaginary XMAC port.
6642 	 * (At least, we don't have 4-port XMAC cards yet.)
6643 	 */
6644 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
6645 	    nxgep->mac.portmode == PORT_10G_COPPER ||
6646 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
6647 	    (nxgep->mac.portnum > 1))
6648 		return (NXGE_OK);
6649 
6650 	if (nxgep->statsp == NULL) {
6651 		/* stats has not been allocated. */
6652 		return (NXGE_OK);
6653 	}
6654 	/* Don't check link if we're in internal loopback mode */
6655 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
6656 		return (NXGE_OK);
6657 
6658 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6659 	    "==> nxge_link_monitor port<%d> enable=%d",
6660 	    nxgep->mac.portnum, enable));
6661 	if (enable == LINK_MONITOR_START) {
6662 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
6663 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
6664 			    != NXGE_OK)
6665 				goto fail;
6666 		} else {
6667 			timeout_id_t timerid;
6668 			/*
6669 			 * check_link_stop means "Stop the link check", so
6670 			 * we return without starting the timer.
6671 			 */
6672 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
6673 				return (NXGE_OK);
6674 
6675 			/*
6676 			 * Otherwise fire the timer for the nxge to check
6677 			 * the link using the check_link function
6678 			 * of the nxge_xcvr_table and pass "nxgep" as the
6679 			 * argument to the check_link function.
6680 			 */
6681 			if (nxgep->xcvr.check_link) {
6682 				timerid = timeout((fptrv_t)(uintptr_t)
6683 				    (nxgep->xcvr.check_link),
6684 				    nxgep,
6685 				    drv_usectohz(LINK_MONITOR_PERIOD));
6686 				MUTEX_ENTER(&nxgep->poll_lock);
6687 				nxgep->nxge_link_poll_timerid = timerid;
6688 				MUTEX_EXIT(&nxgep->poll_lock);
6689 				nxgep->link_check_count ++;
6690 			} else {
6691 				return (NXGE_ERROR);
6692 			}
6693 		}
6694 	} else {
6695 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
6696 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
6697 			    != NXGE_OK)
6698 				goto fail;
6699 		} else {
6700 			clock_t rv;
6701 
6702 			MUTEX_ENTER(&nxgep->poll_lock);
6703 
6704 			/* If <timerid> == 0, the link monitor has */
6705 			/* never been started, or just now stopped. */
6706 			if (nxgep->nxge_link_poll_timerid == 0) {
6707 				MUTEX_EXIT(&nxgep->poll_lock);
6708 				return (NXGE_OK);
6709 			}
6710 
6711 			nxgep->poll_state = LINK_MONITOR_STOPPING;
6712 			rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
6713 			    drv_usectohz(LM_WAIT_MULTIPLIER *
6714 			    LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
6715 			if (rv == -1) {
6716 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6717 				    "==> stopping port %d: "
6718 				    "cv_timedwait(%d) timed out",
6719 				    nxgep->mac.portnum, nxgep->poll_state));
6720 				nxgep->poll_state = LINK_MONITOR_STOP;
6721 				nxgep->nxge_link_poll_timerid = 0;
6722 			}
6723 
6724 			MUTEX_EXIT(&nxgep->poll_lock);
6725 		}
6726 	}
6727 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6728 	    "<== nxge_link_monitor port<%d> enable=%d",
6729 	    nxgep->mac.portnum, enable));
6730 
6731 	return (NXGE_OK);
6732 fail:
6733 	return (status);
6734 
6735 }
6736 
6737 nxge_status_t
6738 nxge_check_tn1010_link(p_nxge_t nxgep)
6739 {
6740 	nxge_status_t	status = NXGE_OK;
6741 	nxge_link_state_t link_up;
6742 
6743 	if (nxgep->nxge_magic != NXGE_MAGIC) {
6744 		/* magic is 0 if driver is not attached */
6745 		return (NXGE_ERROR);
6746 	}
6747 
6748 	/* Link has been stopped, no need to continue */
6749 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
6750 		return (NXGE_OK);
6751 	}
6752 
6753 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
6754 		goto nxge_check_tn1010_link_exit;
6755 
6756 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
6757 		goto fail;
6758 
6759 nxge_check_tn1010_link_exit:
6760 	if (link_up == LINK_IS_UP)
6761 		nxge_link_is_up(nxgep);
6762 	else if (link_up == LINK_IS_DOWN)
6763 		nxge_link_is_down(nxgep);
6764 
6765 	/*
6766 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
6767 	 * which could be THIS function.
6768 	 */
6769 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6770 
6771 	return (NXGE_OK);
6772 
6773 fail:
6774 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
6775 
6776 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6777 	    "nxge_check_tn1010_link: Failed to check link"));
6778 	return (status);
6779 }
6780 
6781 
6782 /*
6783  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
6784  */
6785 static nxge_status_t
6786 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
6787 {
6788 	nxge_status_t	status = NXGE_OK;
6789 	p_nxge_stats_t	statsp;
6790 	uint8_t		phy_port_addr, portn;
6791 	uint16_t	val;
6792 
6793 	*link_up = LINK_NO_CHANGE;
6794 
6795 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
6796 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
6797 	statsp = nxgep->statsp;
6798 
6799 	/* Check if link is up */
6800 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
6801 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
6802 	    != NXGE_OK) {
6803 		goto fail;
6804 	}
6805 	/*
6806 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
6807 	 * portmode and link_speed
6808 	 */
6809 	if (val & TN1010_AN_LINK_STAT_BIT) {
6810 		if ((nxgep->link_notify &&
6811 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6812 		    nxgep->statsp->mac_stats.link_up == 0) {
6813 			statsp->mac_stats.link_up = 1;
6814 			statsp->mac_stats.link_duplex = 2;
6815 			*link_up = LINK_IS_UP;
6816 			nxgep->link_notify = B_FALSE;
6817 		}
6818 	} else {
6819 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6820 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
6821 		    nxgep->statsp->mac_stats.link_up == 1) {
6822 			statsp->mac_stats.link_up = 0;
6823 			statsp->mac_stats.link_speed = 0;
6824 			statsp->mac_stats.link_duplex = 0;
6825 			*link_up = LINK_IS_DOWN;
6826 			nxgep->link_notify = B_FALSE;
6827 		}
6828 	}
6829 	return (NXGE_OK);
6830 
6831 fail:
6832 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6833 	    "nxge_tn1010_check: Unable to check TN1010"));
6834 	return (status);
6835 }
6836 
6837 
6838 /* Set promiscous mode */
6839 
6840 nxge_status_t
6841 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
6842 {
6843 	nxge_status_t status = NXGE_OK;
6844 
6845 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
6846 
6847 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
6848 
6849 	RW_ENTER_WRITER(&nxgep->filter_lock);
6850 
6851 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
6852 		goto fail;
6853 	}
6854 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
6855 		goto fail;
6856 	}
6857 
6858 	RW_EXIT(&nxgep->filter_lock);
6859 
6860 	if (on)
6861 		nxgep->statsp->mac_stats.promisc = B_TRUE;
6862 	else
6863 		nxgep->statsp->mac_stats.promisc = B_FALSE;
6864 
6865 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
6866 
6867 	return (NXGE_OK);
6868 fail:
6869 	RW_EXIT(&nxgep->filter_lock);
6870 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
6871 	    "Unable to set promisc (%d)", on));
6872 
6873 	return (status);
6874 }
6875 
6876 /*ARGSUSED*/
6877 uint_t
6878 nxge_mif_intr(void *arg1, void *arg2)
6879 {
6880 #ifdef	NXGE_DEBUG
6881 	p_nxge_t		nxgep = (p_nxge_t)arg2;
6882 #endif
6883 #if NXGE_MIF
6884 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
6885 	uint32_t		status;
6886 	npi_handle_t		handle;
6887 	uint8_t			portn;
6888 	p_nxge_stats_t		statsp;
6889 #endif
6890 
6891 #ifdef	NXGE_MIF
6892 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
6893 		nxgep = ldvp->nxgep;
6894 	}
6895 	nxgep = ldvp->nxgep;
6896 #endif
6897 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
6898 
6899 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
6900 	return (DDI_INTR_CLAIMED);
6901 
6902 mif_intr_fail:
6903 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
6904 	return (DDI_INTR_UNCLAIMED);
6905 }
6906 
6907 /*ARGSUSED*/
6908 uint_t
6909 nxge_mac_intr(void *arg1, void *arg2)
6910 {
6911 	p_nxge_t		nxgep = (p_nxge_t)arg2;
6912 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
6913 	p_nxge_ldg_t		ldgp;
6914 	uint32_t		status;
6915 	npi_handle_t		handle;
6916 	uint8_t			portn;
6917 	p_nxge_stats_t		statsp;
6918 	npi_status_t		rs = NPI_SUCCESS;
6919 
6920 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
6921 		nxgep = ldvp->nxgep;
6922 	}
6923 
6924 	ldgp = ldvp->ldgp;
6925 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
6926 	    "group %d", ldgp->ldg));
6927 
6928 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
6929 	/*
6930 	 * This interrupt handler is for a specific
6931 	 * mac port.
6932 	 */
6933 	statsp = (p_nxge_stats_t)nxgep->statsp;
6934 	portn = nxgep->mac.portnum;
6935 
6936 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
6937 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
6938 
6939 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
6940 		rs = npi_xmac_tx_get_istatus(handle, portn,
6941 		    (xmac_tx_iconfig_t *)&status);
6942 		if (rs != NPI_SUCCESS)
6943 			goto npi_fail;
6944 		if (status & ICFG_XMAC_TX_ALL) {
6945 			if (status & ICFG_XMAC_TX_UNDERRUN) {
6946 				statsp->xmac_stats.tx_underflow_err++;
6947 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
6948 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
6949 			}
6950 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
6951 				statsp->xmac_stats.tx_maxpktsize_err++;
6952 				/*
6953 				 * Do not send FMA ereport because this
6954 				 * error does not indicate HW failure.
6955 				 */
6956 			}
6957 			if (status & ICFG_XMAC_TX_OVERFLOW) {
6958 				statsp->xmac_stats.tx_overflow_err++;
6959 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
6960 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
6961 			}
6962 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
6963 				statsp->xmac_stats.tx_fifo_xfr_err++;
6964 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
6965 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
6966 			}
6967 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
6968 				statsp->xmac_stats.tx_byte_cnt +=
6969 				    XTXMAC_BYTE_CNT_MASK;
6970 			}
6971 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
6972 				statsp->xmac_stats.tx_frame_cnt +=
6973 				    XTXMAC_FRM_CNT_MASK;
6974 			}
6975 		}
6976 
6977 		rs = npi_xmac_rx_get_istatus(handle, portn,
6978 		    (xmac_rx_iconfig_t *)&status);
6979 		if (rs != NPI_SUCCESS)
6980 			goto npi_fail;
6981 		if (status & ICFG_XMAC_RX_ALL) {
6982 			if (status & ICFG_XMAC_RX_OVERFLOW)
6983 				statsp->xmac_stats.rx_overflow_err++;
6984 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
6985 				statsp->xmac_stats.rx_underflow_err++;
6986 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
6987 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
6988 			}
6989 			/*
6990 			 * Do not send FMA ereport for the following 3 errors
6991 			 * because they do not indicate HW failures.
6992 			 */
6993 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
6994 				statsp->xmac_stats.rx_crc_err_cnt +=
6995 				    XRXMAC_CRC_ER_CNT_MASK;
6996 			}
6997 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
6998 				statsp->xmac_stats.rx_len_err_cnt +=
6999 				    MAC_LEN_ER_CNT_MASK;
7000 			}
7001 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
7002 				statsp->xmac_stats.rx_viol_err_cnt +=
7003 				    XRXMAC_CD_VIO_CNT_MASK;
7004 			}
7005 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
7006 				statsp->xmac_stats.rx_byte_cnt +=
7007 				    XRXMAC_BT_CNT_MASK;
7008 			}
7009 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
7010 				statsp->xmac_stats.rx_hist1_cnt +=
7011 				    XRXMAC_HIST_CNT1_MASK;
7012 			}
7013 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
7014 				statsp->xmac_stats.rx_hist2_cnt +=
7015 				    XRXMAC_HIST_CNT2_MASK;
7016 			}
7017 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
7018 				statsp->xmac_stats.rx_hist3_cnt +=
7019 				    XRXMAC_HIST_CNT3_MASK;
7020 			}
7021 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
7022 				statsp->xmac_stats.rx_hist4_cnt +=
7023 				    XRXMAC_HIST_CNT4_MASK;
7024 			}
7025 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
7026 				statsp->xmac_stats.rx_hist5_cnt +=
7027 				    XRXMAC_HIST_CNT5_MASK;
7028 			}
7029 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
7030 				statsp->xmac_stats.rx_hist6_cnt +=
7031 				    XRXMAC_HIST_CNT6_MASK;
7032 			}
7033 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
7034 				statsp->xmac_stats.rx_broadcast_cnt +=
7035 				    XRXMAC_BC_FRM_CNT_MASK;
7036 			}
7037 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
7038 				statsp->xmac_stats.rx_mult_cnt +=
7039 				    XRXMAC_MC_FRM_CNT_MASK;
7040 			}
7041 			/*
7042 			 * Do not send FMA ereport for the following 3 errors
7043 			 * because they do not indicate HW failures.
7044 			 */
7045 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
7046 				statsp->xmac_stats.rx_frag_cnt +=
7047 				    XRXMAC_FRAG_CNT_MASK;
7048 			}
7049 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
7050 				statsp->xmac_stats.rx_frame_align_err_cnt +=
7051 				    XRXMAC_AL_ER_CNT_MASK;
7052 			}
7053 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
7054 				statsp->xmac_stats.rx_linkfault_err_cnt +=
7055 				    XMAC_LINK_FLT_CNT_MASK;
7056 			}
7057 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
7058 				statsp->xmac_stats.rx_remotefault_err++;
7059 			}
7060 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
7061 				statsp->xmac_stats.rx_localfault_err++;
7062 			}
7063 		}
7064 
7065 		rs = npi_xmac_ctl_get_istatus(handle, portn,
7066 		    (xmac_ctl_iconfig_t *)&status);
7067 		if (rs != NPI_SUCCESS)
7068 			goto npi_fail;
7069 		if (status & ICFG_XMAC_CTRL_ALL) {
7070 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
7071 				statsp->xmac_stats.rx_pause_cnt++;
7072 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
7073 				statsp->xmac_stats.tx_pause_state++;
7074 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
7075 				statsp->xmac_stats.tx_nopause_state++;
7076 		}
7077 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
7078 		rs = npi_bmac_tx_get_istatus(handle, portn,
7079 		    (bmac_tx_iconfig_t *)&status);
7080 		if (rs != NPI_SUCCESS)
7081 			goto npi_fail;
7082 		if (status & ICFG_BMAC_TX_ALL) {
7083 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
7084 				statsp->bmac_stats.tx_underrun_err++;
7085 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7086 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
7087 			}
7088 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
7089 				statsp->bmac_stats.tx_max_pkt_err++;
7090 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7091 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
7092 			}
7093 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
7094 				statsp->bmac_stats.tx_byte_cnt +=
7095 				    BTXMAC_BYTE_CNT_MASK;
7096 			}
7097 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
7098 				statsp->bmac_stats.tx_frame_cnt +=
7099 				    BTXMAC_FRM_CNT_MASK;
7100 			}
7101 		}
7102 
7103 		rs = npi_bmac_rx_get_istatus(handle, portn,
7104 		    (bmac_rx_iconfig_t *)&status);
7105 		if (rs != NPI_SUCCESS)
7106 			goto npi_fail;
7107 		if (status & ICFG_BMAC_RX_ALL) {
7108 			if (status & ICFG_BMAC_RX_OVERFLOW) {
7109 				statsp->bmac_stats.rx_overflow_err++;
7110 			}
7111 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
7112 				statsp->bmac_stats.rx_frame_cnt +=
7113 				    RXMAC_FRM_CNT_MASK;
7114 			}
7115 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
7116 				statsp->bmac_stats.rx_crc_err_cnt +=
7117 				    BMAC_CRC_ER_CNT_MASK;
7118 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7119 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
7120 			}
7121 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
7122 				statsp->bmac_stats.rx_len_err_cnt +=
7123 				    MAC_LEN_ER_CNT_MASK;
7124 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7125 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
7126 			}
7127 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
7128 				statsp->bmac_stats.rx_viol_err_cnt +=
7129 				    BMAC_CD_VIO_CNT_MASK;
7130 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7131 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
7132 			}
7133 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
7134 				statsp->bmac_stats.rx_byte_cnt +=
7135 				    BRXMAC_BYTE_CNT_MASK;
7136 			}
7137 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
7138 				statsp->bmac_stats.rx_align_err_cnt +=
7139 				    BMAC_AL_ER_CNT_MASK;
7140 				NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
7141 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
7142 			}
7143 
7144 			rs = npi_bmac_ctl_get_istatus(handle, portn,
7145 			    (bmac_ctl_iconfig_t *)&status);
7146 			if (rs != NPI_SUCCESS)
7147 				goto npi_fail;
7148 
7149 			if (status & ICFG_BMAC_CTL_ALL) {
7150 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
7151 					statsp->bmac_stats.rx_pause_cnt++;
7152 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
7153 					statsp->bmac_stats.tx_pause_state++;
7154 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
7155 					statsp->bmac_stats.tx_nopause_state++;
7156 			}
7157 		}
7158 
7159 	if (ldgp->nldvs == 1) {
7160 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
7161 		    B_TRUE, ldgp->ldg_timer);
7162 	}
7163 
7164 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
7165 	return (DDI_INTR_CLAIMED);
7166 
7167 npi_fail:
7168 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
7169 	return (DDI_INTR_UNCLAIMED);
7170 }
7171 
7172 nxge_status_t
7173 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
7174 {
7175 	uint8_t		phy_port_addr;
7176 	nxge_status_t	status = NXGE_OK;
7177 	boolean_t	rx_sig_ok;
7178 	boolean_t	pcs_blk_lock;
7179 	boolean_t	link_align;
7180 	uint16_t	val1, val2, val3;
7181 #ifdef	NXGE_DEBUG_SYMBOL_ERR
7182 	uint16_t	val_debug;
7183 	uint32_t	val;
7184 #endif
7185 
7186 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
7187 
7188 #ifdef	NXGE_DEBUG_SYMBOL_ERR
7189 	/* Check Device 3 Register Device 3 0xC809 */
7190 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
7191 	if ((val_debug & ~0x200) != 0) {
7192 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
7193 		    nxgep->mac.portnum, val_debug);
7194 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
7195 		    &val_debug);
7196 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
7197 		    nxgep->mac.portnum, val_debug);
7198 	}
7199 
7200 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7201 	    XPCS_REG_DESCWERR_COUNTER, &val);
7202 	if (val != 0)
7203 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
7204 
7205 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7206 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
7207 	if (val != 0)
7208 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
7209 
7210 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
7211 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
7212 	if (val != 0)
7213 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
7214 #endif
7215 
7216 	/* Check from BCM8704 if 10G link is up or down */
7217 
7218 	/* Check Device 1 Register 0xA bit0 */
7219 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
7220 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
7221 	if (status != NXGE_OK)
7222 		goto fail;
7223 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
7224 
7225 	/* Check Device 3 Register 0x20 bit0 */
7226 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
7227 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
7228 		goto fail;
7229 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
7230 
7231 	/* Check Device 4 Register 0x18 bit12 */
7232 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
7233 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
7234 	if (status != NXGE_OK)
7235 		goto fail;
7236 
7237 	switch (nxgep->chip_id) {
7238 	case BCM8704_CHIP_ID:
7239 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
7240 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
7241 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
7242 		break;
7243 	case BCM8706_CHIP_ID:
7244 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
7245 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
7246 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
7247 		    B_TRUE : B_FALSE;
7248 		break;
7249 	default:
7250 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
7251 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
7252 		goto fail;
7253 	}
7254 
7255 #ifdef	NXGE_DEBUG_ALIGN_ERR
7256 	/* Temp workaround for link down issue */
7257 	if (pcs_blk_lock == B_FALSE) {
7258 		if (val2 != 0x4) {
7259 			pcs_blk_lock = B_TRUE;
7260 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
7261 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
7262 		}
7263 	}
7264 
7265 	if (link_align == B_FALSE) {
7266 		if (val3 != 0x140f) {
7267 			link_align = B_TRUE;
7268 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
7269 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
7270 		}
7271 	}
7272 
7273 	if (rx_sig_ok == B_FALSE) {
7274 		if ((val2 == 0) || (val3 == 0)) {
7275 			rx_sig_ok = B_TRUE;
7276 			cmn_err(CE_NOTE,
7277 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
7278 			    nxgep->mac.portnum);
7279 		}
7280 	}
7281 #endif
7282 
7283 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
7284 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
7285 
7286 	return (NXGE_OK);
7287 fail:
7288 	return (status);
7289 }
7290 
7291 static nxge_status_t
7292 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
7293 {
7294 	uint8_t		phy;
7295 	nxge_status_t   status = NXGE_OK;
7296 	boolean_t	pma_status;
7297 	boolean_t	pcs_status;
7298 	boolean_t	xgxs_status;
7299 	uint16_t	val;
7300 
7301 	phy = nxgep->statsp->mac_stats.xcvr_portn;
7302 
7303 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
7304 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
7305 
7306 	*link_up = B_FALSE;
7307 
7308 	/* Check from Marvell 88X2011 if 10G link is up or down */
7309 
7310 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
7311 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
7312 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
7313 
7314 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7315 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
7316 
7317 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
7318 
7319 	/* Check PMC Register : 3.0001.2 == 1: read twice */
7320 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
7321 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
7322 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
7323 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
7324 
7325 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7326 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
7327 
7328 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
7329 
7330 	/* Check XGXS Register : 4.0018.[0-3,12] */
7331 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
7332 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
7333 
7334 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7335 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
7336 
7337 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
7338 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
7339 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
7340 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
7341 
7342 	*link_up = (pma_status && pcs_status && xgxs_status) ?
7343 	    B_TRUE : B_FALSE;
7344 
7345 fail:
7346 
7347 	if (*link_up == B_FALSE) {
7348 		/* PCS OFF */
7349 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
7350 	} else {
7351 		/* PCS Activity */
7352 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
7353 	}
7354 
7355 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7356 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
7357 
7358 	return (status);
7359 }
7360 
7361 static nxge_status_t
7362 nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up)
7363 {
7364 	uint8_t		phy;
7365 	nxge_status_t   status = NXGE_OK;
7366 	uint16_t	pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat;
7367 	uint8_t		connector = 0;
7368 
7369 	phy = nxgep->statsp->mac_stats.xcvr_portn;
7370 	*link_up = B_FALSE;
7371 
7372 	/* Check from Netlogic AEL2020 if 10G link is up or down */
7373 
7374 	status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR,
7375 	    NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig);
7376 	if (status != NXGE_OK)
7377 		goto fail;
7378 
7379 	status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR,
7380 	    NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1);
7381 	if (status != NXGE_OK)
7382 		goto fail;
7383 
7384 	status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR,
7385 	    NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat);
7386 	if (status != NXGE_OK)
7387 		goto fail;
7388 
7389 	if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) &&
7390 	    (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) &&
7391 	    (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC))
7392 		*link_up = B_TRUE;
7393 	/*
7394 	 * If previously link was down, check the connector type as
7395 	 * it might have been changed.
7396 	 */
7397 	if (nxgep->statsp->mac_stats.link_up == 0) {
7398 		(void) nxge_nlp2020_i2c_read(nxgep, phy,
7399 		    NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector);
7400 
7401 		switch (connector) {
7402 		case SFPP_FIBER:
7403 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7404 			    "nxge_check_nlp2020_link: SFPP_FIBER"));
7405 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
7406 				nxgep->mac.portmode = PORT_10G_FIBER;
7407 				(void) nxge_nlp2020_xcvr_init(nxgep);
7408 			}
7409 			break;
7410 		case QSFP_FIBER:
7411 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7412 			    "nxge_check_nlp2020_link: QSFP_FIBER"));
7413 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
7414 				nxgep->mac.portmode = PORT_10G_FIBER;
7415 				(void) nxge_nlp2020_xcvr_init(nxgep);
7416 			}
7417 			break;
7418 		case QSFP_COPPER_TWINAX:
7419 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7420 			    "nxge_check_nlp2020_link: "
7421 			    "QSFP_COPPER_TWINAX/"
7422 			    "SFPP_COPPER_TWINAX"));
7423 			if (nxgep->mac.portmode != PORT_10G_COPPER) {
7424 				nxgep->mac.portmode = PORT_10G_COPPER;
7425 				(void) nxge_nlp2020_xcvr_init(nxgep);
7426 			} else {
7427 				uint8_t len = 0;
7428 				(void) nxge_nlp2020_i2c_read(nxgep, phy,
7429 				    NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG,
7430 				    &len);
7431 				if (((len < 7) &&
7432 				    (nxgep->nlp_conn ==
7433 				    NXGE_NLP_CONN_COPPER_7M_ABOVE)) ||
7434 				    ((len >= 7) &&
7435 				    (nxgep->nlp_conn ==
7436 				    NXGE_NLP_CONN_COPPER_LT_7M))) {
7437 					(void) nxge_nlp2020_xcvr_init(nxgep);
7438 				}
7439 			}
7440 			break;
7441 		default:
7442 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7443 			    "nxge_check_nlp2020_link: Unknown type [0x%x] "
7444 			    "detected...setting to QSFP_FIBER",
7445 			    connector));
7446 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
7447 				nxgep->mac.portmode = PORT_10G_FIBER;
7448 				(void) nxge_nlp2020_xcvr_init(nxgep);
7449 			}
7450 			break;
7451 		}
7452 	}
7453 fail:
7454 	if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) {
7455 		/* Turn link LED OFF */
7456 		(void) nxge_mdio_write(nxgep, phy,
7457 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000);
7458 		(void) nxge_mdio_write(nxgep, phy,
7459 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0);
7460 	} else if (*link_up == B_TRUE &&
7461 	    nxgep->statsp->mac_stats.link_up == 0) {
7462 		/* Turn link LED ON */
7463 		(void) nxge_mdio_write(nxgep, phy,
7464 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000);
7465 		(void) nxge_mdio_write(nxgep, phy,
7466 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff);
7467 		(void) nxge_mdio_write(nxgep, phy,
7468 		    NLP2020_GPIO_ADDR, 0xff2a, 0x004a);
7469 	}
7470 
7471 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7472 	    " <== nxge_check_nlp2020_link: up=%d", *link_up));
7473 	return (status);
7474 }
7475 
7476 
7477 nxge_status_t
7478 nxge_10g_link_led_on(p_nxge_t nxgep)
7479 {
7480 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
7481 	    != NPI_SUCCESS)
7482 		return (NXGE_ERROR);
7483 	else
7484 		return (NXGE_OK);
7485 }
7486 
7487 nxge_status_t
7488 nxge_10g_link_led_off(p_nxge_t nxgep)
7489 {
7490 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
7491 	    != NPI_SUCCESS)
7492 		return (NXGE_ERROR);
7493 	else
7494 		return (NXGE_OK);
7495 }
7496 
7497 static boolean_t
7498 nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn)
7499 {
7500 	/*
7501 	 * check for BCM PHY (GOA NEM)
7502 	 */
7503 	/*
7504 	 * If this is the 2nd NIU port, then check 2 addresses
7505 	 * to take care of the Goa NEM card. Port 1 can have addr 17
7506 	 * (in the eval board) or 20 (in the P0 board).
7507 	 */
7508 	if (portn == 1) {
7509 		if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR,
7510 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
7511 			nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR;
7512 			goto found_phy;
7513 		}
7514 	}
7515 	if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn,
7516 	    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
7517 		nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn;
7518 			goto found_phy;
7519 	}
7520 
7521 	/*
7522 	 * check for NLP2020 PHY on C4 NEM
7523 	 */
7524 	switch (portn) {
7525 	case 0:
7526 		if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0,
7527 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7528 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0;
7529 			goto found_phy;
7530 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1,
7531 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7532 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1;
7533 			goto found_phy;
7534 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2,
7535 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7536 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2;
7537 			goto found_phy;
7538 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3,
7539 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7540 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3;
7541 			goto found_phy;
7542 		}
7543 		break;
7544 
7545 	case 1:
7546 		if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0,
7547 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7548 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0;
7549 			goto found_phy;
7550 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1,
7551 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7552 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1;
7553 			goto found_phy;
7554 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2,
7555 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7556 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2;
7557 			goto found_phy;
7558 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3,
7559 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
7560 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3;
7561 			goto found_phy;
7562 		}
7563 		break;
7564 	default:
7565 		break;
7566 	}
7567 
7568 	return (B_FALSE);
7569 found_phy:
7570 	return (B_TRUE);
7571 
7572 }
7573 
7574 static boolean_t
7575 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
7576 {
7577 	uint32_t pma_pmd_id = 0;
7578 	uint32_t pcs_id = 0;
7579 	uint32_t phy_id = 0;
7580 
7581 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
7582 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7583 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
7584 	if ((pma_pmd_id & mask) == (id & mask))
7585 		goto found_phy;
7586 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
7587 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7588 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
7589 	if ((pcs_id & mask) == (id & mask))
7590 		goto found_phy;
7591 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
7592 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7593 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
7594 	if ((phy_id & mask) == (id & mask))
7595 		goto found_phy;
7596 
7597 	return (B_FALSE);
7598 
7599 found_phy:
7600 	return (B_TRUE);
7601 }
7602 
7603 /* Check if the given id read using the given MDIO Clause is supported */
7604 
7605 static boolean_t
7606 nxge_is_supported_phy(uint32_t id, uint8_t type)
7607 {
7608 	int		i;
7609 	boolean_t	found = B_FALSE;
7610 
7611 	switch (type) {
7612 	case CLAUSE_45_TYPE:
7613 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
7614 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
7615 			    (id & BCM_PHY_ID_MASK)) ||
7616 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) ||
7617 			    (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) {
7618 				found = B_TRUE;
7619 				break;
7620 			}
7621 		}
7622 		break;
7623 	case CLAUSE_22_TYPE:
7624 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
7625 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
7626 			    (id & BCM_PHY_ID_MASK)) {
7627 				found = B_TRUE;
7628 				break;
7629 			}
7630 		}
7631 		break;
7632 	default:
7633 		break;
7634 	}
7635 
7636 	return (found);
7637 }
7638 
7639 static uint32_t
7640 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
7641 {
7642 	uint16_t	val1 = 0;
7643 	uint16_t	val2 = 0;
7644 	uint32_t	pma_pmd_dev_id = 0;
7645 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
7646 
7647 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7648 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
7649 	    NXGE_DEV_ID_REG_1, &val1);
7650 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
7651 	    NXGE_DEV_ID_REG_2, &val2);
7652 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7653 
7654 	/* Concatenate the Device ID stored in two registers. */
7655 	pma_pmd_dev_id = val1;
7656 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
7657 	pma_pmd_dev_id |= val2;
7658 
7659 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
7660 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
7661 
7662 	return (pma_pmd_dev_id);
7663 }
7664 
7665 static uint32_t
7666 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
7667 {
7668 	uint16_t	val1 = 0;
7669 	uint16_t	val2 = 0;
7670 	uint32_t	pcs_dev_id = 0;
7671 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
7672 
7673 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7674 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
7675 	    NXGE_DEV_ID_REG_1, &val1);
7676 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
7677 	    NXGE_DEV_ID_REG_2, &val2);
7678 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7679 
7680 	pcs_dev_id = val1;
7681 	pcs_dev_id = (pcs_dev_id << 16);
7682 	pcs_dev_id |= val2;
7683 
7684 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
7685 	    "devid[0x%llx]", phy_port, pcs_dev_id));
7686 
7687 	return (pcs_dev_id);
7688 }
7689 
7690 static uint32_t
7691 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
7692 {
7693 	uint16_t	val1 = 0;
7694 	uint16_t	val2 = 0;
7695 	uint32_t	phy_id = 0;
7696 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
7697 	npi_status_t	npi_status = NPI_SUCCESS;
7698 
7699 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7700 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
7701 	    &val1);
7702 	if (npi_status != NPI_SUCCESS) {
7703 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7704 		    "clause 22 read to reg 2 failed!!!"));
7705 		goto exit;
7706 	}
7707 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
7708 	    &val2);
7709 	if (npi_status != 0) {
7710 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7711 		    "clause 22 read to reg 3 failed!!!"));
7712 		goto exit;
7713 	}
7714 	phy_id = val1;
7715 	phy_id = (phy_id << 16);
7716 	phy_id |= val2;
7717 
7718 exit:
7719 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7720 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
7721 	    phy_port, phy_id));
7722 
7723 	return (phy_id);
7724 }
7725 
7726 /*
7727  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
7728  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
7729  * read. Then use the values obtained to determine the phy type of each port
7730  * and the Neptune type.
7731  *
7732  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
7733  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
7734  * in case the portmode information is not available via OBP, nxge.conf,
7735  * VPD or SEEPROM.
7736  */
7737 nxge_status_t
7738 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
7739 {
7740 	int		i, j, l;
7741 	uint32_t	pma_pmd_dev_id = 0;
7742 	uint32_t	pcs_dev_id = 0;
7743 	uint32_t	phy_id = 0;
7744 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
7745 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
7746 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
7747 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
7748 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
7749 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
7750 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
7751 	uint8_t		total_port_fd, total_phy_fd;
7752 	uint8_t		num_xaui;
7753 	nxge_status_t	status = NXGE_OK;
7754 
7755 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
7756 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7757 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
7758 	    nxgep->niu_type));
7759 
7760 	if (isLDOMguest(nxgep)) {
7761 		hw_p->niu_type = NIU_TYPE_NONE;
7762 		hw_p->platform_type = P_NEPTUNE_NONE;
7763 		return (NXGE_OK);
7764 	}
7765 
7766 	j = l = 0;
7767 	total_port_fd = total_phy_fd = 0;
7768 	/*
7769 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
7770 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
7771 	 */
7772 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
7773 
7774 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
7775 
7776 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
7777 			pma_pmd_dev_fd[i] = 1;
7778 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
7779 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
7780 			if (j < NXGE_PORTS_NEPTUNE) {
7781 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
7782 				    == TN1010_DEV_ID) {
7783 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
7784 				} else if ((pma_pmd_dev_id &
7785 				    NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) {
7786 					port_pma_pmd_dev_id[j] =
7787 					    NLP2020_DEV_ID;
7788 				} else {
7789 					port_pma_pmd_dev_id[j] =
7790 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
7791 				}
7792 				port_fd_arr[j] = (uint8_t)i;
7793 				j++;
7794 			}
7795 		} else {
7796 			pma_pmd_dev_fd[i] = 0;
7797 		}
7798 
7799 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
7800 
7801 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
7802 			pcs_dev_fd[i] = 1;
7803 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
7804 			    "dev %x found", i, pcs_dev_id));
7805 			if (pma_pmd_dev_fd[i] == 1) {
7806 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
7807 				    == TN1010_DEV_ID) {
7808 					port_pcs_dev_id[j - 1] =
7809 					    TN1010_DEV_ID;
7810 				} else if ((pcs_dev_id & NLP2020_DEV_ID_MASK)
7811 				    == NLP2020_DEV_ID) {
7812 					port_pcs_dev_id[j - 1] =
7813 					    NLP2020_DEV_ID;
7814 				} else {
7815 					port_pcs_dev_id[j - 1] =
7816 					    pcs_dev_id &
7817 					    BCM_PHY_ID_MASK;
7818 				}
7819 			} else {
7820 				if (j < NXGE_PORTS_NEPTUNE) {
7821 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
7822 					    == TN1010_DEV_ID) {
7823 						port_pcs_dev_id[j] =
7824 						    TN1010_DEV_ID;
7825 					} else if ((pcs_dev_id &
7826 					    NLP2020_DEV_ID_MASK)
7827 					    == NLP2020_DEV_ID) {
7828 						port_pcs_dev_id[j] =
7829 						    NLP2020_DEV_ID;
7830 					} else {
7831 						port_pcs_dev_id[j] =
7832 						    pcs_dev_id &
7833 						    BCM_PHY_ID_MASK;
7834 					}
7835 					port_fd_arr[j] = (uint8_t)i;
7836 					j++;
7837 				}
7838 			}
7839 		} else {
7840 			pcs_dev_fd[i] = 0;
7841 		}
7842 
7843 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
7844 			total_port_fd ++;
7845 		}
7846 
7847 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
7848 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
7849 			total_phy_fd ++;
7850 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
7851 			    "%x found", i, phy_id));
7852 			if (l < NXGE_PORTS_NEPTUNE) {
7853 				if ((phy_id & TN1010_DEV_ID_MASK)
7854 				    == TN1010_DEV_ID) {
7855 					port_phy_id[l] = TN1010_DEV_ID;
7856 				} else {
7857 					port_phy_id[l]
7858 					    = phy_id & BCM_PHY_ID_MASK;
7859 				}
7860 				phy_fd_arr[l] = (uint8_t)i;
7861 				l++;
7862 			}
7863 		}
7864 	}
7865 
7866 	switch (total_port_fd) {
7867 	case 2:
7868 		switch (total_phy_fd) {
7869 		case 2:
7870 			/* 2 10G, 2 1G RGMII Fiber / copper */
7871 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
7872 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7873 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
7874 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
7875 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
7876 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
7877 
7878 				switch (hw_p->platform_type) {
7879 				case P_NEPTUNE_ROCK:
7880 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
7881 					/*
7882 					 * ROCK platform has assigned a lower
7883 					 * addr to port 1. (port 0 = 0x9 and
7884 					 * port 1 = 0x8).
7885 					 */
7886 					hw_p->xcvr_addr[1] = port_fd_arr[0];
7887 					hw_p->xcvr_addr[0] = port_fd_arr[1];
7888 
7889 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7890 					    "Rock with 2 10G, 2 1GC"));
7891 					break;
7892 
7893 				case P_NEPTUNE_NONE:
7894 				default:
7895 					hw_p->platform_type =
7896 					    P_NEPTUNE_GENERIC;
7897 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
7898 
7899 					hw_p->xcvr_addr[0] = port_fd_arr[0];
7900 					hw_p->xcvr_addr[1] = port_fd_arr[1];
7901 
7902 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7903 					    "ARTM card with 2 10G, 2 1GF"));
7904 					break;
7905 				}
7906 
7907 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
7908 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
7909 
7910 			} else {
7911 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7912 				    "Unsupported neptune type 1"));
7913 				goto error_exit;
7914 			}
7915 			break;
7916 
7917 		case 1:
7918 			/* TODO - 2 10G, 1 1G */
7919 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7920 			    "Unsupported neptune type 2 10G, 1 1G"));
7921 			goto error_exit;
7922 		case 0:
7923 			/*
7924 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
7925 			 * cards, etc.
7926 			 */
7927 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
7928 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7929 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
7930 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
7931 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
7932 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
7933 			    ((port_pma_pmd_dev_id[0] ==
7934 			    MARVELL_88X201X_PHY_ID) &&
7935 			    (port_pma_pmd_dev_id[1] ==
7936 			    MARVELL_88X201X_PHY_ID))) {
7937 
7938 				/*
7939 				 * Check the first phy port address against
7940 				 * the known phy start addresses to determine
7941 				 * the platform type.
7942 				 */
7943 
7944 				switch (port_fd_arr[0]) {
7945 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
7946 					/*
7947 					 * The Marvell case also falls into
7948 					 * this case as
7949 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
7950 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
7951 					 * This is OK for the 2 10G case.
7952 					 */
7953 					hw_p->niu_type = NEPTUNE_2_10GF;
7954 					hw_p->platform_type =
7955 					    P_NEPTUNE_ATLAS_2PORT;
7956 					break;
7957 				case GOA_CLAUSE45_PORT_ADDR_BASE:
7958 					if (hw_p->platform_type !=
7959 					    P_NEPTUNE_NIU) {
7960 						hw_p->platform_type =
7961 						    P_NEPTUNE_GENERIC;
7962 						hw_p->niu_type =
7963 						    NEPTUNE_2_10GF;
7964 					}
7965 					break;
7966 				default:
7967 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7968 					    "Unsupported neptune type 2 - 1"));
7969 					goto error_exit;
7970 				}
7971 
7972 				for (i = 0; i < 2; i++) {
7973 					hw_p->xcvr_addr[i] = port_fd_arr[i];
7974 				}
7975 
7976 			/* 2 10G optical Netlogic AEL2020 ports */
7977 			} else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) &&
7978 			    (port_pcs_dev_id[1]  == NLP2020_DEV_ID)) ||
7979 			    ((port_pma_pmd_dev_id[0]  == NLP2020_DEV_ID) &&
7980 			    (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) {
7981 				if (hw_p->platform_type != P_NEPTUNE_NIU) {
7982 					hw_p->platform_type =
7983 					    P_NEPTUNE_GENERIC;
7984 					hw_p->niu_type =
7985 					    NEPTUNE_2_10GF;
7986 				}
7987 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7988 				    "Found 2 NL PHYs at addrs 0x%x and 0x%x",
7989 				    port_fd_arr[0], port_fd_arr[1]));
7990 				hw_p->xcvr_addr[0] = port_fd_arr[0];
7991 				hw_p->xcvr_addr[1] = port_fd_arr[1];
7992 
7993 			/* Both XAUI slots have copper XAUI cards */
7994 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
7995 			    == TN1010_DEV_ID) &&
7996 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
7997 			    == TN1010_DEV_ID)) ||
7998 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
7999 			    == TN1010_DEV_ID) &&
8000 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
8001 			    == TN1010_DEV_ID))) {
8002 				hw_p->niu_type = NEPTUNE_2_TN1010;
8003 				hw_p->xcvr_addr[0] = port_fd_arr[0];
8004 				hw_p->xcvr_addr[1] = port_fd_arr[1];
8005 
8006 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
8007 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8008 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8009 			    == TN1010_DEV_ID) ||
8010 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
8011 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
8012 			    TN1010_DEV_ID)) {
8013 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
8014 				hw_p->xcvr_addr[0] = port_fd_arr[0];
8015 				hw_p->xcvr_addr[1] = port_fd_arr[1];
8016 
8017 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
8018 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
8019 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8020 			    == TN1010_DEV_ID) ||
8021 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
8022 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8023 			    == TN1010_DEV_ID)) {
8024 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
8025 				hw_p->xcvr_addr[0] = port_fd_arr[0];
8026 				hw_p->xcvr_addr[1] = port_fd_arr[1];
8027 
8028 			} else {
8029 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8030 				    "Unsupported neptune type 2"));
8031 				goto error_exit;
8032 			}
8033 			break;
8034 
8035 		case 4:
8036 			if (nxge_get_num_of_xaui(
8037 			    port_pma_pmd_dev_id, port_pcs_dev_id,
8038 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
8039 				goto error_exit;
8040 			}
8041 			if (num_xaui != 2)
8042 				goto error_exit;
8043 
8044 			/*
8045 			 *  Maramba with 2 XAUIs (either fiber or copper)
8046 			 *
8047 			 * Check the first phy port address against
8048 			 * the known phy start addresses to determine
8049 			 * the platform type.
8050 			 */
8051 			switch (phy_fd_arr[0]) {
8052 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
8053 				hw_p->platform_type =
8054 				    P_NEPTUNE_MARAMBA_P0;
8055 				break;
8056 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8057 				hw_p->platform_type =
8058 				    P_NEPTUNE_MARAMBA_P1;
8059 				break;
8060 			default:
8061 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8062 				    "Unknown port %d...Cannot "
8063 				    "determine platform type", i));
8064 				goto error_exit;
8065 			}
8066 
8067 			hw_p->xcvr_addr[0] = port_fd_arr[0];
8068 			hw_p->xcvr_addr[1] = port_fd_arr[1];
8069 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
8070 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
8071 
8072 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
8073 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8074 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8075 			    == TN1010_DEV_ID) {
8076 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
8077 
8078 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
8079 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8080 			    == TN1010_DEV_ID) &&
8081 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
8082 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
8083 
8084 			/* Both slots have fiber XAUI */
8085 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
8086 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
8087 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
8088 
8089 			/* Both slots have copper XAUI */
8090 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8091 			    == TN1010_DEV_ID) &&
8092 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8093 			    == TN1010_DEV_ID) {
8094 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
8095 
8096 			} else {
8097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8098 				    "Unsupported neptune type 3"));
8099 				goto error_exit;
8100 			}
8101 			break;
8102 		default:
8103 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8104 			    "Unsupported neptune type 5"));
8105 			goto error_exit;
8106 		}
8107 		break;
8108 	case 1:		/* Only one clause45 port */
8109 		switch (total_phy_fd) {	/* Number of clause22 ports */
8110 		case 3:
8111 			/*
8112 			 * TODO 3 1G, 1 10G mode.
8113 			 * Differentiate between 1_1G_1_10G_2_1G and
8114 			 * 1_10G_3_1G
8115 			 */
8116 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8117 			    "Unsupported neptune type 7"));
8118 			goto error_exit;
8119 		case 2:
8120 			/*
8121 			 * TODO 2 1G, 1 10G mode.
8122 			 * Differentiate between 1_1G_1_10G_1_1G and
8123 			 * 1_10G_2_1G
8124 			 */
8125 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8126 			    "Unsupported neptune type 8"));
8127 			goto error_exit;
8128 		case 1:
8129 			/*
8130 			 * TODO 1 1G, 1 10G mode.
8131 			 * Differentiate between 1_1G_1_10G and
8132 			 * 1_10G_1_1G
8133 			 */
8134 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8135 			    "Unsupported neptune type 9"));
8136 			goto error_exit;
8137 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
8138 			/* Fiber XAUI */
8139 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
8140 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
8141 
8142 				/*
8143 				 * Check the first phy port address against
8144 				 * the known phy start addresses to determine
8145 				 * the platform type.
8146 				 */
8147 
8148 				switch (port_fd_arr[0]) {
8149 				case N2_CLAUSE45_PORT_ADDR_BASE:
8150 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
8151 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
8152 					/*
8153 					 * If hw_p->platform_type ==
8154 					 * P_NEPTUNE_NIU, then portmode
8155 					 * is already known, so there is
8156 					 * no need to figure out hw_p->
8157 					 * platform_type because
8158 					 * platform_type is only for
8159 					 * figuring out portmode.
8160 					 */
8161 					if (hw_p->platform_type !=
8162 					    P_NEPTUNE_NIU) {
8163 						hw_p->platform_type =
8164 						    P_NEPTUNE_GENERIC;
8165 						hw_p->niu_type =
8166 						    NEPTUNE_2_10GF;
8167 					}
8168 					break;
8169 				default:
8170 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8171 					    "Unsupported neptune type 10"));
8172 					goto error_exit;
8173 				}
8174 				/*
8175 				 * For GOA, which is a hot swappable PHY, the
8176 				 * phy address to function number mapping
8177 				 * should be preserved, i.e., addr 16 is
8178 				 * assigned to function 0 and 20 to function 1
8179 				 * But for Huron XAUI, the assignment should
8180 				 * be by function number, i.e., whichever
8181 				 * function number attaches should be
8182 				 * assigned the available PHY (this is required
8183 				 * primarily to support pre-production Huron
8184 				 * boards where function 0 is mapped to addr 17
8185 				 */
8186 				if (port_fd_arr[0] ==
8187 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
8188 					hw_p->xcvr_addr[1] = port_fd_arr[0];
8189 				} else {
8190 					hw_p->xcvr_addr[nxgep->function_num] =
8191 					    port_fd_arr[0];
8192 				}
8193 			} else if (port_pcs_dev_id[0] == NLP2020_DEV_ID ||
8194 			    port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) {
8195 				/* A 10G NLP2020 PHY in slot0 or slot1 */
8196 				switch (port_fd_arr[0]) {
8197 				case NLP2020_CL45_PORT0_ADDR0:
8198 				case NLP2020_CL45_PORT0_ADDR1:
8199 				case NLP2020_CL45_PORT0_ADDR2:
8200 				case NLP2020_CL45_PORT0_ADDR3:
8201 				case NLP2020_CL45_PORT1_ADDR0:
8202 				case NLP2020_CL45_PORT1_ADDR1:
8203 				case NLP2020_CL45_PORT1_ADDR2:
8204 				case NLP2020_CL45_PORT1_ADDR3:
8205 					/*
8206 					 * If hw_p->platform_type ==
8207 					 * P_NEPTUNE_NIU, then portmode
8208 					 * is already known, so there is
8209 					 * no need to figure out hw_p->
8210 					 * platform_type because
8211 					 * platform_type is only for
8212 					 * figuring out portmode.
8213 					 */
8214 					if (hw_p->platform_type !=
8215 					    P_NEPTUNE_NIU) {
8216 						hw_p->platform_type =
8217 						    P_NEPTUNE_GENERIC;
8218 						hw_p->niu_type =
8219 						    NEPTUNE_2_10GF;
8220 					}
8221 					break;
8222 				default:
8223 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8224 					    "Unsupported neptune type 10-1"));
8225 					goto error_exit;
8226 				}
8227 				switch (port_fd_arr[0]) {
8228 				case NLP2020_CL45_PORT0_ADDR0:
8229 				case NLP2020_CL45_PORT0_ADDR1:
8230 				case NLP2020_CL45_PORT0_ADDR2:
8231 				case NLP2020_CL45_PORT0_ADDR3:
8232 					hw_p->xcvr_addr[0] = port_fd_arr[0];
8233 					break;
8234 				case NLP2020_CL45_PORT1_ADDR0:
8235 				case NLP2020_CL45_PORT1_ADDR1:
8236 				case NLP2020_CL45_PORT1_ADDR2:
8237 				case NLP2020_CL45_PORT1_ADDR3:
8238 					hw_p->xcvr_addr[1] = port_fd_arr[0];
8239 					break;
8240 				default:
8241 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8242 					    "Unsupported neptune type 10-11"));
8243 					goto error_exit;
8244 				}
8245 
8246 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8247 				    "Found 1 NL PHYs at addr 0x%x",
8248 				    port_fd_arr[0]));
8249 
8250 			/* A 10G copper XAUI in either slot0 or slot1 */
8251 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8252 			    == TN1010_DEV_ID ||
8253 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8254 			    == TN1010_DEV_ID) {
8255 				switch (port_fd_arr[0]) {
8256 				/* The XAUI is in slot0 */
8257 				case N2_CLAUSE45_PORT_ADDR_BASE:
8258 					hw_p->niu_type = NEPTUNE_1_TN1010;
8259 					break;
8260 
8261 				/* The XAUI is in slot1 */
8262 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
8263 					hw_p->niu_type
8264 					    = NEPTUNE_1_NONE_1_TN1010;
8265 					break;
8266 				default:
8267 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8268 					    "Unsupported XAUI port address"));
8269 					goto error_exit;
8270 				}
8271 				hw_p->xcvr_addr[nxgep->function_num]
8272 				    = port_fd_arr[0];
8273 
8274 			} else {
8275 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8276 				    "Unsupported PHY type"));
8277 				goto error_exit;
8278 			}
8279 			break;
8280 		case 4: /* Maramba always have 4 clause 45 ports */
8281 
8282 			/* Maramba with 1 XAUI */
8283 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
8284 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
8285 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8286 			    != TN1010_DEV_ID) &&
8287 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8288 			    != TN1010_DEV_ID)) {
8289 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8290 				    "Unsupported neptune type 12"));
8291 				goto error_exit;
8292 			}
8293 
8294 			/*
8295 			 * Check the first phy port address against
8296 			 * the known phy start addresses to determine
8297 			 * the platform type.
8298 			 */
8299 			switch (phy_fd_arr[0]) {
8300 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
8301 				hw_p->platform_type =
8302 				    P_NEPTUNE_MARAMBA_P0;
8303 				break;
8304 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8305 				hw_p->platform_type =
8306 				    P_NEPTUNE_MARAMBA_P1;
8307 				break;
8308 			default:
8309 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8310 				    "Unknown port %d...Cannot "
8311 				    "determine platform type 10 - 2",
8312 				    i));
8313 				goto error_exit;
8314 			}
8315 
8316 			/*
8317 			 * Check the clause45 address to determine
8318 			 * if XAUI is in port 0 or port 1.
8319 			 */
8320 			switch (port_fd_arr[0]) {
8321 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
8322 				if (port_pcs_dev_id[0]
8323 				    == PHY_BCM8704_FAMILY ||
8324 				    port_pma_pmd_dev_id[0]
8325 				    == PHY_BCM8704_FAMILY) {
8326 					hw_p->niu_type
8327 					    = NEPTUNE_1_10GF_3_1GC;
8328 				} else {
8329 					hw_p->niu_type
8330 					    = NEPTUNE_1_TN1010_3_1GC;
8331 				}
8332 				hw_p->xcvr_addr[0] = port_fd_arr[0];
8333 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
8334 					hw_p->xcvr_addr[i] =
8335 					    phy_fd_arr[i];
8336 				}
8337 				break;
8338 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
8339 				if (port_pcs_dev_id[0]
8340 				    == PHY_BCM8704_FAMILY ||
8341 				    port_pma_pmd_dev_id[0]
8342 				    == PHY_BCM8704_FAMILY) {
8343 					hw_p->niu_type =
8344 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
8345 				} else {
8346 					hw_p->niu_type =
8347 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
8348 				}
8349 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
8350 				hw_p->xcvr_addr[1] = port_fd_arr[0];
8351 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
8352 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
8353 				break;
8354 			default:
8355 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8356 				    "Unsupported neptune type 11"));
8357 				goto error_exit;
8358 			}
8359 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8360 			    "Maramba with 1 XAUI (fiber or copper)"));
8361 			break;
8362 		default:
8363 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8364 			    "Unsupported neptune type 13"));
8365 			goto error_exit;
8366 		}
8367 		break;
8368 	case 0: /* 4 ports Neptune based NIC */
8369 		switch (total_phy_fd) {
8370 		case 4:
8371 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
8372 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
8373 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
8374 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
8375 
8376 				/*
8377 				 * Check the first phy port address against
8378 				 * the known phy start addresses to determine
8379 				 * the platform type.
8380 				 */
8381 				switch (phy_fd_arr[0]) {
8382 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
8383 					hw_p->platform_type =
8384 					    P_NEPTUNE_MARAMBA_P1;
8385 					break;
8386 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
8387 					hw_p->platform_type =
8388 					    P_NEPTUNE_ATLAS_4PORT;
8389 					break;
8390 				default:
8391 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8392 					    "Unknown port %d...Cannot "
8393 					    "determine platform type", i));
8394 					goto error_exit;
8395 				}
8396 				hw_p->niu_type = NEPTUNE_4_1GC;
8397 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
8398 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
8399 				}
8400 			} else {
8401 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8402 				    "Unsupported neptune type 14"));
8403 				goto error_exit;
8404 			}
8405 			break;
8406 		case 3:
8407 			/* TODO 3 1G mode */
8408 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8409 			    "Unsupported neptune type 15"));
8410 			goto error_exit;
8411 		case 2:
8412 			/* TODO 2 1G mode */
8413 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
8414 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
8415 				hw_p->platform_type = P_NEPTUNE_GENERIC;
8416 				hw_p->niu_type = NEPTUNE_2_1GRF;
8417 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
8418 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
8419 			} else {
8420 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8421 				    "Unsupported neptune type 16"));
8422 				goto error_exit;
8423 			}
8424 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8425 			    "2 RGMII Fiber ports - RTM"));
8426 			break;
8427 
8428 		case 1:
8429 			/* TODO 1 1G mode */
8430 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8431 			    "Unsupported neptune type 17"));
8432 			goto error_exit;
8433 		default:
8434 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8435 			    "Unsupported neptune type 18, total phy fd %d",
8436 			    total_phy_fd));
8437 			goto error_exit;
8438 		}
8439 		break;
8440 	default:
8441 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8442 		    "Unsupported neptune type 19"));
8443 		goto error_exit;
8444 	}
8445 
8446 scan_exit:
8447 
8448 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
8449 	    "niu type [0x%x]\n", hw_p->niu_type));
8450 	return (status);
8451 
8452 error_exit:
8453 	return (NXGE_ERROR);
8454 }
8455 
8456 boolean_t
8457 nxge_is_valid_local_mac(ether_addr_st mac_addr)
8458 {
8459 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
8460 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
8461 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
8462 		return (B_FALSE);
8463 	else
8464 		return (B_TRUE);
8465 }
8466 
8467 static void
8468 nxge_bcm5464_link_led_off(p_nxge_t nxgep)
8469 {
8470 
8471 	npi_status_t rs = NPI_SUCCESS;
8472 	uint8_t xcvr_portn;
8473 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8474 
8475 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
8476 
8477 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
8478 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
8479 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
8480 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
8481 	}
8482 	/*
8483 	 * For Altas 4-1G copper, Xcvr port numbers are
8484 	 * swapped with ethernet port number. This is
8485 	 * designed for better signal integrity in routing.
8486 	 */
8487 	switch (portn) {
8488 	case 0:
8489 		xcvr_portn += 3;
8490 		break;
8491 	case 1:
8492 		xcvr_portn += 2;
8493 		break;
8494 	case 2:
8495 		xcvr_portn += 1;
8496 		break;
8497 	case 3:
8498 	default:
8499 		break;
8500 	}
8501 
8502 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
8503 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
8504 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
8505 	if (rs != NPI_SUCCESS) {
8506 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8507 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
8508 		    "returned error 0x[%x]", rs));
8509 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
8510 		return;
8511 	}
8512 
8513 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
8514 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
8515 	if (rs != NPI_SUCCESS) {
8516 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8517 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
8518 		    "returned error 0x[%x]", rs));
8519 	}
8520 
8521 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
8522 }
8523 
8524 static nxge_status_t
8525 nxge_mii_get_link_mode(p_nxge_t nxgep)
8526 {
8527 	p_nxge_stats_t	statsp;
8528 	uint8_t		xcvr_portn;
8529 	p_mii_regs_t	mii_regs;
8530 	mii_mode_control_stat_t	mode;
8531 	int		status = NXGE_OK;
8532 
8533 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
8534 
8535 	statsp = nxgep->statsp;
8536 	xcvr_portn = statsp->mac_stats.xcvr_portn;
8537 	mii_regs = NULL;
8538 	mode.value = 0;
8539 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8540 #if defined(__i386)
8541 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
8542 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
8543 	    mode.value)) != NXGE_OK) {
8544 		goto fail;
8545 #else
8546 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
8547 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
8548 	    mode.value)) != NXGE_OK) {
8549 		goto fail;
8550 #endif
8551 	}
8552 #if defined(__i386)
8553 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
8554 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
8555 	    &mode.value)) != NXGE_OK) {
8556 		goto fail;
8557 	}
8558 #else
8559 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
8560 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
8561 	    &mode.value)) != NXGE_OK) {
8562 		goto fail;
8563 	}
8564 #endif
8565 
8566 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
8567 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
8568 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8569 		    "nxge_mii_get_link_mode: fiber mode"));
8570 	}
8571 
8572 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8573 	    "nxge_mii_get_link_mode: "
8574 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
8575 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
8576 	    mode.value, nxgep->mac.portmode));
8577 
8578 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8579 	    "<== nxge_mii_get_link_mode"));
8580 	return (status);
8581 fail:
8582 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8583 	    "<== nxge_mii_get_link_mode (failed)"));
8584 	return (NXGE_ERROR);
8585 }
8586 
8587 nxge_status_t
8588 nxge_mac_set_framesize(p_nxge_t nxgep)
8589 {
8590 	npi_attr_t		ap;
8591 	uint8_t			portn;
8592 	npi_handle_t		handle;
8593 	npi_status_t		rs = NPI_SUCCESS;
8594 
8595 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
8596 
8597 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8598 	handle = nxgep->npi_handle;
8599 
8600 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8601 	    "==> nxge_mac_sec_framesize: port<%d> "
8602 	    "min framesize %d max framesize %d ",
8603 	    portn,
8604 	    nxgep->mac.minframesize,
8605 	    nxgep->mac.maxframesize));
8606 
8607 	SET_MAC_ATTR2(handle, ap, portn,
8608 	    MAC_PORT_FRAME_SIZE,
8609 	    nxgep->mac.minframesize,
8610 	    nxgep->mac.maxframesize,
8611 	    rs);
8612 	if (rs != NPI_SUCCESS) {
8613 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8614 		    "<== nxge_mac_set_framesize: failed to configure "
8615 		    "max/min frame size port %d", portn));
8616 
8617 		return (NXGE_ERROR | rs);
8618 	}
8619 
8620 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8621 	    "<== nxge_mac_set_framesize: port<%d>", portn));
8622 
8623 	return (NXGE_OK);
8624 }
8625 
8626 static nxge_status_t
8627 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
8628     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
8629 {
8630 	uint8_t i;
8631 
8632 	for (i = 0; i < 4; i++) {
8633 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
8634 			return (NXGE_ERROR);
8635 	}
8636 
8637 	*num_xaui = 0;
8638 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
8639 	    port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
8640 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
8641 	    == TN1010_DEV_ID) &&
8642 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
8643 	    == TN1010_DEV_ID))) {
8644 		(*num_xaui) ++;
8645 	}
8646 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
8647 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
8648 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
8649 	    == TN1010_DEV_ID) &&
8650 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
8651 	    == TN1010_DEV_ID))) {
8652 		(*num_xaui) ++;
8653 	}
8654 	return (NXGE_OK);
8655 }
8656 
8657 /*
8658  * Instruction from Teranetics:  Once you detect link is up, go
8659  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
8660  * may want to qualify it by first checking Register 30.1.7:6 and
8661  * making sure it reads "01" (Auto-Neg Complete).
8662  *
8663  * If this function is called when the link is down or before auto-
8664  * negotiation has completed, then the speed of the PHY is not certain.
8665  * In such cases, this function returns 1G as the default speed with
8666  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
8667  * driver based on a default speed because this function will be called
8668  * again when the link comes up.  Returning NXGE_ERROR, which may
8669  * cause brutal chain reaction in caller functions, is not necessary.
8670  */
8671 static nxge_status_t
8672 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
8673 {
8674 	uint8_t		phy_port_addr, autoneg_stat, link_up;
8675 	nxge_status_t	status = NXGE_OK;
8676 	uint16_t	val;
8677 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8678 
8679 	/* Set default speed to 10G */
8680 	*speed = TN1010_SPEED_10G;
8681 
8682 	/* Set Clause 45 */
8683 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
8684 
8685 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
8686 
8687 	/* Check Device 1 Register 0xA bit0 for link up status */
8688 	status = nxge_mdio_read(nxgep, phy_port_addr,
8689 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
8690 	if (status != NXGE_OK)
8691 		goto fail;
8692 
8693 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
8694 	    ? B_TRUE : B_FALSE);
8695 	if (link_up == B_FALSE) {
8696 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8697 		    "nxge_get_tn1010_speed: link is down"));
8698 		goto nxge_get_tn1010_speed_exit;
8699 	}
8700 
8701 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
8702 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
8703 	    &val)) != NXGE_OK) {
8704 		goto fail;
8705 	}
8706 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
8707 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
8708 
8709 	/*
8710 	 * Return NXGE_OK even when we can not get a settled speed. In
8711 	 * such case, the speed reported should not be trusted but that
8712 	 * is OK, we will call this function periodically and will get
8713 	 * the correct speed after the link is up.
8714 	 */
8715 	switch (autoneg_stat) {
8716 	case TN1010_AN_IN_PROG:
8717 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8718 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
8719 		break;
8720 	case TN1010_AN_COMPLETE:
8721 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
8722 		    TN1010_VENDOR_MMD1_DEV_ADDR,
8723 		    TN1010_VENDOR_MMD1_STATUS_REG,
8724 		    &val)) != NXGE_OK) {
8725 			goto fail;
8726 		}
8727 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
8728 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
8729 		break;
8730 	case TN1010_AN_RSVD:
8731 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8732 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
8733 		break;
8734 	case TN1010_AN_FAILED:
8735 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8736 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
8737 		break;
8738 	default:
8739 		break;
8740 	}
8741 nxge_get_tn1010_speed_exit:
8742 	return (NXGE_OK);
8743 fail:
8744 	return (status);
8745 }
8746 
8747 
8748 /*
8749  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
8750  * figures out the speed of the PHY determined by the autonegotiation
8751  * process and sets the following 3 parameters,
8752  *	nxgep->mac.portmode
8753  *	nxgep->statsp->mac_stats.link_speed
8754  *	nxgep->statsp->mac_stats.xcvr_inuse
8755  */
8756 static nxge_status_t
8757 nxge_set_tn1010_param(p_nxge_t nxgep)
8758 {
8759 	uint16_t speed;
8760 
8761 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
8762 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8763 		    "nxge_set_tn1010_param: "
8764 		    "Failed to get TN1010 speed"));
8765 		return (NXGE_ERROR);
8766 	}
8767 	if (speed == TN1010_SPEED_1G) {
8768 		nxgep->mac.portmode = PORT_1G_TN1010;
8769 		nxgep->statsp->mac_stats.link_speed = 1000;
8770 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
8771 	} else {
8772 		nxgep->mac.portmode = PORT_10G_TN1010;
8773 		nxgep->statsp->mac_stats.link_speed = 10000;
8774 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
8775 	}
8776 	return (NXGE_OK);
8777 }
8778 
8779 #ifdef NXGE_DEBUG
8780 static void
8781 nxge_mii_dump(p_nxge_t nxgep)
8782 {
8783 	p_nxge_stats_t	statsp;
8784 	uint8_t		xcvr_portn;
8785 	p_mii_regs_t	mii_regs;
8786 	mii_bmcr_t	bmcr;
8787 	mii_bmsr_t	bmsr;
8788 	mii_idr1_t	idr1;
8789 	mii_idr2_t	idr2;
8790 	mii_mode_control_stat_t	mode;
8791 	p_nxge_param_t	param_arr;
8792 
8793 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
8794 
8795 	statsp = nxgep->statsp;
8796 	xcvr_portn = statsp->mac_stats.xcvr_portn;
8797 
8798 	mii_regs = NULL;
8799 
8800 #if defined(__i386)
8801 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8802 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
8803 #else
8804 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8805 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
8806 #endif
8807 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8808 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
8809 	    xcvr_portn, bmcr.value));
8810 
8811 #if defined(__i386)
8812 	(void) nxge_mii_read(nxgep,
8813 	    nxgep->statsp->mac_stats.xcvr_portn,
8814 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
8815 #else
8816 	(void) nxge_mii_read(nxgep,
8817 	    nxgep->statsp->mac_stats.xcvr_portn,
8818 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
8819 #endif
8820 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8821 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
8822 	    xcvr_portn, bmsr.value));
8823 
8824 #if defined(__i386)
8825 	(void) nxge_mii_read(nxgep,
8826 	    nxgep->statsp->mac_stats.xcvr_portn,
8827 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
8828 #else
8829 	(void) nxge_mii_read(nxgep,
8830 	    nxgep->statsp->mac_stats.xcvr_portn,
8831 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
8832 #endif
8833 
8834 
8835 #if defined(__i386)
8836 	(void) nxge_mii_read(nxgep,
8837 	    nxgep->statsp->mac_stats.xcvr_portn,
8838 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
8839 #else
8840 	(void) nxge_mii_read(nxgep,
8841 	    nxgep->statsp->mac_stats.xcvr_portn,
8842 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
8843 #endif
8844 
8845 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8846 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
8847 	    xcvr_portn, idr1.value));
8848 
8849 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8850 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
8851 	    xcvr_portn, idr2.value));
8852 
8853 	mode.value = 0;
8854 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8855 
8856 #if defined(__i386)
8857 	(void) nxge_mii_write(nxgep, xcvr_portn,
8858 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
8859 
8860 	(void) nxge_mii_read(nxgep, xcvr_portn,
8861 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
8862 #else
8863 	(void) nxge_mii_write(nxgep, xcvr_portn,
8864 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
8865 
8866 	(void) nxge_mii_read(nxgep, xcvr_portn,
8867 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
8868 #endif
8869 
8870 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8871 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
8872 	    xcvr_portn, mode.value));
8873 }
8874 #endif
8875