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