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