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