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