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