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