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