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