xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision fb2a9bae0030340ad72b9c26ba1ffee2ee3cafec)
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 2010 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_DEBUG_MSG((nxgep, MAC_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_DEBUG_MSG((nxgep, MAC_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 static npi_status_t
3344 nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)
3345 {
3346 	uint32_t		i;
3347 	uint16_t		hashtab_e;
3348 	p_hash_filter_t		hash_filter;
3349 	uint8_t			portn;
3350 	npi_handle_t		handle;
3351 	npi_status_t		rs = NPI_SUCCESS;
3352 
3353 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3354 	handle = nxgep->npi_handle;
3355 
3356 	/*
3357 	 * Load the multicast hash filter bits.
3358 	 */
3359 	hash_filter = nxgep->hash_filter;
3360 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
3361 		if (hash_filter != NULL) {
3362 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
3363 			    (NMCFILTER_REGS - 1) - i];
3364 		} else {
3365 			hashtab_e = 0;
3366 		}
3367 
3368 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
3369 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
3370 			return (rs);
3371 	}
3372 
3373 	return (NPI_SUCCESS);
3374 }
3375 
3376 /*
3377  * Initialize the RxMAC sub-block
3378  */
3379 nxge_status_t
3380 nxge_rx_mac_init(p_nxge_t nxgep)
3381 {
3382 	npi_attr_t		ap;
3383 	nxge_port_t		portt;
3384 	uint8_t			portn;
3385 	npi_handle_t		handle;
3386 	npi_status_t		rs = NPI_SUCCESS;
3387 	uint16_t 		*addr16p;
3388 	uint16_t 		addr0, addr1, addr2;
3389 	xmac_rx_config_t	xconfig;
3390 	bmac_rx_config_t	bconfig;
3391 
3392 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
3393 
3394 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
3395 	    portn));
3396 	handle = nxgep->npi_handle;
3397 	portt = nxgep->mac.porttype;
3398 
3399 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
3400 	addr0 = ntohs(addr16p[2]);
3401 	addr1 = ntohs(addr16p[1]);
3402 	addr2 = ntohs(addr16p[0]);
3403 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR,
3404 	    addr0, addr1, addr2, rs);
3405 	if (rs != NPI_SUCCESS)
3406 		goto fail;
3407 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
3408 	if (rs != NPI_SUCCESS)
3409 		goto fail;
3410 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
3411 	if (rs != NPI_SUCCESS)
3412 		goto fail;
3413 
3414 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
3415 	if (rs != NPI_SUCCESS)
3416 		goto fail;
3417 
3418 	if (portt == PORT_TYPE_XMAC) {
3419 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
3420 		    0)) != NPI_SUCCESS)
3421 			goto fail;
3422 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
3423 
3424 		(void) nxge_fflp_init_hostinfo(nxgep);
3425 
3426 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
3427 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
3428 		    ~CFG_XMAC_RX_STRIP_CRC;
3429 
3430 		if (nxgep->filter.all_phys_cnt != 0)
3431 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
3432 		if (nxgep->filter.all_multicast_cnt != 0)
3433 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
3434 
3435 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
3436 
3437 		if ((rs = npi_xmac_rx_config(handle, INIT,
3438 		    portn, xconfig)) != NPI_SUCCESS)
3439 			goto fail;
3440 		nxgep->mac.rx_config = xconfig;
3441 
3442 		/*
3443 		 * Comparison of mac unique address is always
3444 		 * enabled on XMAC
3445 		 */
3446 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
3447 		    != NPI_SUCCESS)
3448 			goto fail;
3449 	} else {
3450 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
3451 		    0) != NPI_SUCCESS)
3452 			goto fail;
3453 
3454 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
3455 
3456 		(void) nxge_fflp_init_hostinfo(nxgep);
3457 
3458 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
3459 		    ~CFG_BMAC_RX_STRIP_CRC;
3460 
3461 		if (nxgep->filter.all_phys_cnt != 0)
3462 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
3463 		if (nxgep->filter.all_multicast_cnt != 0)
3464 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
3465 
3466 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
3467 		if ((rs = npi_bmac_rx_config(handle, INIT,
3468 		    portn, bconfig)) != NPI_SUCCESS)
3469 			goto fail;
3470 		nxgep->mac.rx_config = bconfig;
3471 
3472 		/*
3473 		 * Always enable comparison of mac unique address
3474 		 */
3475 		if ((rs = npi_mac_altaddr_enable(handle,
3476 		    portn, 0)) != NPI_SUCCESS)
3477 			goto fail;
3478 	}
3479 
3480 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
3481 	    portn));
3482 
3483 	return (NXGE_OK);
3484 
3485 fail:
3486 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3487 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
3488 
3489 	return (NXGE_ERROR | rs);
3490 }
3491 
3492 /* Enable TXMAC */
3493 
3494 nxge_status_t
3495 nxge_tx_mac_enable(p_nxge_t nxgep)
3496 {
3497 	npi_handle_t	handle;
3498 	npi_status_t	rs = NPI_SUCCESS;
3499 	nxge_status_t	status = NXGE_OK;
3500 
3501 	handle = nxgep->npi_handle;
3502 
3503 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
3504 	    nxgep->mac.portnum));
3505 
3506 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
3507 		goto fail;
3508 
3509 	/* based on speed */
3510 	nxgep->msg_min = ETHERMIN;
3511 
3512 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3513 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
3514 		    CFG_XMAC_TX)) != NPI_SUCCESS)
3515 			goto fail;
3516 	} else {
3517 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
3518 		    CFG_BMAC_TX)) != NPI_SUCCESS)
3519 			goto fail;
3520 	}
3521 
3522 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
3523 	    nxgep->mac.portnum));
3524 
3525 	return (NXGE_OK);
3526 fail:
3527 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3528 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
3529 	    nxgep->mac.portnum));
3530 	if (rs != NPI_SUCCESS)
3531 		return (NXGE_ERROR | rs);
3532 	else
3533 		return (status);
3534 }
3535 
3536 /* Disable TXMAC */
3537 
3538 nxge_status_t
3539 nxge_tx_mac_disable(p_nxge_t nxgep)
3540 {
3541 	npi_handle_t	handle;
3542 	npi_status_t	rs = NPI_SUCCESS;
3543 
3544 	if (isLDOMguest(nxgep))
3545 		return (NXGE_OK);
3546 
3547 	handle = nxgep->npi_handle;
3548 
3549 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
3550 	    nxgep->mac.portnum));
3551 
3552 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3553 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
3554 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
3555 			goto fail;
3556 	} else {
3557 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
3558 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
3559 			goto fail;
3560 	}
3561 
3562 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
3563 	    nxgep->mac.portnum));
3564 	return (NXGE_OK);
3565 fail:
3566 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3567 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
3568 	    nxgep->mac.portnum));
3569 	return (NXGE_ERROR | rs);
3570 }
3571 
3572 /* Enable RXMAC */
3573 
3574 nxge_status_t
3575 nxge_rx_mac_enable(p_nxge_t nxgep)
3576 {
3577 	npi_handle_t	handle;
3578 	uint8_t 	portn;
3579 	npi_status_t	rs = NPI_SUCCESS;
3580 	nxge_status_t	status = NXGE_OK;
3581 
3582 	/* This is a service-domain-only activity. */
3583 	if (isLDOMguest(nxgep))
3584 		return (status);
3585 
3586 	handle = nxgep->npi_handle;
3587 	portn = nxgep->mac.portnum;
3588 
3589 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
3590 	    portn));
3591 
3592 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
3593 		goto fail;
3594 
3595 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3596 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
3597 		    CFG_XMAC_RX)) != NPI_SUCCESS)
3598 			goto fail;
3599 	} else {
3600 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
3601 		    CFG_BMAC_RX)) != NPI_SUCCESS)
3602 			goto fail;
3603 	}
3604 
3605 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3606 	    "<== nxge_rx_mac_enable: port<%d>", portn));
3607 
3608 	return (NXGE_OK);
3609 fail:
3610 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3611 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
3612 
3613 	if (rs != NPI_SUCCESS)
3614 		return (NXGE_ERROR | rs);
3615 	else
3616 		return (status);
3617 }
3618 
3619 /* Disable RXMAC */
3620 
3621 nxge_status_t
3622 nxge_rx_mac_disable(p_nxge_t nxgep)
3623 {
3624 	npi_handle_t	handle;
3625 	uint8_t		portn;
3626 	npi_status_t	rs = NPI_SUCCESS;
3627 
3628 	/* If we are a guest domain driver, don't bother. */
3629 	if (isLDOMguest(nxgep))
3630 		return (NXGE_OK);
3631 
3632 	handle = nxgep->npi_handle;
3633 	portn = nxgep->mac.portnum;
3634 
3635 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
3636 	    portn));
3637 
3638 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3639 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
3640 		    CFG_XMAC_RX)) != NPI_SUCCESS)
3641 			goto fail;
3642 	} else {
3643 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
3644 		    CFG_BMAC_RX)) != NPI_SUCCESS)
3645 			goto fail;
3646 	}
3647 
3648 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
3649 	    portn));
3650 	return (NXGE_OK);
3651 fail:
3652 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3653 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
3654 
3655 	return (NXGE_ERROR | rs);
3656 }
3657 
3658 /* Reset TXMAC */
3659 
3660 nxge_status_t
3661 nxge_tx_mac_reset(p_nxge_t nxgep)
3662 {
3663 	npi_handle_t	handle;
3664 	uint8_t		portn;
3665 	npi_status_t	rs = NPI_SUCCESS;
3666 
3667 	handle = nxgep->npi_handle;
3668 	portn = nxgep->mac.portnum;
3669 
3670 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
3671 	    portn));
3672 
3673 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3674 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
3675 		    != NPI_SUCCESS)
3676 			goto fail;
3677 	} else {
3678 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
3679 		    != NPI_SUCCESS)
3680 			goto fail;
3681 	}
3682 
3683 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
3684 	    portn));
3685 
3686 	return (NXGE_OK);
3687 fail:
3688 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3689 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
3690 
3691 	return (NXGE_ERROR | rs);
3692 }
3693 
3694 /* Reset RXMAC */
3695 
3696 nxge_status_t
3697 nxge_rx_mac_reset(p_nxge_t nxgep)
3698 {
3699 	npi_handle_t	handle;
3700 	uint8_t		portn;
3701 	npi_status_t	rs = NPI_SUCCESS;
3702 
3703 	handle = nxgep->npi_handle;
3704 	portn = nxgep->mac.portnum;
3705 
3706 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
3707 	    portn));
3708 
3709 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3710 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
3711 		    != NPI_SUCCESS)
3712 		goto fail;
3713 	} else {
3714 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
3715 		    != NPI_SUCCESS)
3716 		goto fail;
3717 	}
3718 
3719 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
3720 	    portn));
3721 
3722 	return (NXGE_OK);
3723 fail:
3724 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3725 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
3726 	return (NXGE_ERROR | rs);
3727 }
3728 
3729 /* 10G fiber link interrupt start routine */
3730 
3731 static nxge_status_t
3732 nxge_10G_link_intr_start(p_nxge_t nxgep)
3733 {
3734 	npi_status_t	rs = NPI_SUCCESS;
3735 	uint8_t		portn = nxgep->mac.portnum;
3736 
3737 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
3738 
3739 	if (rs != NPI_SUCCESS)
3740 		return (NXGE_ERROR | rs);
3741 	else
3742 		return (NXGE_OK);
3743 }
3744 
3745 /* 10G fiber link interrupt stop routine */
3746 
3747 static nxge_status_t
3748 nxge_10G_link_intr_stop(p_nxge_t nxgep)
3749 {
3750 	npi_status_t	rs = NPI_SUCCESS;
3751 	uint8_t		portn = nxgep->mac.portnum;
3752 
3753 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
3754 
3755 	if (rs != NPI_SUCCESS)
3756 		return (NXGE_ERROR | rs);
3757 	else
3758 		return (NXGE_OK);
3759 }
3760 
3761 /* 1G fiber link interrupt start routine */
3762 
3763 static nxge_status_t
3764 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
3765 {
3766 	npi_status_t	rs = NPI_SUCCESS;
3767 	uint8_t		portn = nxgep->mac.portnum;
3768 
3769 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
3770 	if (rs != NPI_SUCCESS)
3771 		return (NXGE_ERROR | rs);
3772 	else
3773 		return (NXGE_OK);
3774 }
3775 
3776 /* 1G fiber link interrupt stop routine */
3777 
3778 static nxge_status_t
3779 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
3780 {
3781 	npi_status_t	rs = NPI_SUCCESS;
3782 	uint8_t		portn = nxgep->mac.portnum;
3783 
3784 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
3785 
3786 	if (rs != NPI_SUCCESS)
3787 		return (NXGE_ERROR | rs);
3788 	else
3789 		return (NXGE_OK);
3790 }
3791 
3792 /* 1G copper link interrupt start routine */
3793 
3794 static nxge_status_t
3795 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
3796 {
3797 	npi_status_t	rs = NPI_SUCCESS;
3798 	uint8_t		portn = nxgep->mac.portnum;
3799 
3800 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
3801 	    MII_STATUS, MII_STATUS_LINKUP);
3802 
3803 	if (rs != NPI_SUCCESS)
3804 		return (NXGE_ERROR | rs);
3805 	else
3806 		return (NXGE_OK);
3807 }
3808 
3809 /* 1G copper link interrupt stop routine */
3810 
3811 static nxge_status_t
3812 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
3813 {
3814 	npi_status_t	rs = NPI_SUCCESS;
3815 	uint8_t		portn = nxgep->mac.portnum;
3816 
3817 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
3818 
3819 	if (rs != NPI_SUCCESS)
3820 		return (NXGE_ERROR | rs);
3821 	else
3822 		return (NXGE_OK);
3823 }
3824 
3825 /* Enable/Disable Link Status change interrupt */
3826 
3827 nxge_status_t
3828 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
3829 {
3830 	uint8_t		portn;
3831 	nxge_status_t	status = NXGE_OK;
3832 
3833 	portn = nxgep->mac.portnum;
3834 
3835 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
3836 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
3837 		return (NXGE_OK);
3838 
3839 	if (enable == LINK_INTR_START)
3840 		status = nxgep->xcvr.link_intr_start(nxgep);
3841 	else if (enable == LINK_INTR_STOP)
3842 		status = nxgep->xcvr.link_intr_stop(nxgep);
3843 	if (status != NXGE_OK)
3844 		goto fail;
3845 
3846 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
3847 
3848 	return (NXGE_OK);
3849 fail:
3850 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3851 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
3852 
3853 	return (status);
3854 }
3855 
3856 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
3857 
3858 nxge_status_t
3859 nxge_mii_xcvr_init(p_nxge_t nxgep)
3860 {
3861 	p_nxge_param_t	param_arr;
3862 	p_nxge_stats_t	statsp;
3863 	uint8_t		xcvr_portn;
3864 	p_mii_regs_t	mii_regs;
3865 	mii_bmcr_t	bmcr;
3866 	mii_bmsr_t	bmsr;
3867 	mii_anar_t	anar;
3868 	mii_gcr_t	gcr;
3869 	mii_esr_t	esr;
3870 	mii_aux_ctl_t	bcm5464r_aux;
3871 	int		status = NXGE_OK;
3872 
3873 	uint_t delay;
3874 
3875 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
3876 
3877 	param_arr = nxgep->param_arr;
3878 	statsp = nxgep->statsp;
3879 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3880 
3881 	mii_regs = NULL;
3882 
3883 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3884 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3885 
3886 	/*
3887 	 * The mif phy mode may be connected to either a copper link
3888 	 * or fiber link. Read the mode control register to get the fiber
3889 	 * configuration if it is hard-wired to fiber link.
3890 	 */
3891 	(void) nxge_mii_get_link_mode(nxgep);
3892 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3893 		return (nxge_mii_xcvr_fiber_init(nxgep));
3894 	}
3895 
3896 	/*
3897 	 * Reset the transceiver.
3898 	 */
3899 	delay = 0;
3900 	bmcr.value = 0;
3901 	bmcr.bits.reset = 1;
3902 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3903 #if defined(__i386)
3904 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
3905 #else
3906 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
3907 #endif
3908 	    bmcr.value)) != NXGE_OK)
3909 		goto fail;
3910 	do {
3911 		drv_usecwait(500);
3912 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3913 #if defined(__i386)
3914 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
3915 #else
3916 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
3917 #endif
3918 		    &bmcr.value)) != NXGE_OK)
3919 			goto fail;
3920 		delay++;
3921 	} while ((bmcr.bits.reset) && (delay < 1000));
3922 	if (delay == 1000) {
3923 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
3924 		goto fail;
3925 	}
3926 
3927 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3928 #if defined(__i386)
3929 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3930 #else
3931 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3932 #endif
3933 	    &bmsr.value)) != NXGE_OK)
3934 		goto fail;
3935 
3936 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
3937 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
3938 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
3939 	param_arr[param_anar_100hdx].value = 0;
3940 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
3941 	param_arr[param_anar_10hdx].value = 0;
3942 
3943 	/*
3944 	 * Initialize the xcvr statistics.
3945 	 */
3946 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
3947 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
3948 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
3949 	statsp->mac_stats.cap_100hdx = 0;
3950 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
3951 	statsp->mac_stats.cap_10hdx = 0;
3952 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
3953 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
3954 
3955 	/*
3956 	 * Initialize the xcvr advertised capability statistics.
3957 	 */
3958 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
3959 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3960 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
3961 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
3962 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
3963 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
3964 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
3965 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
3966 	statsp->mac_stats.adv_cap_asmpause =
3967 	    param_arr[param_anar_asmpause].value;
3968 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
3969 
3970 
3971 	/*
3972 	 * Check for extended status just in case we're
3973 	 * running a Gigibit phy.
3974 	 */
3975 	if (bmsr.bits.extend_status) {
3976 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3977 #if defined(__i386)
3978 		    (uint8_t)(uint32_t)(&mii_regs->esr),
3979 #else
3980 		    (uint8_t)(uint64_t)(&mii_regs->esr),
3981 #endif
3982 		    &esr.value)) != NXGE_OK)
3983 			goto fail;
3984 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
3985 		param_arr[param_anar_1000hdx].value = 0;
3986 
3987 		statsp->mac_stats.cap_1000fdx =
3988 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
3989 		statsp->mac_stats.cap_1000hdx = 0;
3990 	} else {
3991 		param_arr[param_anar_1000fdx].value = 0;
3992 		param_arr[param_anar_1000hdx].value = 0;
3993 	}
3994 
3995 	/*
3996 	 * Initialize 1G Statistics once the capability is established.
3997 	 */
3998 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
3999 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4000 
4001 	/*
4002 	 * Initialize the link statistics.
4003 	 */
4004 	statsp->mac_stats.link_T4 = 0;
4005 	statsp->mac_stats.link_asmpause = 0;
4006 	statsp->mac_stats.link_pause = 0;
4007 	statsp->mac_stats.link_speed = 0;
4008 	statsp->mac_stats.link_duplex = 0;
4009 	statsp->mac_stats.link_up = 0;
4010 
4011 	/*
4012 	 * Switch off Auto-negotiation, 100M and full duplex.
4013 	 */
4014 	bmcr.value = 0;
4015 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4016 #if defined(__i386)
4017 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4018 #else
4019 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4020 #endif
4021 	    bmcr.value)) != NXGE_OK)
4022 		goto fail;
4023 
4024 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4025 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4026 		bmcr.bits.loopback = 1;
4027 		bmcr.bits.enable_autoneg = 0;
4028 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4029 			bmcr.bits.speed_1000_sel = 1;
4030 		bmcr.bits.duplex_mode = 1;
4031 		param_arr[param_autoneg].value = 0;
4032 	} else {
4033 		bmcr.bits.loopback = 0;
4034 	}
4035 
4036 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
4037 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
4038 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
4039 		param_arr[param_autoneg].value = 0;
4040 		bcm5464r_aux.value = 0;
4041 		bcm5464r_aux.bits.ext_lb = 1;
4042 		bcm5464r_aux.bits.write_1 = 1;
4043 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4044 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4045 			goto fail;
4046 	}
4047 
4048 	/* If auto-negotiation is desired */
4049 	if (param_arr[param_autoneg].value) {
4050 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4051 		    "Restarting Auto-negotiation."));
4052 		/*
4053 		 * Setup our Auto-negotiation advertisement register.
4054 		 */
4055 		anar.value = 0;
4056 		anar.bits.selector = 1;
4057 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
4058 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
4059 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
4060 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
4061 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
4062 		anar.bits.cap_asmpause = 0;
4063 		anar.bits.cap_pause = 0;
4064 		if (param_arr[param_anar_1000fdx].value ||
4065 		    param_arr[param_anar_100fdx].value ||
4066 		    param_arr[param_anar_10fdx].value) {
4067 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
4068 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
4069 		}
4070 
4071 		/* Write to the auto-negotiation advertisement register */
4072 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4073 #if defined(__i386)
4074 		    (uint8_t)(uint32_t)(&mii_regs->anar),
4075 #else
4076 		    (uint8_t)(uint64_t)(&mii_regs->anar),
4077 #endif
4078 		    anar.value)) != NXGE_OK)
4079 			goto fail;
4080 		if (bmsr.bits.extend_status) {
4081 			gcr.value = 0;
4082 			gcr.bits.ms_mode_en =
4083 			    param_arr[param_master_cfg_enable].value;
4084 			gcr.bits.master =
4085 			    param_arr[param_master_cfg_value].value;
4086 			gcr.bits.link_1000fdx =
4087 			    param_arr[param_anar_1000fdx].value;
4088 			gcr.bits.link_1000hdx =
4089 			    param_arr[param_anar_1000hdx].value;
4090 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4091 #if defined(__i386)
4092 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
4093 #else
4094 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
4095 #endif
4096 			    gcr.value)) != NXGE_OK)
4097 				goto fail;
4098 		}
4099 
4100 		bmcr.bits.enable_autoneg = 1;
4101 		bmcr.bits.restart_autoneg = 1;
4102 
4103 	} else {
4104 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
4105 		bmcr.bits.speed_1000_sel =
4106 		    param_arr[param_anar_1000fdx].value |
4107 		    param_arr[param_anar_1000hdx].value;
4108 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
4109 		    (param_arr[param_anar_100fdx].value |
4110 		    param_arr[param_anar_100hdx].value);
4111 
4112 		/* Force to 1G */
4113 		if (bmcr.bits.speed_1000_sel) {
4114 			statsp->mac_stats.link_speed = 1000;
4115 			gcr.value = 0;
4116 			gcr.bits.ms_mode_en =
4117 			    param_arr[param_master_cfg_enable].value;
4118 			gcr.bits.master =
4119 			    param_arr[param_master_cfg_value].value;
4120 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4121 #if defined(__i386)
4122 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
4123 #else
4124 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
4125 #endif
4126 			    gcr.value)) != NXGE_OK)
4127 				goto fail;
4128 			if (param_arr[param_anar_1000fdx].value) {
4129 				bmcr.bits.duplex_mode = 1;
4130 				statsp->mac_stats.link_duplex = 2;
4131 			} else
4132 				statsp->mac_stats.link_duplex = 1;
4133 
4134 		/* Force to 100M */
4135 		} else if (bmcr.bits.speed_sel) {
4136 			statsp->mac_stats.link_speed = 100;
4137 			if (param_arr[param_anar_100fdx].value) {
4138 				bmcr.bits.duplex_mode = 1;
4139 				statsp->mac_stats.link_duplex = 2;
4140 			} else
4141 				statsp->mac_stats.link_duplex = 1;
4142 
4143 		/* Force to 10M */
4144 		} else {
4145 			statsp->mac_stats.link_speed = 10;
4146 			if (param_arr[param_anar_10fdx].value) {
4147 				bmcr.bits.duplex_mode = 1;
4148 				statsp->mac_stats.link_duplex = 2;
4149 			} else
4150 				statsp->mac_stats.link_duplex = 1;
4151 		}
4152 		if (statsp->mac_stats.link_duplex != 1) {
4153 			statsp->mac_stats.link_asmpause =
4154 			    statsp->mac_stats.cap_asmpause;
4155 			statsp->mac_stats.link_pause =
4156 			    statsp->mac_stats.cap_pause;
4157 		}
4158 
4159 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
4160 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
4161 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
4162 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
4163 				/* BCM5464R 1000mbps external loopback mode */
4164 				gcr.value = 0;
4165 				gcr.bits.ms_mode_en = 1;
4166 				gcr.bits.master = 1;
4167 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
4168 #if defined(__i386)
4169 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
4170 #else
4171 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
4172 #endif
4173 				    gcr.value)) != NXGE_OK)
4174 					goto fail;
4175 				bmcr.value = 0;
4176 				bmcr.bits.speed_1000_sel = 1;
4177 				statsp->mac_stats.link_speed = 1000;
4178 			} else if (statsp->port_stats.lb_mode
4179 			    == nxge_lb_ext100) {
4180 				/* BCM5464R 100mbps external loopback mode */
4181 				bmcr.value = 0;
4182 				bmcr.bits.speed_sel = 1;
4183 				bmcr.bits.duplex_mode = 1;
4184 				statsp->mac_stats.link_speed = 100;
4185 			} else if (statsp->port_stats.lb_mode
4186 			    == nxge_lb_ext10) {
4187 				/* BCM5464R 10mbps external loopback mode */
4188 				bmcr.value = 0;
4189 				bmcr.bits.duplex_mode = 1;
4190 				statsp->mac_stats.link_speed = 10;
4191 			}
4192 		}
4193 	}
4194 
4195 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4196 #if defined(__i386)
4197 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4198 #else
4199 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4200 #endif
4201 	    bmcr.value)) != NXGE_OK)
4202 		goto fail;
4203 
4204 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4205 #if defined(__i386)
4206 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4207 #else
4208 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4209 #endif
4210 	    &bmcr.value)) != NXGE_OK)
4211 		goto fail;
4212 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
4213 
4214 	/*
4215 	 * Initialize the xcvr status kept in the context structure.
4216 	 */
4217 	nxgep->soft_bmsr.value = 0;
4218 
4219 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4220 #if defined(__i386)
4221 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4222 #else
4223 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4224 #endif
4225 	    &nxgep->bmsr.value)) != NXGE_OK)
4226 		goto fail;
4227 
4228 	statsp->mac_stats.xcvr_inits++;
4229 	nxgep->bmsr.value = 0;
4230 
4231 fail:
4232 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4233 	    "<== nxge_mii_xcvr_init status 0x%x", status));
4234 	return (status);
4235 }
4236 
4237 nxge_status_t
4238 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
4239 {
4240 	p_nxge_param_t	param_arr;
4241 	p_nxge_stats_t	statsp;
4242 	uint8_t		xcvr_portn;
4243 	p_mii_regs_t	mii_regs;
4244 	mii_bmcr_t	bmcr;
4245 	mii_bmsr_t	bmsr;
4246 	mii_gcr_t	gcr;
4247 	mii_esr_t	esr;
4248 	mii_aux_ctl_t	bcm5464r_aux;
4249 	int		status = NXGE_OK;
4250 
4251 	uint_t delay;
4252 
4253 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
4254 
4255 	param_arr = nxgep->param_arr;
4256 	statsp = nxgep->statsp;
4257 	xcvr_portn = statsp->mac_stats.xcvr_portn;
4258 
4259 	mii_regs = NULL;
4260 
4261 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4262 	    "nxge_mii_xcvr_fiber_init: "
4263 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
4264 
4265 	/*
4266 	 * Reset the transceiver.
4267 	 */
4268 	delay = 0;
4269 	bmcr.value = 0;
4270 	bmcr.bits.reset = 1;
4271 
4272 #if defined(__i386)
4273 
4274 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4275 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4276 		goto fail;
4277 #else
4278 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4279 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4280 		goto fail;
4281 #endif
4282 	do {
4283 		drv_usecwait(500);
4284 #if defined(__i386)
4285 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4286 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
4287 		    != NXGE_OK)
4288 			goto fail;
4289 #else
4290 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4291 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
4292 		    != NXGE_OK)
4293 			goto fail;
4294 #endif
4295 		delay++;
4296 	} while ((bmcr.bits.reset) && (delay < 1000));
4297 	if (delay == 1000) {
4298 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4299 		goto fail;
4300 	}
4301 
4302 #if defined(__i386)
4303 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4304 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4305 		goto fail;
4306 #else
4307 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4308 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4309 		goto fail;
4310 #endif
4311 
4312 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4313 	param_arr[param_anar_100T4].value = 0;
4314 	param_arr[param_anar_100fdx].value = 0;
4315 	param_arr[param_anar_100hdx].value = 0;
4316 	param_arr[param_anar_10fdx].value = 0;
4317 	param_arr[param_anar_10hdx].value = 0;
4318 
4319 	/*
4320 	 * Initialize the xcvr statistics.
4321 	 */
4322 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4323 	statsp->mac_stats.cap_100T4 = 0;
4324 	statsp->mac_stats.cap_100fdx = 0;
4325 	statsp->mac_stats.cap_100hdx = 0;
4326 	statsp->mac_stats.cap_10fdx = 0;
4327 	statsp->mac_stats.cap_10hdx = 0;
4328 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4329 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4330 
4331 	/*
4332 	 * Initialize the xcvr advertised capability statistics.
4333 	 */
4334 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4335 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4336 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4337 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4338 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4339 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4340 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4341 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4342 	statsp->mac_stats.adv_cap_asmpause =
4343 	    param_arr[param_anar_asmpause].value;
4344 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4345 
4346 	/*
4347 	 * Check for extended status just in case we're
4348 	 * running a Gigibit phy.
4349 	 */
4350 	if (bmsr.bits.extend_status) {
4351 #if defined(__i386)
4352 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4353 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
4354 		    NXGE_OK)
4355 			goto fail;
4356 #else
4357 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4358 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
4359 		    NXGE_OK)
4360 			goto fail;
4361 #endif
4362 		param_arr[param_anar_1000fdx].value &=
4363 		    esr.bits.link_1000fdx;
4364 		param_arr[param_anar_1000hdx].value = 0;
4365 
4366 		statsp->mac_stats.cap_1000fdx =
4367 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4368 		statsp->mac_stats.cap_1000hdx = 0;
4369 	} else {
4370 		param_arr[param_anar_1000fdx].value = 0;
4371 		param_arr[param_anar_1000hdx].value = 0;
4372 	}
4373 
4374 	/*
4375 	 * Initialize 1G Statistics once the capability is established.
4376 	 */
4377 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4378 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4379 
4380 	/*
4381 	 * Initialize the link statistics.
4382 	 */
4383 	statsp->mac_stats.link_T4 = 0;
4384 	statsp->mac_stats.link_asmpause = 0;
4385 	statsp->mac_stats.link_pause = 0;
4386 	statsp->mac_stats.link_speed = 0;
4387 	statsp->mac_stats.link_duplex = 0;
4388 	statsp->mac_stats.link_up = 0;
4389 
4390 	/*
4391 	 * Switch off Auto-negotiation, 100M and full duplex.
4392 	 */
4393 	bmcr.value = 0;
4394 #if defined(__i386)
4395 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4396 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4397 		goto fail;
4398 #else
4399 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4400 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4401 		goto fail;
4402 #endif
4403 
4404 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4405 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4406 		bmcr.bits.loopback = 1;
4407 		bmcr.bits.enable_autoneg = 0;
4408 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4409 			bmcr.bits.speed_1000_sel = 1;
4410 		bmcr.bits.duplex_mode = 1;
4411 		param_arr[param_autoneg].value = 0;
4412 	} else {
4413 		bmcr.bits.loopback = 0;
4414 	}
4415 
4416 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
4417 		param_arr[param_autoneg].value = 0;
4418 		bcm5464r_aux.value = 0;
4419 		bcm5464r_aux.bits.ext_lb = 1;
4420 		bcm5464r_aux.bits.write_1 = 1;
4421 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4422 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4423 			goto fail;
4424 	}
4425 
4426 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
4427 	bmcr.bits.speed_1000_sel = 1;
4428 	bmcr.bits.speed_sel = 0;
4429 	bmcr.bits.duplex_mode = 1;
4430 	statsp->mac_stats.link_speed = 1000;
4431 	statsp->mac_stats.link_duplex = 2;
4432 
4433 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
4434 		/* BCM5464R 1000mbps external loopback mode */
4435 		gcr.value = 0;
4436 		gcr.bits.ms_mode_en = 1;
4437 		gcr.bits.master = 1;
4438 #if defined(__i386)
4439 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4440 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
4441 		    gcr.value)) != NXGE_OK)
4442 			goto fail;
4443 #else
4444 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4445 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
4446 		    gcr.value)) != NXGE_OK)
4447 			goto fail;
4448 #endif
4449 		bmcr.value = 0;
4450 		bmcr.bits.speed_1000_sel = 1;
4451 		statsp->mac_stats.link_speed = 1000;
4452 	}
4453 
4454 #if defined(__i386)
4455 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4456 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4457 	    bmcr.value)) != NXGE_OK)
4458 		goto fail;
4459 #else
4460 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4461 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4462 	    bmcr.value)) != NXGE_OK)
4463 		goto fail;
4464 #endif
4465 
4466 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4467 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
4468 	    bmcr.value));
4469 
4470 #if defined(__i386)
4471 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4472 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4473 		goto fail;
4474 #else
4475 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4476 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4477 		goto fail;
4478 #endif
4479 
4480 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4481 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
4482 
4483 	/*
4484 	 * Initialize the xcvr status kept in the context structure.
4485 	 */
4486 	nxgep->soft_bmsr.value = 0;
4487 #if defined(__i386)
4488 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4489 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4490 	    &nxgep->bmsr.value)) != NXGE_OK)
4491 		goto fail;
4492 #else
4493 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4494 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4495 	    &nxgep->bmsr.value)) != NXGE_OK)
4496 		goto fail;
4497 #endif
4498 
4499 	statsp->mac_stats.xcvr_inits++;
4500 	nxgep->bmsr.value = 0;
4501 
4502 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4503 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4504 	return (status);
4505 
4506 fail:
4507 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4508 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4509 	return (status);
4510 }
4511 
4512 /* Read from a MII compliant register */
4513 
4514 nxge_status_t
4515 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
4516 		uint16_t *value)
4517 {
4518 	npi_status_t rs = NPI_SUCCESS;
4519 
4520 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
4521 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
4522 
4523 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4524 
4525 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4526 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
4527 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
4528 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
4529 			goto fail;
4530 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
4531 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
4532 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
4533 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
4534 			goto fail;
4535 	} else
4536 		goto fail;
4537 
4538 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4539 
4540 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
4541 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
4542 	return (NXGE_OK);
4543 fail:
4544 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4545 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4546 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
4547 
4548 	return (NXGE_ERROR | rs);
4549 }
4550 
4551 /* Write to a MII compliant Register */
4552 
4553 nxge_status_t
4554 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
4555 		uint16_t value)
4556 {
4557 	npi_status_t rs = NPI_SUCCESS;
4558 
4559 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
4560 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
4561 
4562 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4563 
4564 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4565 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
4566 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4567 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
4568 			goto fail;
4569 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
4570 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
4571 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
4572 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
4573 			goto fail;
4574 	} else
4575 		goto fail;
4576 
4577 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4578 
4579 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
4580 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
4581 	return (NXGE_OK);
4582 fail:
4583 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4584 
4585 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4586 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
4587 
4588 	return (NXGE_ERROR | rs);
4589 }
4590 
4591 /*
4592  * Perform write to Clause45 serdes / transceiver device
4593  * Arguments:
4594  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
4595  *			number if nxge_mdio_write is used for accessing the
4596  *			internal LSIL serdes. Otherwise PHYAD is different
4597  * 			for different platforms.
4598  *	device:		With each PHYAD, the driver can use MDIO to control
4599  *			multiple devices inside the PHY, here "device" is an
4600  *			MMD (MDIO managable device).
4601  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
4602  *			the register which the driver will write value to.
4603  *	value:		The register value will be filled in.
4604  */
4605 nxge_status_t
4606 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
4607 		uint16_t xcvr_reg, uint16_t *value)
4608 {
4609 	npi_status_t rs = NPI_SUCCESS;
4610 
4611 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
4612 	    xcvr_portn));
4613 
4614 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4615 
4616 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
4617 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
4618 		goto fail;
4619 
4620 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4621 
4622 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
4623 	    xcvr_portn));
4624 	return (NXGE_OK);
4625 fail:
4626 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4627 
4628 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4629 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
4630 
4631 	return (NXGE_ERROR | rs);
4632 }
4633 
4634 /* Perform write to Clause45 serdes / transceiver device */
4635 
4636 nxge_status_t
4637 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
4638 		uint16_t xcvr_reg, uint16_t value)
4639 {
4640 	npi_status_t rs = NPI_SUCCESS;
4641 
4642 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
4643 	    xcvr_portn));
4644 
4645 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
4646 
4647 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
4648 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
4649 		goto fail;
4650 
4651 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4652 
4653 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
4654 	    xcvr_portn));
4655 	return (NXGE_OK);
4656 fail:
4657 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
4658 
4659 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4660 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
4661 
4662 	return (NXGE_ERROR | rs);
4663 }
4664 
4665 
4666 /* Check MII to see if there is any link status change */
4667 
4668 nxge_status_t
4669 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
4670 		nxge_link_state_t *link_up)
4671 {
4672 	p_nxge_param_t	param_arr;
4673 	p_nxge_stats_t	statsp;
4674 	p_mii_regs_t	mii_regs;
4675 	p_mii_bmsr_t	soft_bmsr;
4676 	mii_anar_t	anar;
4677 	mii_anlpar_t	anlpar;
4678 	mii_anar_t	an_common;
4679 	mii_aner_t	aner;
4680 	mii_gsr_t	gsr;
4681 	nxge_status_t	status = NXGE_OK;
4682 
4683 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
4684 
4685 	mii_regs = NULL;
4686 	param_arr = nxgep->param_arr;
4687 	statsp = nxgep->statsp;
4688 	soft_bmsr = &nxgep->soft_bmsr;
4689 	*link_up = LINK_NO_CHANGE;
4690 
4691 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4692 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
4693 	    bmsr.value, bmsr_ints.value));
4694 
4695 	if (bmsr_ints.bits.link_status) {
4696 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4697 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
4698 		    bmsr.value, bmsr_ints.value));
4699 		if (bmsr.bits.link_status) {
4700 			soft_bmsr->bits.link_status = 1;
4701 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4702 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
4703 		    "0x%x", bmsr.value, bmsr_ints.value));
4704 		} else {
4705 			/* Only status change will update *link_up */
4706 			if (statsp->mac_stats.link_up == 1) {
4707 				*link_up = LINK_IS_DOWN;
4708 				/* Will notify, turn off further msg */
4709 				nxgep->link_notify = B_FALSE;
4710 			}
4711 			statsp->mac_stats.link_up = 0;
4712 			soft_bmsr->bits.link_status = 0;
4713 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4714 			    "Link down cable problem"));
4715 		}
4716 	}
4717 
4718 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
4719 	    param_arr[param_autoneg].value) {
4720 		if (bmsr_ints.bits.auto_neg_complete) {
4721 			if (bmsr.bits.auto_neg_complete)
4722 				soft_bmsr->bits.auto_neg_complete = 1;
4723 			else
4724 				soft_bmsr->bits.auto_neg_complete = 0;
4725 		}
4726 		if (soft_bmsr->bits.link_status == 0) {
4727 			statsp->mac_stats.link_T4 = 0;
4728 			statsp->mac_stats.link_speed = 0;
4729 			statsp->mac_stats.link_duplex = 0;
4730 			statsp->mac_stats.link_asmpause = 0;
4731 			statsp->mac_stats.link_pause = 0;
4732 			statsp->mac_stats.lp_cap_autoneg = 0;
4733 			statsp->mac_stats.lp_cap_100T4 = 0;
4734 			statsp->mac_stats.lp_cap_1000fdx = 0;
4735 			statsp->mac_stats.lp_cap_1000hdx = 0;
4736 			statsp->mac_stats.lp_cap_100fdx = 0;
4737 			statsp->mac_stats.lp_cap_100hdx = 0;
4738 			statsp->mac_stats.lp_cap_10fdx = 0;
4739 			statsp->mac_stats.lp_cap_10hdx = 0;
4740 			statsp->mac_stats.lp_cap_10gfdx = 0;
4741 			statsp->mac_stats.lp_cap_10ghdx = 0;
4742 			statsp->mac_stats.lp_cap_asmpause = 0;
4743 			statsp->mac_stats.lp_cap_pause = 0;
4744 		}
4745 	} else
4746 		soft_bmsr->bits.auto_neg_complete = 1;
4747 
4748 	if ((bmsr_ints.bits.link_status ||
4749 	    bmsr_ints.bits.auto_neg_complete) &&
4750 	    soft_bmsr->bits.link_status &&
4751 	    soft_bmsr->bits.auto_neg_complete) {
4752 		if (statsp->mac_stats.link_up == 0) {
4753 			*link_up = LINK_IS_UP;
4754 			nxgep->link_notify = B_FALSE;
4755 		}
4756 		statsp->mac_stats.link_up = 1;
4757 
4758 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4759 		    "==> nxge_mii_check "
4760 		    "(auto negotiation complete or link up) "
4761 		    "soft bmsr 0x%x bmsr_int 0x%x",
4762 		    bmsr.value, bmsr_ints.value));
4763 
4764 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4765 		    param_arr[param_autoneg].value) {
4766 			if ((status = nxge_mii_read(nxgep,
4767 			    statsp->mac_stats.xcvr_portn,
4768 #if defined(__i386)
4769 			    (uint8_t)(uint32_t)(&mii_regs->anar),
4770 #else
4771 			    (uint8_t)(uint64_t)(&mii_regs->anar),
4772 #endif
4773 			    &anar.value)) != NXGE_OK)
4774 				goto fail;
4775 			if ((status = nxge_mii_read(nxgep,
4776 			    statsp->mac_stats.xcvr_portn,
4777 #if defined(__i386)
4778 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
4779 #else
4780 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
4781 #endif
4782 			    &anlpar.value)) != NXGE_OK)
4783 				goto fail;
4784 			if ((status = nxge_mii_read(nxgep,
4785 			    statsp->mac_stats.xcvr_portn,
4786 #if defined(__i386)
4787 			    (uint8_t)(uint32_t)(&mii_regs->aner),
4788 #else
4789 			    (uint8_t)(uint64_t)(&mii_regs->aner),
4790 #endif
4791 			    &aner.value)) != NXGE_OK)
4792 				goto fail;
4793 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
4794 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
4795 			statsp->mac_stats.lp_cap_100fdx =
4796 			    anlpar.bits.cap_100fdx;
4797 			statsp->mac_stats.lp_cap_100hdx =
4798 			    anlpar.bits.cap_100hdx;
4799 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
4800 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
4801 			statsp->mac_stats.lp_cap_asmpause =
4802 			    anlpar.bits.cap_asmpause;
4803 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
4804 			an_common.value = anar.value & anlpar.value;
4805 			if (param_arr[param_anar_1000fdx].value ||
4806 			    param_arr[param_anar_1000hdx].value) {
4807 				if ((status = nxge_mii_read(nxgep,
4808 				    statsp->mac_stats.xcvr_portn,
4809 #if defined(__i386)
4810 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
4811 #else
4812 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
4813 #endif
4814 				    &gsr.value)) != NXGE_OK)
4815 					goto fail;
4816 				statsp->mac_stats.lp_cap_1000fdx =
4817 				    gsr.bits.link_1000fdx;
4818 				statsp->mac_stats.lp_cap_1000hdx =
4819 				    gsr.bits.link_1000hdx;
4820 				if (param_arr[param_anar_1000fdx].value &&
4821 				    gsr.bits.link_1000fdx) {
4822 					statsp->mac_stats.link_speed = 1000;
4823 					statsp->mac_stats.link_duplex = 2;
4824 				} else if (
4825 				    param_arr[param_anar_1000hdx].value &&
4826 				    gsr.bits.link_1000hdx) {
4827 					statsp->mac_stats.link_speed = 1000;
4828 					statsp->mac_stats.link_duplex = 1;
4829 				}
4830 			}
4831 			if ((an_common.value != 0) &&
4832 			    !(statsp->mac_stats.link_speed)) {
4833 				if (an_common.bits.cap_100T4) {
4834 					statsp->mac_stats.link_T4 = 1;
4835 					statsp->mac_stats.link_speed = 100;
4836 					statsp->mac_stats.link_duplex = 1;
4837 				} else if (an_common.bits.cap_100fdx) {
4838 					statsp->mac_stats.link_speed = 100;
4839 					statsp->mac_stats.link_duplex = 2;
4840 				} else if (an_common.bits.cap_100hdx) {
4841 					statsp->mac_stats.link_speed = 100;
4842 					statsp->mac_stats.link_duplex = 1;
4843 				} else if (an_common.bits.cap_10fdx) {
4844 					statsp->mac_stats.link_speed = 10;
4845 					statsp->mac_stats.link_duplex = 2;
4846 				} else if (an_common.bits.cap_10hdx) {
4847 					statsp->mac_stats.link_speed = 10;
4848 					statsp->mac_stats.link_duplex = 1;
4849 				} else {
4850 					goto fail;
4851 				}
4852 			}
4853 			if (statsp->mac_stats.link_duplex != 1) {
4854 				int	link_pause;
4855 				int	cp, lcp;
4856 
4857 				statsp->mac_stats.link_asmpause =
4858 				    an_common.bits.cap_asmpause;
4859 				cp = statsp->mac_stats.cap_pause;
4860 				lcp = statsp->mac_stats.lp_cap_pause;
4861 				if (statsp->mac_stats.link_asmpause) {
4862 					if ((cp == 0) && (lcp == 1)) {
4863 						link_pause = 0;
4864 					} else {
4865 						link_pause = 1;
4866 					}
4867 				} else {
4868 					link_pause = an_common.bits.cap_pause;
4869 				}
4870 				statsp->mac_stats.link_pause = link_pause;
4871 			}
4872 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4873 			statsp->mac_stats.link_speed = 1000;
4874 			statsp->mac_stats.link_duplex = 2;
4875 		}
4876 	}
4877 	/* Initial link_notify, delay link down msg */
4878 	if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
4879 	    (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) {
4880 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
4881 		    LINK_IS_DOWN);
4882 		nxgep->link_notify = B_FALSE;
4883 	}
4884 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
4885 	return (NXGE_OK);
4886 fail:
4887 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4888 	    "nxge_mii_check: Unable to check MII"));
4889 	return (status);
4890 }
4891 
4892 /*
4893  * Check PCS to see if there is any link status change.
4894  * This function is called by PORT_1G_SERDES only.
4895  */
4896 void
4897 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
4898 {
4899 	p_nxge_stats_t	statsp;
4900 	boolean_t	linkup;
4901 
4902 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
4903 
4904 	statsp = nxgep->statsp;
4905 	*link_up = LINK_NO_CHANGE;
4906 
4907 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
4908 	if (linkup) {
4909 		if ((nxgep->link_notify &&
4910 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
4911 		    nxgep->statsp->mac_stats.link_up == 0) {
4912 			statsp->mac_stats.link_up = 1;
4913 			statsp->mac_stats.link_speed = 1000;
4914 			statsp->mac_stats.link_duplex = 2;
4915 			*link_up = LINK_IS_UP;
4916 			nxgep->link_notify = B_FALSE;
4917 		}
4918 	} else {
4919 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
4920 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
4921 		    nxgep->statsp->mac_stats.link_up == 1) {
4922 			statsp->mac_stats.link_up = 0;
4923 			statsp->mac_stats.link_speed = 0;
4924 			statsp->mac_stats.link_duplex = 0;
4925 			*link_up = LINK_IS_DOWN;
4926 			nxgep->link_notify = B_FALSE;
4927 		}
4928 	}
4929 
4930 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
4931 }
4932 
4933 /* Add a multicast address entry into the HW hash table */
4934 
4935 nxge_status_t
4936 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
4937 {
4938 	uint32_t mchash;
4939 	p_hash_filter_t hash_filter;
4940 	uint16_t hash_bit;
4941 	uint_t j;
4942 	nxge_status_t status = NXGE_OK;
4943 	npi_status_t rs;
4944 
4945 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
4946 
4947 	RW_ENTER_WRITER(&nxgep->filter_lock);
4948 	mchash = crc32_mchash(addrp);
4949 	if (nxgep->hash_filter == NULL) {
4950 		NXGE_DEBUG_MSG((NULL, STR_CTL,
4951 		    "Allocating hash filter storage."));
4952 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
4953 		    KM_SLEEP);
4954 	}
4955 
4956 	hash_filter = nxgep->hash_filter;
4957 	j = mchash / HASH_REG_WIDTH;
4958 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
4959 	hash_filter->hash_filter_regs[j] |= hash_bit;
4960 	hash_filter->hash_bit_ref_cnt[mchash]++;
4961 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
4962 		hash_filter->hash_ref_cnt++;
4963 	}
4964 
4965 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
4966 	if (rs != NPI_SUCCESS)
4967 		goto fail;
4968 
4969 	RW_EXIT(&nxgep->filter_lock);
4970 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
4971 	return (NXGE_OK);
4972 fail:
4973 	RW_EXIT(&nxgep->filter_lock);
4974 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
4975 	    "Unable to add multicast address"));
4976 	return (status);
4977 }
4978 
4979 /* Remove a multicast address entry from the HW hash table */
4980 
4981 nxge_status_t
4982 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
4983 {
4984 	uint32_t mchash;
4985 	p_hash_filter_t hash_filter;
4986 	uint16_t hash_bit;
4987 	uint_t j;
4988 	nxge_status_t status = NXGE_OK;
4989 	npi_status_t rs;
4990 
4991 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
4992 	RW_ENTER_WRITER(&nxgep->filter_lock);
4993 	mchash = crc32_mchash(addrp);
4994 	if (nxgep->hash_filter == NULL) {
4995 		NXGE_DEBUG_MSG((NULL, STR_CTL,
4996 		    "Hash filter already de_allocated."));
4997 		RW_EXIT(&nxgep->filter_lock);
4998 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
4999 		return (NXGE_OK);
5000 	}
5001 	hash_filter = nxgep->hash_filter;
5002 	hash_filter->hash_bit_ref_cnt[mchash]--;
5003 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
5004 		j = mchash / HASH_REG_WIDTH;
5005 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
5006 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
5007 		hash_filter->hash_ref_cnt--;
5008 	}
5009 
5010 	if (hash_filter->hash_ref_cnt == 0) {
5011 		NXGE_DEBUG_MSG((NULL, STR_CTL,
5012 		    "De-allocating hash filter storage."));
5013 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
5014 		nxgep->hash_filter = NULL;
5015 	}
5016 
5017 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
5018 	if (rs != NPI_SUCCESS)
5019 		goto fail;
5020 
5021 	RW_EXIT(&nxgep->filter_lock);
5022 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
5023 
5024 	return (NXGE_OK);
5025 fail:
5026 	RW_EXIT(&nxgep->filter_lock);
5027 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
5028 	    "Unable to remove multicast address"));
5029 
5030 	return (status);
5031 }
5032 
5033 /* Set MAC address into MAC address HW registers */
5034 
5035 nxge_status_t
5036 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
5037 {
5038 	nxge_status_t status = NXGE_OK;
5039 
5040 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
5041 
5042 	MUTEX_ENTER(&nxgep->ouraddr_lock);
5043 	/*
5044 	 * Exit if the address is same as ouraddr or multicast or broadcast
5045 	 */
5046 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
5047 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
5048 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
5049 		goto nxge_set_mac_addr_exit;
5050 	}
5051 	nxgep->ouraddr = *addrp;
5052 	/*
5053 	 * Set new interface local address and re-init device.
5054 	 * This is destructive to any other streams attached
5055 	 * to this device.
5056 	 */
5057 	RW_ENTER_WRITER(&nxgep->filter_lock);
5058 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
5059 		goto fail;
5060 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
5061 		goto fail;
5062 
5063 	RW_EXIT(&nxgep->filter_lock);
5064 	MUTEX_EXIT(&nxgep->ouraddr_lock);
5065 	goto nxge_set_mac_addr_end;
5066 nxge_set_mac_addr_exit:
5067 	MUTEX_EXIT(&nxgep->ouraddr_lock);
5068 nxge_set_mac_addr_end:
5069 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
5070 
5071 	return (NXGE_OK);
5072 fail:
5073 	MUTEX_EXIT(&nxgep->ouraddr_lock);
5074 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
5075 	    "Unable to set mac address"));
5076 	return (status);
5077 }
5078 
5079 static
5080 check_link_state_t
5081 nxge_check_link_stop(nxge_t *nxge)
5082 {
5083 	/* If the poll has been cancelled, return STOP. */
5084 	MUTEX_ENTER(&nxge->poll_lock);
5085 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
5086 		nxge->poll_state = LINK_MONITOR_STOP;
5087 		nxge->nxge_link_poll_timerid = 0;
5088 		cv_broadcast(&nxge->poll_cv);
5089 		MUTEX_EXIT(&nxge->poll_lock);
5090 
5091 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
5092 		    "nxge_check_%s_link(port<%d>) stopped.",
5093 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
5094 		    nxge->mac.portnum));
5095 		return (CHECK_LINK_STOP);
5096 	}
5097 	MUTEX_EXIT(&nxge->poll_lock);
5098 
5099 	return (CHECK_LINK_RESCHEDULE);
5100 }
5101 
5102 /*
5103  * Check status of MII (MIF or PCS) link.
5104  * This function is called once per second, that is because this function
5105  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
5106  * call this function recursively.
5107  */
5108 static nxge_status_t
5109 nxge_check_mii_link(p_nxge_t nxgep)
5110 {
5111 	mii_bmsr_t bmsr_ints, bmsr_data;
5112 	mii_anlpar_t anlpar;
5113 	mii_gsr_t gsr;
5114 	p_mii_regs_t mii_regs;
5115 	nxge_status_t status = NXGE_OK;
5116 	uint8_t portn;
5117 	nxge_link_state_t link_up;
5118 
5119 	if (nxgep->nxge_magic != NXGE_MAGIC)
5120 		return (NXGE_ERROR);
5121 
5122 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
5123 		return (NXGE_OK);
5124 
5125 	portn = nxgep->mac.portnum;
5126 
5127 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
5128 	    portn));
5129 
5130 	mii_regs = NULL;
5131 
5132 	RW_ENTER_WRITER(&nxgep->filter_lock);
5133 
5134 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
5135 		goto nxge_check_mii_link_exit;
5136 
5137 	switch (nxgep->mac.portmode) {
5138 	default:
5139 		bmsr_data.value = 0;
5140 		if ((status = nxge_mii_read(nxgep,
5141 		    nxgep->statsp->mac_stats.xcvr_portn,
5142 #if defined(__i386)
5143 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5144 #else
5145 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5146 #endif
5147 		    &bmsr_data.value)) != NXGE_OK) {
5148 			goto fail;
5149 		}
5150 
5151 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5152 		    "==> nxge_check_mii_link port<0x%x> "
5153 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
5154 		    portn, bmsr_data.value, nxgep->bmsr.value));
5155 
5156 		if (nxgep->param_arr[param_autoneg].value) {
5157 			if ((status = nxge_mii_read(nxgep,
5158 			    nxgep->statsp->mac_stats.xcvr_portn,
5159 #if defined(__i386)
5160 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
5161 #else
5162 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
5163 #endif
5164 			    &gsr.value)) != NXGE_OK)
5165 				goto fail;
5166 			if ((status = nxge_mii_read(nxgep,
5167 			    nxgep->statsp->mac_stats.xcvr_portn,
5168 #if defined(__i386)
5169 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
5170 #else
5171 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
5172 #endif
5173 			    &anlpar.value)) != NXGE_OK)
5174 				goto fail;
5175 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
5176 
5177 				if (nxgep->statsp->mac_stats.link_up &&
5178 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
5179 				    gsr.bits.link_1000fdx) ||
5180 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
5181 				    gsr.bits.link_1000hdx) ||
5182 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
5183 				    anlpar.bits.cap_100T4) ||
5184 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
5185 				    anlpar.bits.cap_100fdx) ||
5186 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
5187 				    anlpar.bits.cap_100hdx) ||
5188 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
5189 				    anlpar.bits.cap_10fdx) ||
5190 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
5191 				    anlpar.bits.cap_10hdx))) {
5192 					bmsr_data.bits.link_status = 0;
5193 				}
5194 			}
5195 		}
5196 
5197 		/* Workaround for link down issue */
5198 		if (bmsr_data.value == 0) {
5199 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
5200 			goto nxge_check_mii_link_exit;
5201 		}
5202 
5203 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5204 		    "==> nxge_check_mii_link port<0x%x> :"
5205 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
5206 		    portn, nxgep->bmsr.value, bmsr_data.value));
5207 
5208 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
5209 		nxgep->bmsr.value = bmsr_data.value;
5210 
5211 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5212 		    "==> nxge_check_mii_link port<0x%x> CALLING "
5213 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
5214 		    portn, bmsr_data.value, bmsr_ints.value));
5215 
5216 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
5217 		    &link_up)) != NXGE_OK) {
5218 			goto fail;
5219 		}
5220 		break;
5221 
5222 	case PORT_1G_SERDES:
5223 		/*
5224 		 * Above default is for all cases except PORT_1G_SERDES.
5225 		 * The default case gets information from the PHY, but a
5226 		 * nxge whose portmode equals PORT_1G_SERDES does not
5227 		 * have a PHY.
5228 		 */
5229 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5230 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
5231 		nxge_pcs_check(nxgep, portn, &link_up);
5232 		break;
5233 	}
5234 
5235 nxge_check_mii_link_exit:
5236 	RW_EXIT(&nxgep->filter_lock);
5237 	if (link_up == LINK_IS_UP) {
5238 		nxge_link_is_up(nxgep);
5239 	} else if (link_up == LINK_IS_DOWN) {
5240 		nxge_link_is_down(nxgep);
5241 	}
5242 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
5243 
5244 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
5245 	    portn));
5246 	return (NXGE_OK);
5247 
5248 fail:
5249 	RW_EXIT(&nxgep->filter_lock);
5250 
5251 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
5252 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5253 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
5254 	return (status);
5255 }
5256 
5257 /*ARGSUSED*/
5258 static nxge_status_t
5259 nxge_check_10g_link(p_nxge_t nxgep)
5260 {
5261 	uint8_t		portn;
5262 	nxge_status_t	status = NXGE_OK;
5263 	boolean_t	link_up;
5264 	uint32_t	val;
5265 	npi_status_t	rs;
5266 
5267 	if (nxgep->nxge_magic != NXGE_MAGIC)
5268 		return (NXGE_ERROR);
5269 
5270 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
5271 		return (NXGE_OK);
5272 
5273 	portn = nxgep->mac.portnum;
5274 	val = 0;
5275 	rs = NPI_SUCCESS;
5276 
5277 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
5278 	    portn));
5279 
5280 	switch (nxgep->mac.portmode) {
5281 	default:
5282 		/*
5283 		 * Check if the phy is present in case of hot swappable phy
5284 		 */
5285 		if (nxgep->hot_swappable_phy) {
5286 			boolean_t phy_present_now = B_FALSE;
5287 
5288 			/*
5289 			 * If this is the 2nd Goa port, then check 2 addresses
5290 			 * to take care of the Goa NEM card requirements.
5291 			 */
5292 			if (portn == 1) {
5293 				if (nxge_is_phy_present(nxgep,
5294 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
5295 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
5296 					phy_present_now = B_TRUE;
5297 					nxgep->xcvr_addr =
5298 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
5299 					goto phy_check_done;
5300 				}
5301 			}
5302 			if (nxge_is_phy_present(nxgep,
5303 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
5304 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
5305 				nxgep->xcvr_addr =
5306 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
5307 				phy_present_now = B_TRUE;
5308 			}
5309 
5310 phy_check_done:
5311 			/* Check back-to-back XAUI connect to detect Opus NEM */
5312 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
5313 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
5314 			if (rs != 0)
5315 				goto fail;
5316 
5317 			link_up = B_FALSE;
5318 			if (val & XPCS_STATUS_LANE_ALIGN) {
5319 				link_up = B_TRUE;
5320 			}
5321 
5322 			if (nxgep->phy_absent) {
5323 				if (phy_present_now) {
5324 				/*
5325 				 * Detect, Initialize phy and do link up
5326 				 * set xcvr vals, link_init, nxge_init
5327 				 */
5328 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5329 					    "Hot swappable phy DETECTED!!"));
5330 					nxgep->phy_absent = B_FALSE;
5331 					(void) nxge_xcvr_find(nxgep);
5332 					(void) nxge_link_init(nxgep);
5333 					if (!(nxgep->drv_state &
5334 					    STATE_HW_INITIALIZED)) {
5335 						status = nxge_init(nxgep);
5336 						if (status != NXGE_OK) {
5337 							NXGE_ERROR_MSG((nxgep,
5338 							    NXGE_ERR_CTL,
5339 							    "Hot swappable "
5340 							    "phy present, but"
5341 							    " driver init"
5342 							    "  failed..."));
5343 							goto fail;
5344 						}
5345 					}
5346 				} else if (link_up) { /* XAUI linkup, no PHY */
5347 					/*
5348 					 * This is the back-to-back XAUI
5349 					 * connect case for Opus NEM.
5350 					 */
5351 					nxgep->statsp->mac_stats.xcvr_inuse =
5352 					    XPCS_XCVR;
5353 					nxgep->mac.portmode = PORT_10G_SERDES;
5354 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5355 					    "HSP 10G Serdes DETECTED!!"));
5356 					break;
5357 				}
5358 
5359 				if (nxgep->link_notify &&
5360 				    nxgep->link_check_count > 3 &&
5361 				    nxgep->nxge_mac_state == NXGE_MAC_STARTED ||
5362 				    nxgep->statsp->mac_stats.link_up == 1) {
5363 					nxgep->statsp->mac_stats.link_up = 0;
5364 					nxgep->statsp->mac_stats.link_speed = 0;
5365 					nxgep->statsp->mac_stats.link_duplex =
5366 					    0;
5367 
5368 					nxge_link_is_down(nxgep);
5369 					nxgep->link_notify = B_FALSE;
5370 				}
5371 
5372 				goto start_link_check;
5373 
5374 			} else if (!phy_present_now) {
5375 				/*
5376 				 * Phy gone, bring link down reset xcvr vals
5377 				 */
5378 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5379 				    "Hot swappable phy REMOVED!!"));
5380 				nxgep->phy_absent = B_TRUE;
5381 				nxgep->statsp->mac_stats.link_up = 0;
5382 				nxgep->statsp->mac_stats.link_speed = 0;
5383 				nxgep->statsp->mac_stats.link_duplex = 0;
5384 				nxge_link_is_down(nxgep);
5385 				nxgep->link_notify = B_FALSE;
5386 
5387 				(void) nxge_xcvr_find(nxgep);
5388 
5389 				goto start_link_check;
5390 
5391 			}
5392 		}
5393 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
5394 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
5395 		} else {
5396 			status = nxge_check_bcm8704_link(nxgep, &link_up);
5397 		}
5398 		if (status != NXGE_OK)
5399 			goto fail;
5400 		break;
5401 	case PORT_10G_SERDES:
5402 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5403 		    XPCS_REG_STATUS, &val);
5404 		if (rs != 0)
5405 			goto fail;
5406 
5407 		link_up = B_FALSE;
5408 		if (val & XPCS_STATUS_LANE_ALIGN) {
5409 			link_up = B_TRUE;
5410 		}
5411 
5412 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5413 		    "==> nxge_check_10g_link port<%d> "
5414 		    "XPCS_REG_STATUS2 0x%x link_up %d",
5415 		    portn, val, link_up));
5416 
5417 		break;
5418 	}
5419 
5420 	if (link_up) {
5421 		if ((nxgep->link_notify &&
5422 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5423 		    nxgep->statsp->mac_stats.link_up == 0) {
5424 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
5425 				goto fail;
5426 			nxgep->statsp->mac_stats.link_up = 1;
5427 			nxgep->statsp->mac_stats.link_speed = 10000;
5428 			nxgep->statsp->mac_stats.link_duplex = 2;
5429 
5430 			nxge_link_is_up(nxgep);
5431 			nxgep->link_notify = B_FALSE;
5432 		}
5433 	} else {
5434 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
5435 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5436 		    nxgep->statsp->mac_stats.link_up == 1) {
5437 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
5438 				goto fail;
5439 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5440 			    "Link down cable problem"));
5441 			nxgep->statsp->mac_stats.link_up = 0;
5442 			nxgep->statsp->mac_stats.link_speed = 0;
5443 			nxgep->statsp->mac_stats.link_duplex = 0;
5444 
5445 			nxge_link_is_down(nxgep);
5446 			nxgep->link_notify = B_FALSE;
5447 
5448 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
5449 				/*
5450 				 * NEM was unplugged, set up xcvr table
5451 				 * to find another xcvr in the future.
5452 				 */
5453 				(void) nxge_xcvr_find(nxgep);
5454 			}
5455 		}
5456 	}
5457 
5458 start_link_check:
5459 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
5460 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
5461 	    portn));
5462 	return (NXGE_OK);
5463 
5464 fail:
5465 	(void) nxge_check_link_stop(nxgep);
5466 
5467 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5468 	    "nxge_check_10g_link: Failed to check link port<%d>",
5469 	    portn));
5470 	return (status);
5471 }
5472 
5473 
5474 /* Declare link down */
5475 
5476 void
5477 nxge_link_is_down(p_nxge_t nxgep)
5478 {
5479 	p_nxge_stats_t statsp;
5480 	char link_stat_msg[64];
5481 
5482 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
5483 
5484 	statsp = nxgep->statsp;
5485 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
5486 	    statsp->mac_stats.xcvr_portn);
5487 
5488 	if (nxge_no_msg == B_FALSE) {
5489 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
5490 	}
5491 
5492 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
5493 
5494 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
5495 }
5496 
5497 /* Declare link up */
5498 
5499 void
5500 nxge_link_is_up(p_nxge_t nxgep)
5501 {
5502 	p_nxge_stats_t statsp;
5503 	char link_stat_msg[64];
5504 	uint32_t val;
5505 
5506 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
5507 
5508 	statsp = nxgep->statsp;
5509 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
5510 	    statsp->mac_stats.xcvr_portn,
5511 	    statsp->mac_stats.link_speed);
5512 
5513 	if (statsp->mac_stats.link_T4)
5514 		(void) strcat(link_stat_msg, "T4");
5515 	else if (statsp->mac_stats.link_duplex == 2)
5516 		(void) strcat(link_stat_msg, "full duplex");
5517 	else
5518 		(void) strcat(link_stat_msg, "half duplex");
5519 
5520 
5521 	/* Clean up symbol errors incurred during link transition */
5522 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
5523 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
5524 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5525 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
5526 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5527 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
5528 	}
5529 
5530 	/*
5531 	 * If the driver was plumbed without a link (therefore auto-negotiation
5532 	 * could not complete), the driver will detect a link up when a cable
5533 	 * conneting to a link partner is plugged into the port. By the time
5534 	 * link-up is detected, auto-negotiation should have completed (The
5535 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
5536 	 * configure the Neptune/NIU according to the newly negotiated speed.
5537 	 * This is necessary only for the TN1010 basad device because only the
5538 	 * TN1010 supports dual speeds.
5539 	 */
5540 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
5541 	    nxgep->mac.portmode == PORT_10G_TN1010) {
5542 
5543 		(void) nxge_set_tn1010_param(nxgep);
5544 
5545 		/*
5546 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
5547 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
5548 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
5549 		 */
5550 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
5551 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5552 			    "nxge_link_is_up: nxge_xcvr_find failed"));
5553 		}
5554 
5555 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
5556 		if (nxge_link_init(nxgep) != NXGE_OK) {
5557 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5558 			    "nxge_link_is_up: nxge_link_init failed"));
5559 		}
5560 
5561 		/*
5562 		 * nxge_mac_init calls many subroutines including
5563 		 * nxge_xif_init which sets XGMII or GMII mode
5564 		 */
5565 		if (nxge_mac_init(nxgep) != NXGE_OK) {
5566 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5567 			    "nxge_link_is_up: nxge_mac_init failed"));
5568 		}
5569 	} else {
5570 		(void) nxge_xif_init(nxgep);
5571 	}
5572 
5573 	if (nxge_no_msg == B_FALSE) {
5574 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
5575 	}
5576 
5577 	mac_link_update(nxgep->mach, LINK_STATE_UP);
5578 
5579 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
5580 }
5581 
5582 #ifdef NXGE_DEBUG
5583 /* Dump all TN1010 Status registers */
5584 static void
5585 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
5586 {
5587 	uint16_t val;
5588 
5589 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5590 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
5591 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
5592 
5593 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5594 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
5595 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
5596 
5597 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5598 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
5599 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
5600 
5601 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5602 	    TN1010_PCS_DEV_ADDR, 1, &val);
5603 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
5604 
5605 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5606 	    TN1010_PCS_DEV_ADDR, 8, &val);
5607 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
5608 
5609 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5610 	    TN1010_PCS_DEV_ADDR, 32, &val);
5611 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
5612 
5613 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5614 	    TN1010_PCS_DEV_ADDR, 33, &val);
5615 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
5616 
5617 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5618 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
5619 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
5620 
5621 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5622 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
5623 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
5624 
5625 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5626 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
5627 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
5628 
5629 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5630 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
5631 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
5632 
5633 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5634 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
5635 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
5636 
5637 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5638 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
5639 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
5640 
5641 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5642 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
5643 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
5644 
5645 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5646 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
5647 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
5648 
5649 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5650 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
5651 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
5652 
5653 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
5654 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
5655 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
5656 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
5657 }
5658 #endif
5659 
5660 /*
5661  * Calculate the bit in the multicast address filter
5662  * that selects the given * address.
5663  * Note: For GEM, the last 8-bits are used.
5664  */
5665 uint32_t
5666 crc32_mchash(p_ether_addr_t addr)
5667 {
5668 	uint8_t *cp;
5669 	uint32_t crc;
5670 	uint32_t c;
5671 	int byte;
5672 	int bit;
5673 
5674 	cp = (uint8_t *)addr;
5675 	crc = (uint32_t)0xffffffff;
5676 	for (byte = 0; byte < 6; byte++) {
5677 		c = (uint32_t)cp[byte];
5678 		for (bit = 0; bit < 8; bit++) {
5679 			if ((c & 0x1) ^ (crc & 0x1))
5680 				crc = (crc >> 1)^0xedb88320;
5681 			else
5682 				crc = (crc >> 1);
5683 			c >>= 1;
5684 		}
5685 	}
5686 	return ((~crc) >> (32 - HASH_BITS));
5687 }
5688 
5689 /* Reset serdes */
5690 
5691 nxge_status_t
5692 nxge_serdes_reset(p_nxge_t nxgep)
5693 {
5694 	npi_handle_t		handle;
5695 
5696 	handle = nxgep->npi_handle;
5697 
5698 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
5699 	drv_usecwait(500);
5700 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
5701 
5702 	return (NXGE_OK);
5703 }
5704 
5705 /*
5706  * This function monitors link status using interrupt or polling.
5707  * It calls nxgep->xcvr.check_link, a member function of
5708  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
5709  * function back, that is why the check_link routine is
5710  * executed periodically.
5711  */
5712 nxge_status_t
5713 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
5714 {
5715 	nxge_status_t status = NXGE_OK;
5716 
5717 	/* If we are a guest domain driver, don't bother. */
5718 	if (isLDOMguest(nxgep))
5719 		return (status);
5720 
5721 	/*
5722 	 * Return immediately if this is an imaginary XMAC port.
5723 	 * (At least, we don't have 4-port XMAC cards yet.)
5724 	 */
5725 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
5726 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
5727 	    (nxgep->mac.portnum > 1))
5728 		return (NXGE_OK);
5729 
5730 	if (nxgep->statsp == NULL) {
5731 		/* stats has not been allocated. */
5732 		return (NXGE_OK);
5733 	}
5734 	/* Don't check link if we're in internal loopback mode */
5735 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
5736 		return (NXGE_OK);
5737 
5738 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5739 	    "==> nxge_link_monitor port<%d> enable=%d",
5740 	    nxgep->mac.portnum, enable));
5741 	if (enable == LINK_MONITOR_START) {
5742 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
5743 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
5744 			    != NXGE_OK)
5745 				goto fail;
5746 		} else {
5747 			timeout_id_t timerid;
5748 			/*
5749 			 * check_link_stop means "Stop the link check", so
5750 			 * we return without starting the timer.
5751 			 */
5752 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
5753 				return (NXGE_OK);
5754 
5755 			/*
5756 			 * Otherwise fire the timer for the nxge to check
5757 			 * the link using the check_link function
5758 			 * of the nxge_xcvr_table and pass "nxgep" as the
5759 			 * argument to the check_link function.
5760 			 */
5761 			if (nxgep->xcvr.check_link) {
5762 				timerid = timeout(
5763 				    (fptrv_t)(nxgep->xcvr.check_link),
5764 				    nxgep,
5765 				    drv_usectohz(LINK_MONITOR_PERIOD));
5766 				MUTEX_ENTER(&nxgep->poll_lock);
5767 				nxgep->nxge_link_poll_timerid = timerid;
5768 				MUTEX_EXIT(&nxgep->poll_lock);
5769 				nxgep->link_check_count ++;
5770 			} else {
5771 				return (NXGE_ERROR);
5772 			}
5773 		}
5774 	} else {
5775 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
5776 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
5777 			    != NXGE_OK)
5778 				goto fail;
5779 		} else {
5780 			clock_t rv;
5781 
5782 			MUTEX_ENTER(&nxgep->poll_lock);
5783 
5784 			/* If <timerid> == 0, the link monitor has */
5785 			/* never been started, or just now stopped. */
5786 			if (nxgep->nxge_link_poll_timerid == 0) {
5787 				MUTEX_EXIT(&nxgep->poll_lock);
5788 				return (NXGE_OK);
5789 			}
5790 
5791 			nxgep->poll_state = LINK_MONITOR_STOPPING;
5792 			rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
5793 			    drv_usectohz(LM_WAIT_MULTIPLIER *
5794 			    LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
5795 			if (rv == -1) {
5796 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5797 				    "==> stopping port %d: "
5798 				    "cv_timedwait(%d) timed out",
5799 				    nxgep->mac.portnum, nxgep->poll_state));
5800 				nxgep->poll_state = LINK_MONITOR_STOP;
5801 				nxgep->nxge_link_poll_timerid = 0;
5802 			}
5803 
5804 			MUTEX_EXIT(&nxgep->poll_lock);
5805 		}
5806 	}
5807 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5808 	    "<== nxge_link_monitor port<%d> enable=%d",
5809 	    nxgep->mac.portnum, enable));
5810 
5811 	return (NXGE_OK);
5812 fail:
5813 	return (status);
5814 
5815 }
5816 
5817 nxge_status_t
5818 nxge_check_tn1010_link(p_nxge_t nxgep)
5819 {
5820 	nxge_status_t	status = NXGE_OK;
5821 	nxge_link_state_t link_up;
5822 
5823 	if (nxgep->nxge_magic != NXGE_MAGIC) {
5824 		/* magic is 0 if driver is not attached */
5825 		return (NXGE_ERROR);
5826 	}
5827 
5828 	/* Link has been stopped, no need to continue */
5829 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
5830 		return (NXGE_OK);
5831 	}
5832 
5833 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
5834 		goto nxge_check_tn1010_link_exit;
5835 
5836 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
5837 		goto fail;
5838 
5839 nxge_check_tn1010_link_exit:
5840 	if (link_up == LINK_IS_UP)
5841 		nxge_link_is_up(nxgep);
5842 	else if (link_up == LINK_IS_DOWN)
5843 		nxge_link_is_down(nxgep);
5844 
5845 	/*
5846 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
5847 	 * which could be THIS function.
5848 	 */
5849 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
5850 
5851 	return (NXGE_OK);
5852 
5853 fail:
5854 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
5855 
5856 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5857 	    "nxge_check_tn1010_link: Failed to check link"));
5858 	return (status);
5859 }
5860 
5861 
5862 /*
5863  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
5864  */
5865 static nxge_status_t
5866 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
5867 {
5868 	nxge_status_t	status = NXGE_OK;
5869 	p_nxge_stats_t	statsp;
5870 	uint8_t		phy_port_addr, portn;
5871 	uint16_t	val;
5872 
5873 	*link_up = LINK_NO_CHANGE;
5874 
5875 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5876 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
5877 	statsp = nxgep->statsp;
5878 
5879 	/* Check if link is up */
5880 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
5881 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
5882 	    != NXGE_OK) {
5883 		goto fail;
5884 	}
5885 	/*
5886 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
5887 	 * portmode and link_speed
5888 	 */
5889 	if (val & TN1010_AN_LINK_STAT_BIT) {
5890 		if ((nxgep->link_notify &&
5891 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5892 		    nxgep->statsp->mac_stats.link_up == 0) {
5893 			statsp->mac_stats.link_up = 1;
5894 			statsp->mac_stats.link_duplex = 2;
5895 			*link_up = LINK_IS_UP;
5896 			nxgep->link_notify = B_FALSE;
5897 		}
5898 	} else {
5899 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
5900 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
5901 		    nxgep->statsp->mac_stats.link_up == 1) {
5902 			statsp->mac_stats.link_up = 0;
5903 			statsp->mac_stats.link_speed = 0;
5904 			statsp->mac_stats.link_duplex = 0;
5905 			*link_up = LINK_IS_DOWN;
5906 			nxgep->link_notify = B_FALSE;
5907 		}
5908 	}
5909 	return (NXGE_OK);
5910 
5911 fail:
5912 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5913 	    "nxge_tn1010_check: Unable to check TN1010"));
5914 	return (status);
5915 }
5916 
5917 
5918 /* Set promiscous mode */
5919 
5920 nxge_status_t
5921 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
5922 {
5923 	nxge_status_t status = NXGE_OK;
5924 
5925 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
5926 
5927 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
5928 
5929 	RW_ENTER_WRITER(&nxgep->filter_lock);
5930 
5931 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
5932 		goto fail;
5933 	}
5934 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
5935 		goto fail;
5936 	}
5937 
5938 	RW_EXIT(&nxgep->filter_lock);
5939 
5940 	if (on)
5941 		nxgep->statsp->mac_stats.promisc = B_TRUE;
5942 	else
5943 		nxgep->statsp->mac_stats.promisc = B_FALSE;
5944 
5945 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
5946 
5947 	return (NXGE_OK);
5948 fail:
5949 	RW_EXIT(&nxgep->filter_lock);
5950 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
5951 	    "Unable to set promisc (%d)", on));
5952 
5953 	return (status);
5954 }
5955 
5956 /*ARGSUSED*/
5957 uint_t
5958 nxge_mif_intr(void *arg1, void *arg2)
5959 {
5960 #ifdef	NXGE_DEBUG
5961 	p_nxge_t		nxgep = (p_nxge_t)arg2;
5962 #endif
5963 #if NXGE_MIF
5964 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
5965 	uint32_t		status;
5966 	npi_handle_t		handle;
5967 	uint8_t			portn;
5968 	p_nxge_stats_t		statsp;
5969 #endif
5970 
5971 #ifdef	NXGE_MIF
5972 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
5973 		nxgep = ldvp->nxgep;
5974 	}
5975 	nxgep = ldvp->nxgep;
5976 #endif
5977 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
5978 
5979 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
5980 	return (DDI_INTR_CLAIMED);
5981 
5982 mif_intr_fail:
5983 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
5984 	return (DDI_INTR_UNCLAIMED);
5985 }
5986 
5987 /*ARGSUSED*/
5988 uint_t
5989 nxge_mac_intr(void *arg1, void *arg2)
5990 {
5991 	p_nxge_t		nxgep = (p_nxge_t)arg2;
5992 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
5993 	p_nxge_ldg_t		ldgp;
5994 	uint32_t		status;
5995 	npi_handle_t		handle;
5996 	uint8_t			portn;
5997 	p_nxge_stats_t		statsp;
5998 	npi_status_t		rs = NPI_SUCCESS;
5999 
6000 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
6001 		nxgep = ldvp->nxgep;
6002 	}
6003 
6004 	ldgp = ldvp->ldgp;
6005 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
6006 	    "group %d", ldgp->ldg));
6007 
6008 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
6009 	/*
6010 	 * This interrupt handler is for a specific
6011 	 * mac port.
6012 	 */
6013 	statsp = (p_nxge_stats_t)nxgep->statsp;
6014 	portn = nxgep->mac.portnum;
6015 
6016 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
6017 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
6018 
6019 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
6020 		rs = npi_xmac_tx_get_istatus(handle, portn,
6021 		    (xmac_tx_iconfig_t *)&status);
6022 		if (rs != NPI_SUCCESS)
6023 			goto npi_fail;
6024 		if (status & ICFG_XMAC_TX_ALL) {
6025 			if (status & ICFG_XMAC_TX_UNDERRUN) {
6026 				statsp->xmac_stats.tx_underflow_err++;
6027 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6028 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
6029 			}
6030 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
6031 				statsp->xmac_stats.tx_maxpktsize_err++;
6032 				/*
6033 				 * Do not send FMA ereport because this
6034 				 * error does not indicate HW failure.
6035 				 */
6036 			}
6037 			if (status & ICFG_XMAC_TX_OVERFLOW) {
6038 				statsp->xmac_stats.tx_overflow_err++;
6039 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6040 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
6041 			}
6042 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
6043 				statsp->xmac_stats.tx_fifo_xfr_err++;
6044 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6045 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
6046 			}
6047 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
6048 				statsp->xmac_stats.tx_byte_cnt +=
6049 				    XTXMAC_BYTE_CNT_MASK;
6050 			}
6051 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
6052 				statsp->xmac_stats.tx_frame_cnt +=
6053 				    XTXMAC_FRM_CNT_MASK;
6054 			}
6055 		}
6056 
6057 		rs = npi_xmac_rx_get_istatus(handle, portn,
6058 		    (xmac_rx_iconfig_t *)&status);
6059 		if (rs != NPI_SUCCESS)
6060 			goto npi_fail;
6061 		if (status & ICFG_XMAC_RX_ALL) {
6062 			if (status & ICFG_XMAC_RX_OVERFLOW)
6063 				statsp->xmac_stats.rx_overflow_err++;
6064 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
6065 				statsp->xmac_stats.rx_underflow_err++;
6066 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6067 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
6068 			}
6069 			/*
6070 			 * Do not send FMA ereport for the following 3 errors
6071 			 * because they do not indicate HW failures.
6072 			 */
6073 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
6074 				statsp->xmac_stats.rx_crc_err_cnt +=
6075 				    XRXMAC_CRC_ER_CNT_MASK;
6076 			}
6077 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
6078 				statsp->xmac_stats.rx_len_err_cnt +=
6079 				    MAC_LEN_ER_CNT_MASK;
6080 			}
6081 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
6082 				statsp->xmac_stats.rx_viol_err_cnt +=
6083 				    XRXMAC_CD_VIO_CNT_MASK;
6084 			}
6085 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
6086 				statsp->xmac_stats.rx_byte_cnt +=
6087 				    XRXMAC_BT_CNT_MASK;
6088 			}
6089 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
6090 				statsp->xmac_stats.rx_hist1_cnt +=
6091 				    XRXMAC_HIST_CNT1_MASK;
6092 			}
6093 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
6094 				statsp->xmac_stats.rx_hist2_cnt +=
6095 				    XRXMAC_HIST_CNT2_MASK;
6096 			}
6097 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
6098 				statsp->xmac_stats.rx_hist3_cnt +=
6099 				    XRXMAC_HIST_CNT3_MASK;
6100 			}
6101 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
6102 				statsp->xmac_stats.rx_hist4_cnt +=
6103 				    XRXMAC_HIST_CNT4_MASK;
6104 			}
6105 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
6106 				statsp->xmac_stats.rx_hist5_cnt +=
6107 				    XRXMAC_HIST_CNT5_MASK;
6108 			}
6109 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
6110 				statsp->xmac_stats.rx_hist6_cnt +=
6111 				    XRXMAC_HIST_CNT6_MASK;
6112 			}
6113 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
6114 				statsp->xmac_stats.rx_broadcast_cnt +=
6115 				    XRXMAC_BC_FRM_CNT_MASK;
6116 			}
6117 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
6118 				statsp->xmac_stats.rx_mult_cnt +=
6119 				    XRXMAC_MC_FRM_CNT_MASK;
6120 			}
6121 			/*
6122 			 * Do not send FMA ereport for the following 3 errors
6123 			 * because they do not indicate HW failures.
6124 			 */
6125 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
6126 				statsp->xmac_stats.rx_frag_cnt +=
6127 				    XRXMAC_FRAG_CNT_MASK;
6128 			}
6129 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
6130 				statsp->xmac_stats.rx_frame_align_err_cnt +=
6131 				    XRXMAC_AL_ER_CNT_MASK;
6132 			}
6133 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
6134 				statsp->xmac_stats.rx_linkfault_err_cnt +=
6135 				    XMAC_LINK_FLT_CNT_MASK;
6136 			}
6137 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
6138 				statsp->xmac_stats.rx_remotefault_err++;
6139 			}
6140 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
6141 				statsp->xmac_stats.rx_localfault_err++;
6142 			}
6143 		}
6144 
6145 		rs = npi_xmac_ctl_get_istatus(handle, portn,
6146 		    (xmac_ctl_iconfig_t *)&status);
6147 		if (rs != NPI_SUCCESS)
6148 			goto npi_fail;
6149 		if (status & ICFG_XMAC_CTRL_ALL) {
6150 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
6151 				statsp->xmac_stats.rx_pause_cnt++;
6152 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
6153 				statsp->xmac_stats.tx_pause_state++;
6154 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
6155 				statsp->xmac_stats.tx_nopause_state++;
6156 		}
6157 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
6158 		rs = npi_bmac_tx_get_istatus(handle, portn,
6159 		    (bmac_tx_iconfig_t *)&status);
6160 		if (rs != NPI_SUCCESS)
6161 			goto npi_fail;
6162 		if (status & ICFG_BMAC_TX_ALL) {
6163 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
6164 				statsp->bmac_stats.tx_underrun_err++;
6165 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6166 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
6167 			}
6168 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
6169 				statsp->bmac_stats.tx_max_pkt_err++;
6170 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6171 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
6172 			}
6173 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
6174 				statsp->bmac_stats.tx_byte_cnt +=
6175 				    BTXMAC_BYTE_CNT_MASK;
6176 			}
6177 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
6178 				statsp->bmac_stats.tx_frame_cnt +=
6179 				    BTXMAC_FRM_CNT_MASK;
6180 			}
6181 		}
6182 
6183 		rs = npi_bmac_rx_get_istatus(handle, portn,
6184 		    (bmac_rx_iconfig_t *)&status);
6185 		if (rs != NPI_SUCCESS)
6186 			goto npi_fail;
6187 		if (status & ICFG_BMAC_RX_ALL) {
6188 			if (status & ICFG_BMAC_RX_OVERFLOW) {
6189 				statsp->bmac_stats.rx_overflow_err++;
6190 			}
6191 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
6192 				statsp->bmac_stats.rx_frame_cnt +=
6193 				    RXMAC_FRM_CNT_MASK;
6194 			}
6195 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
6196 				statsp->bmac_stats.rx_crc_err_cnt +=
6197 				    BMAC_CRC_ER_CNT_MASK;
6198 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6199 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
6200 			}
6201 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
6202 				statsp->bmac_stats.rx_len_err_cnt +=
6203 				    MAC_LEN_ER_CNT_MASK;
6204 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6205 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
6206 			}
6207 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
6208 				statsp->bmac_stats.rx_viol_err_cnt +=
6209 				    BMAC_CD_VIO_CNT_MASK;
6210 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6211 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
6212 			}
6213 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
6214 				statsp->bmac_stats.rx_byte_cnt +=
6215 				    BRXMAC_BYTE_CNT_MASK;
6216 			}
6217 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
6218 				statsp->bmac_stats.rx_align_err_cnt +=
6219 				    BMAC_AL_ER_CNT_MASK;
6220 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
6221 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
6222 			}
6223 
6224 			rs = npi_bmac_ctl_get_istatus(handle, portn,
6225 			    (bmac_ctl_iconfig_t *)&status);
6226 			if (rs != NPI_SUCCESS)
6227 				goto npi_fail;
6228 
6229 			if (status & ICFG_BMAC_CTL_ALL) {
6230 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
6231 					statsp->bmac_stats.rx_pause_cnt++;
6232 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
6233 					statsp->bmac_stats.tx_pause_state++;
6234 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
6235 					statsp->bmac_stats.tx_nopause_state++;
6236 			}
6237 		}
6238 
6239 	if (ldgp->nldvs == 1) {
6240 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
6241 		    B_TRUE, ldgp->ldg_timer);
6242 	}
6243 
6244 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
6245 	return (DDI_INTR_CLAIMED);
6246 
6247 npi_fail:
6248 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
6249 	return (DDI_INTR_UNCLAIMED);
6250 }
6251 
6252 nxge_status_t
6253 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
6254 {
6255 	uint8_t		phy_port_addr;
6256 	nxge_status_t	status = NXGE_OK;
6257 	boolean_t	rx_sig_ok;
6258 	boolean_t	pcs_blk_lock;
6259 	boolean_t	link_align;
6260 	uint16_t	val1, val2, val3;
6261 #ifdef	NXGE_DEBUG_SYMBOL_ERR
6262 	uint16_t	val_debug;
6263 	uint32_t	val;
6264 #endif
6265 
6266 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
6267 
6268 #ifdef	NXGE_DEBUG_SYMBOL_ERR
6269 	/* Check Device 3 Register Device 3 0xC809 */
6270 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
6271 	if ((val_debug & ~0x200) != 0) {
6272 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
6273 		    nxgep->mac.portnum, val_debug);
6274 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
6275 		    &val_debug);
6276 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
6277 		    nxgep->mac.portnum, val_debug);
6278 	}
6279 
6280 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6281 	    XPCS_REG_DESCWERR_COUNTER, &val);
6282 	if (val != 0)
6283 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
6284 
6285 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6286 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
6287 	if (val != 0)
6288 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
6289 
6290 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6291 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
6292 	if (val != 0)
6293 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
6294 #endif
6295 
6296 	/* Check from BCM8704 if 10G link is up or down */
6297 
6298 	/* Check Device 1 Register 0xA bit0 */
6299 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
6300 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
6301 	if (status != NXGE_OK)
6302 		goto fail;
6303 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
6304 
6305 	/* Check Device 3 Register 0x20 bit0 */
6306 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
6307 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
6308 		goto fail;
6309 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
6310 
6311 	/* Check Device 4 Register 0x18 bit12 */
6312 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
6313 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
6314 	if (status != NXGE_OK)
6315 		goto fail;
6316 
6317 	switch (nxgep->chip_id) {
6318 	case BCM8704_CHIP_ID:
6319 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
6320 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
6321 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
6322 		break;
6323 	case BCM8706_CHIP_ID:
6324 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
6325 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
6326 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
6327 		    B_TRUE : B_FALSE;
6328 		break;
6329 	default:
6330 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
6331 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
6332 		goto fail;
6333 	}
6334 
6335 #ifdef	NXGE_DEBUG_ALIGN_ERR
6336 	/* Temp workaround for link down issue */
6337 	if (pcs_blk_lock == B_FALSE) {
6338 		if (val2 != 0x4) {
6339 			pcs_blk_lock = B_TRUE;
6340 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
6341 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
6342 		}
6343 	}
6344 
6345 	if (link_align == B_FALSE) {
6346 		if (val3 != 0x140f) {
6347 			link_align = B_TRUE;
6348 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
6349 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
6350 		}
6351 	}
6352 
6353 	if (rx_sig_ok == B_FALSE) {
6354 		if ((val2 == 0) || (val3 == 0)) {
6355 			rx_sig_ok = B_TRUE;
6356 			cmn_err(CE_NOTE,
6357 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
6358 			    nxgep->mac.portnum);
6359 		}
6360 	}
6361 #endif
6362 
6363 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
6364 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
6365 
6366 	return (NXGE_OK);
6367 fail:
6368 	return (status);
6369 }
6370 
6371 static nxge_status_t
6372 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
6373 {
6374 	uint8_t		phy;
6375 	nxge_status_t   status = NXGE_OK;
6376 	boolean_t	pma_status;
6377 	boolean_t	pcs_status;
6378 	boolean_t	xgxs_status;
6379 	uint16_t	val;
6380 
6381 	phy = nxgep->statsp->mac_stats.xcvr_portn;
6382 
6383 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
6384 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
6385 
6386 	*link_up = B_FALSE;
6387 
6388 	/* Check from Marvell 88X2011 if 10G link is up or down */
6389 
6390 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
6391 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
6392 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
6393 
6394 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6395 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
6396 
6397 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
6398 
6399 	/* Check PMC Register : 3.0001.2 == 1: read twice */
6400 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
6401 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
6402 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
6403 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
6404 
6405 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6406 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
6407 
6408 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
6409 
6410 	/* Check XGXS Register : 4.0018.[0-3,12] */
6411 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
6412 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
6413 
6414 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6415 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
6416 
6417 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
6418 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
6419 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
6420 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
6421 
6422 	*link_up = (pma_status && pcs_status && xgxs_status) ?
6423 	    B_TRUE : B_FALSE;
6424 
6425 fail:
6426 
6427 	if (*link_up == B_FALSE) {
6428 		/* PCS OFF */
6429 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
6430 	} else {
6431 		/* PCS Activity */
6432 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
6433 	}
6434 
6435 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6436 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
6437 
6438 	return (status);
6439 }
6440 
6441 nxge_status_t
6442 nxge_10g_link_led_on(p_nxge_t nxgep)
6443 {
6444 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
6445 	    != NPI_SUCCESS)
6446 		return (NXGE_ERROR);
6447 	else
6448 		return (NXGE_OK);
6449 }
6450 
6451 nxge_status_t
6452 nxge_10g_link_led_off(p_nxge_t nxgep)
6453 {
6454 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
6455 	    != NPI_SUCCESS)
6456 		return (NXGE_ERROR);
6457 	else
6458 		return (NXGE_OK);
6459 }
6460 
6461 static boolean_t
6462 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
6463 {
6464 	uint32_t pma_pmd_id = 0;
6465 	uint32_t pcs_id = 0;
6466 	uint32_t phy_id = 0;
6467 
6468 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
6469 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6470 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
6471 	if ((pma_pmd_id & mask) == (id & mask))
6472 		goto found_phy;
6473 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
6474 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6475 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
6476 	if ((pcs_id & mask) == (id & mask))
6477 		goto found_phy;
6478 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
6479 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6480 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
6481 	if ((phy_id & mask) == (id & mask))
6482 		goto found_phy;
6483 
6484 	return (B_FALSE);
6485 
6486 found_phy:
6487 	return (B_TRUE);
6488 }
6489 
6490 /* Check if the given id read using the given MDIO Clause is supported */
6491 
6492 static boolean_t
6493 nxge_is_supported_phy(uint32_t id, uint8_t type)
6494 {
6495 	int		i;
6496 	boolean_t	found = B_FALSE;
6497 
6498 	switch (type) {
6499 	case CLAUSE_45_TYPE:
6500 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
6501 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
6502 			    (id & BCM_PHY_ID_MASK)) ||
6503 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
6504 				found = B_TRUE;
6505 				break;
6506 			}
6507 		}
6508 		break;
6509 	case CLAUSE_22_TYPE:
6510 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
6511 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
6512 			    (id & BCM_PHY_ID_MASK)) {
6513 				found = B_TRUE;
6514 				break;
6515 			}
6516 		}
6517 		break;
6518 	default:
6519 		break;
6520 	}
6521 
6522 	return (found);
6523 }
6524 
6525 static uint32_t
6526 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
6527 {
6528 	uint16_t	val1 = 0;
6529 	uint16_t	val2 = 0;
6530 	uint32_t	pma_pmd_dev_id = 0;
6531 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
6532 
6533 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
6534 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
6535 	    NXGE_DEV_ID_REG_1, &val1);
6536 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
6537 	    NXGE_DEV_ID_REG_2, &val2);
6538 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
6539 
6540 	/* Concatenate the Device ID stored in two registers. */
6541 	pma_pmd_dev_id = val1;
6542 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
6543 	pma_pmd_dev_id |= val2;
6544 
6545 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
6546 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
6547 
6548 	return (pma_pmd_dev_id);
6549 }
6550 
6551 static uint32_t
6552 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
6553 {
6554 	uint16_t	val1 = 0;
6555 	uint16_t	val2 = 0;
6556 	uint32_t	pcs_dev_id = 0;
6557 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
6558 
6559 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
6560 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
6561 	    NXGE_DEV_ID_REG_1, &val1);
6562 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
6563 	    NXGE_DEV_ID_REG_2, &val2);
6564 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
6565 
6566 	pcs_dev_id = val1;
6567 	pcs_dev_id = (pcs_dev_id << 16);
6568 	pcs_dev_id |= val2;
6569 
6570 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
6571 	    "devid[0x%llx]", phy_port, pcs_dev_id));
6572 
6573 	return (pcs_dev_id);
6574 }
6575 
6576 static uint32_t
6577 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
6578 {
6579 	uint16_t	val1 = 0;
6580 	uint16_t	val2 = 0;
6581 	uint32_t	phy_id = 0;
6582 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
6583 	npi_status_t	npi_status = NPI_SUCCESS;
6584 
6585 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
6586 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
6587 	    &val1);
6588 	if (npi_status != NPI_SUCCESS) {
6589 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
6590 		    "clause 22 read to reg 2 failed!!!"));
6591 		goto exit;
6592 	}
6593 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
6594 	    &val2);
6595 	if (npi_status != 0) {
6596 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
6597 		    "clause 22 read to reg 3 failed!!!"));
6598 		goto exit;
6599 	}
6600 	phy_id = val1;
6601 	phy_id = (phy_id << 16);
6602 	phy_id |= val2;
6603 
6604 exit:
6605 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
6606 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
6607 	    phy_port, phy_id));
6608 
6609 	return (phy_id);
6610 }
6611 
6612 /*
6613  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
6614  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
6615  * read. Then use the values obtained to determine the phy type of each port
6616  * and the Neptune type.
6617  *
6618  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
6619  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
6620  * in case the portmode information is not available via OBP, nxge.conf,
6621  * VPD or SEEPROM.
6622  */
6623 nxge_status_t
6624 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
6625 {
6626 	int		i, j, l;
6627 	uint32_t	pma_pmd_dev_id = 0;
6628 	uint32_t	pcs_dev_id = 0;
6629 	uint32_t	phy_id = 0;
6630 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
6631 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
6632 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
6633 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
6634 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
6635 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
6636 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
6637 	uint8_t		total_port_fd, total_phy_fd;
6638 	uint8_t		num_xaui;
6639 	nxge_status_t	status = NXGE_OK;
6640 
6641 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
6642 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6643 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
6644 	    nxgep->niu_type));
6645 
6646 	if (isLDOMguest(nxgep)) {
6647 		hw_p->niu_type = NIU_TYPE_NONE;
6648 		hw_p->platform_type = P_NEPTUNE_NONE;
6649 		return (NXGE_OK);
6650 	}
6651 
6652 	j = l = 0;
6653 	total_port_fd = total_phy_fd = 0;
6654 	/*
6655 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
6656 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
6657 	 */
6658 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
6659 
6660 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
6661 
6662 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
6663 			pma_pmd_dev_fd[i] = 1;
6664 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
6665 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
6666 			if (j < NXGE_PORTS_NEPTUNE) {
6667 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
6668 				    == TN1010_DEV_ID) {
6669 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
6670 				} else {
6671 					port_pma_pmd_dev_id[j] =
6672 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
6673 				}
6674 				port_fd_arr[j] = (uint8_t)i;
6675 				j++;
6676 			}
6677 		} else {
6678 			pma_pmd_dev_fd[i] = 0;
6679 		}
6680 
6681 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
6682 
6683 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
6684 			pcs_dev_fd[i] = 1;
6685 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
6686 			    "dev %x found", i, pcs_dev_id));
6687 			if (pma_pmd_dev_fd[i] == 1) {
6688 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
6689 				    == TN1010_DEV_ID) {
6690 					port_pcs_dev_id[j - 1] =
6691 					    TN1010_DEV_ID;
6692 				} else {
6693 					port_pcs_dev_id[j - 1] =
6694 					    pcs_dev_id &
6695 					    BCM_PHY_ID_MASK;
6696 				}
6697 			} else {
6698 				if (j < NXGE_PORTS_NEPTUNE) {
6699 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
6700 					    == TN1010_DEV_ID) {
6701 						port_pcs_dev_id[j] =
6702 						    TN1010_DEV_ID;
6703 					} else {
6704 						port_pcs_dev_id[j] =
6705 						    pcs_dev_id &
6706 						    BCM_PHY_ID_MASK;
6707 					}
6708 					port_fd_arr[j] = (uint8_t)i;
6709 					j++;
6710 				}
6711 			}
6712 		} else {
6713 			pcs_dev_fd[i] = 0;
6714 		}
6715 
6716 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
6717 			total_port_fd ++;
6718 		}
6719 
6720 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
6721 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
6722 			total_phy_fd ++;
6723 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
6724 			    "%x found", i, phy_id));
6725 			if (l < NXGE_PORTS_NEPTUNE) {
6726 				if ((phy_id & TN1010_DEV_ID_MASK)
6727 				    == TN1010_DEV_ID) {
6728 					port_phy_id[l] = TN1010_DEV_ID;
6729 				} else {
6730 					port_phy_id[l]
6731 					    = phy_id & BCM_PHY_ID_MASK;
6732 				}
6733 				phy_fd_arr[l] = (uint8_t)i;
6734 				l++;
6735 			}
6736 		}
6737 	}
6738 
6739 	switch (total_port_fd) {
6740 	case 2:
6741 		switch (total_phy_fd) {
6742 		case 2:
6743 			/* 2 10G, 2 1G RGMII Fiber / copper */
6744 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
6745 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
6746 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
6747 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
6748 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
6749 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
6750 
6751 				switch (hw_p->platform_type) {
6752 				case P_NEPTUNE_ROCK:
6753 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
6754 					/*
6755 					 * ROCK platform has assigned a lower
6756 					 * addr to port 1. (port 0 = 0x9 and
6757 					 * port 1 = 0x8).
6758 					 */
6759 					hw_p->xcvr_addr[1] = port_fd_arr[0];
6760 					hw_p->xcvr_addr[0] = port_fd_arr[1];
6761 
6762 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6763 					    "Rock with 2 10G, 2 1GC"));
6764 					break;
6765 
6766 				case P_NEPTUNE_NONE:
6767 				default:
6768 					hw_p->platform_type =
6769 					    P_NEPTUNE_GENERIC;
6770 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
6771 
6772 					hw_p->xcvr_addr[0] = port_fd_arr[0];
6773 					hw_p->xcvr_addr[1] = port_fd_arr[1];
6774 
6775 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6776 					    "ARTM card with 2 10G, 2 1GF"));
6777 					break;
6778 				}
6779 
6780 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
6781 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
6782 
6783 			} else {
6784 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6785 				    "Unsupported neptune type 1"));
6786 				goto error_exit;
6787 			}
6788 			break;
6789 
6790 		case 1:
6791 			/* TODO - 2 10G, 1 1G */
6792 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6793 			    "Unsupported neptune type 2 10G, 1 1G"));
6794 			goto error_exit;
6795 		case 0:
6796 			/*
6797 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
6798 			 * cards, etc.
6799 			 */
6800 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
6801 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
6802 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
6803 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
6804 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
6805 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
6806 			    ((port_pma_pmd_dev_id[0] ==
6807 			    MARVELL_88X201X_PHY_ID) &&
6808 			    (port_pma_pmd_dev_id[1] ==
6809 			    MARVELL_88X201X_PHY_ID))) {
6810 
6811 				/*
6812 				 * Check the first phy port address against
6813 				 * the known phy start addresses to determine
6814 				 * the platform type.
6815 				 */
6816 
6817 				switch (port_fd_arr[0]) {
6818 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
6819 					/*
6820 					 * The Marvell case also falls into
6821 					 * this case as
6822 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
6823 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
6824 					 * This is OK for the 2 10G case.
6825 					 */
6826 					hw_p->niu_type = NEPTUNE_2_10GF;
6827 					hw_p->platform_type =
6828 					    P_NEPTUNE_ATLAS_2PORT;
6829 					break;
6830 				case GOA_CLAUSE45_PORT_ADDR_BASE:
6831 					if (hw_p->platform_type !=
6832 					    P_NEPTUNE_NIU) {
6833 						hw_p->platform_type =
6834 						    P_NEPTUNE_GENERIC;
6835 						hw_p->niu_type =
6836 						    NEPTUNE_2_10GF;
6837 					}
6838 					break;
6839 				default:
6840 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6841 					    "Unsupported neptune type 2 - 1"));
6842 					goto error_exit;
6843 				}
6844 
6845 				for (i = 0; i < 2; i++) {
6846 					hw_p->xcvr_addr[i] = port_fd_arr[i];
6847 				}
6848 
6849 			/* Both XAUI slots have copper XAUI cards */
6850 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
6851 			    == TN1010_DEV_ID) &&
6852 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
6853 			    == TN1010_DEV_ID)) ||
6854 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
6855 			    == TN1010_DEV_ID) &&
6856 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
6857 			    == TN1010_DEV_ID))) {
6858 				hw_p->niu_type = NEPTUNE_2_TN1010;
6859 				hw_p->xcvr_addr[0] = port_fd_arr[0];
6860 				hw_p->xcvr_addr[1] = port_fd_arr[1];
6861 
6862 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
6863 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
6864 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
6865 			    == TN1010_DEV_ID) ||
6866 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
6867 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
6868 			    TN1010_DEV_ID)) {
6869 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
6870 				hw_p->xcvr_addr[0] = port_fd_arr[0];
6871 				hw_p->xcvr_addr[1] = port_fd_arr[1];
6872 
6873 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
6874 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
6875 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
6876 			    == TN1010_DEV_ID) ||
6877 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
6878 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
6879 			    == TN1010_DEV_ID)) {
6880 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
6881 				hw_p->xcvr_addr[0] = port_fd_arr[0];
6882 				hw_p->xcvr_addr[1] = port_fd_arr[1];
6883 
6884 			} else {
6885 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6886 				    "Unsupported neptune type 2"));
6887 				goto error_exit;
6888 			}
6889 			break;
6890 
6891 		case 4:
6892 			if (nxge_get_num_of_xaui(
6893 			    port_pma_pmd_dev_id, port_pcs_dev_id,
6894 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
6895 				goto error_exit;
6896 			}
6897 			if (num_xaui != 2)
6898 				goto error_exit;
6899 
6900 			/*
6901 			 *  Maramba with 2 XAUIs (either fiber or copper)
6902 			 *
6903 			 * Check the first phy port address against
6904 			 * the known phy start addresses to determine
6905 			 * the platform type.
6906 			 */
6907 			switch (phy_fd_arr[0]) {
6908 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
6909 				hw_p->platform_type =
6910 				    P_NEPTUNE_MARAMBA_P0;
6911 				break;
6912 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
6913 				hw_p->platform_type =
6914 				    P_NEPTUNE_MARAMBA_P1;
6915 				break;
6916 			default:
6917 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6918 				    "Unknown port %d...Cannot "
6919 				    "determine platform type", i));
6920 				goto error_exit;
6921 			}
6922 
6923 			hw_p->xcvr_addr[0] = port_fd_arr[0];
6924 			hw_p->xcvr_addr[1] = port_fd_arr[1];
6925 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
6926 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
6927 
6928 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
6929 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
6930 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
6931 			    == TN1010_DEV_ID) {
6932 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
6933 
6934 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
6935 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
6936 			    == TN1010_DEV_ID) &&
6937 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
6938 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
6939 
6940 			/* Both slots have fiber XAUI */
6941 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
6942 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
6943 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
6944 
6945 			/* Both slots have copper XAUI */
6946 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
6947 			    == TN1010_DEV_ID) &&
6948 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
6949 			    == TN1010_DEV_ID) {
6950 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
6951 
6952 			} else {
6953 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6954 				    "Unsupported neptune type 3"));
6955 				goto error_exit;
6956 			}
6957 			break;
6958 		default:
6959 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6960 			    "Unsupported neptune type 5"));
6961 			goto error_exit;
6962 		}
6963 		break;
6964 	case 1: 	/* Only one clause45 port */
6965 		switch (total_phy_fd) {	/* Number of clause22 ports */
6966 		case 3:
6967 			/*
6968 			 * TODO 3 1G, 1 10G mode.
6969 			 * Differentiate between 1_1G_1_10G_2_1G and
6970 			 * 1_10G_3_1G
6971 			 */
6972 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6973 			    "Unsupported neptune type 7"));
6974 			goto error_exit;
6975 		case 2:
6976 			/*
6977 			 * TODO 2 1G, 1 10G mode.
6978 			 * Differentiate between 1_1G_1_10G_1_1G and
6979 			 * 1_10G_2_1G
6980 			 */
6981 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6982 			    "Unsupported neptune type 8"));
6983 			goto error_exit;
6984 		case 1:
6985 			/*
6986 			 * TODO 1 1G, 1 10G mode.
6987 			 * Differentiate between 1_1G_1_10G and
6988 			 * 1_10G_1_1G
6989 			 */
6990 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6991 			    "Unsupported neptune type 9"));
6992 			goto error_exit;
6993 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
6994 			/* Fiber XAUI */
6995 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
6996 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
6997 
6998 				/*
6999 				 * Check the first phy port address against
7000 				 * the known phy start addresses to determine
7001 				 * the platform type.
7002 				 */
7003 
7004 				switch (port_fd_arr[0]) {
7005 				case N2_CLAUSE45_PORT_ADDR_BASE:
7006 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
7007 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
7008 					/*
7009 					 * If hw_p->platform_type ==
7010 					 * P_NEPTUNE_NIU, then portmode
7011 					 * is already known, so there is
7012 					 * no need to figure out hw_p->
7013 					 * platform_type because
7014 					 * platform_type is only for
7015 					 * figuring out portmode.
7016 					 */
7017 					if (hw_p->platform_type !=
7018 					    P_NEPTUNE_NIU) {
7019 						hw_p->platform_type =
7020 						    P_NEPTUNE_GENERIC;
7021 						hw_p->niu_type =
7022 						    NEPTUNE_2_10GF;
7023 					}
7024 					break;
7025 				default:
7026 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7027 					    "Unsupported neptune type 10"));
7028 					goto error_exit;
7029 				}
7030 				/*
7031 				 * For GOA, which is a hot swappable PHY, the
7032 				 * phy address to function number mapping
7033 				 * should be preserved, i.e., addr 16 is
7034 				 * assigned to function 0 and 20 to function 1
7035 				 * But for Huron XAUI, the assignment should
7036 				 * be by function number, i.e., whichever
7037 				 * function number attaches should be
7038 				 * assigned the available PHY (this is required
7039 				 * primarily to support pre-production Huron
7040 				 * boards where function 0 is mapped to addr 17
7041 				 */
7042 				if (port_fd_arr[0] ==
7043 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
7044 					hw_p->xcvr_addr[1] = port_fd_arr[0];
7045 				} else {
7046 					hw_p->xcvr_addr[nxgep->function_num] =
7047 					    port_fd_arr[0];
7048 				}
7049 
7050 			/* A 10G copper XAUI in either slot0 or slot1 */
7051 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
7052 			    == TN1010_DEV_ID ||
7053 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
7054 			    == TN1010_DEV_ID) {
7055 				switch (port_fd_arr[0]) {
7056 				/* The XAUI is in slot0 */
7057 				case N2_CLAUSE45_PORT_ADDR_BASE:
7058 					hw_p->niu_type = NEPTUNE_1_TN1010;
7059 					break;
7060 
7061 				/* The XAUI is in slot1 */
7062 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
7063 					hw_p->niu_type
7064 					    = NEPTUNE_1_NONE_1_TN1010;
7065 					break;
7066 				default:
7067 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7068 					    "Unsupported XAUI port address"));
7069 					goto error_exit;
7070 				}
7071 				hw_p->xcvr_addr[nxgep->function_num]
7072 				    = port_fd_arr[0];
7073 
7074 			} else {
7075 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7076 				    "Unsupported PHY type"));
7077 				goto error_exit;
7078 			}
7079 			break;
7080 		case 4: /* Maramba always have 4 clause 45 ports */
7081 
7082 			/* Maramba with 1 XAUI */
7083 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
7084 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
7085 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
7086 			    != TN1010_DEV_ID) &&
7087 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
7088 			    != TN1010_DEV_ID)) {
7089 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7090 				    "Unsupported neptune type 12"));
7091 				goto error_exit;
7092 			}
7093 
7094 			/*
7095 			 * Check the first phy port address against
7096 			 * the known phy start addresses to determine
7097 			 * the platform type.
7098 			 */
7099 			switch (phy_fd_arr[0]) {
7100 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
7101 				hw_p->platform_type =
7102 				    P_NEPTUNE_MARAMBA_P0;
7103 				break;
7104 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
7105 				hw_p->platform_type =
7106 				    P_NEPTUNE_MARAMBA_P1;
7107 				break;
7108 			default:
7109 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7110 				    "Unknown port %d...Cannot "
7111 				    "determine platform type 10 - 2",
7112 				    i));
7113 				goto error_exit;
7114 			}
7115 
7116 			/*
7117 			 * Check the clause45 address to determine
7118 			 * if XAUI is in port 0 or port 1.
7119 			 */
7120 			switch (port_fd_arr[0]) {
7121 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
7122 				if (port_pcs_dev_id[0]
7123 				    == PHY_BCM8704_FAMILY ||
7124 				    port_pma_pmd_dev_id[0]
7125 				    == PHY_BCM8704_FAMILY) {
7126 					hw_p->niu_type
7127 					    = NEPTUNE_1_10GF_3_1GC;
7128 				} else {
7129 					hw_p->niu_type
7130 					    = NEPTUNE_1_TN1010_3_1GC;
7131 				}
7132 				hw_p->xcvr_addr[0] = port_fd_arr[0];
7133 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
7134 					hw_p->xcvr_addr[i] =
7135 					    phy_fd_arr[i];
7136 				}
7137 				break;
7138 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
7139 				if (port_pcs_dev_id[0]
7140 				    == PHY_BCM8704_FAMILY ||
7141 				    port_pma_pmd_dev_id[0]
7142 				    == PHY_BCM8704_FAMILY) {
7143 					hw_p->niu_type =
7144 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
7145 				} else {
7146 					hw_p->niu_type =
7147 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
7148 				}
7149 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
7150 				hw_p->xcvr_addr[1] = port_fd_arr[0];
7151 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
7152 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
7153 				break;
7154 			default:
7155 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7156 				    "Unsupported neptune type 11"));
7157 				goto error_exit;
7158 			}
7159 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7160 			    "Maramba with 1 XAUI (fiber or copper)"));
7161 			break;
7162 		default:
7163 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7164 			    "Unsupported neptune type 13"));
7165 			goto error_exit;
7166 		}
7167 		break;
7168 	case 0: /* 4 ports Neptune based NIC */
7169 		switch (total_phy_fd) {
7170 		case 4:
7171 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
7172 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
7173 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
7174 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
7175 
7176 				/*
7177 				 * Check the first phy port address against
7178 				 * the known phy start addresses to determine
7179 				 * the platform type.
7180 				 */
7181 				switch (phy_fd_arr[0]) {
7182 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
7183 					hw_p->platform_type =
7184 					    P_NEPTUNE_MARAMBA_P1;
7185 					break;
7186 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
7187 					hw_p->platform_type =
7188 					    P_NEPTUNE_ATLAS_4PORT;
7189 					break;
7190 				default:
7191 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7192 					    "Unknown port %d...Cannot "
7193 					    "determine platform type", i));
7194 					goto error_exit;
7195 				}
7196 				hw_p->niu_type = NEPTUNE_4_1GC;
7197 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
7198 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
7199 				}
7200 			} else {
7201 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7202 				    "Unsupported neptune type 14"));
7203 				goto error_exit;
7204 			}
7205 			break;
7206 		case 3:
7207 			/* TODO 3 1G mode */
7208 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7209 			    "Unsupported neptune type 15"));
7210 			goto error_exit;
7211 		case 2:
7212 			/* TODO 2 1G mode */
7213 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
7214 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
7215 				hw_p->platform_type = P_NEPTUNE_GENERIC;
7216 				hw_p->niu_type = NEPTUNE_2_1GRF;
7217 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
7218 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
7219 			} else {
7220 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7221 				    "Unsupported neptune type 16"));
7222 				goto error_exit;
7223 			}
7224 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7225 			    "2 RGMII Fiber ports - RTM"));
7226 			break;
7227 
7228 		case 1:
7229 			/* TODO 1 1G mode */
7230 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7231 			    "Unsupported neptune type 17"));
7232 			goto error_exit;
7233 		default:
7234 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7235 			    "Unsupported neptune type 18, total phy fd %d",
7236 			    total_phy_fd));
7237 			goto error_exit;
7238 		}
7239 		break;
7240 	default:
7241 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7242 		    "Unsupported neptune type 19"));
7243 		goto error_exit;
7244 	}
7245 
7246 scan_exit:
7247 
7248 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
7249 	    "niu type [0x%x]\n", hw_p->niu_type));
7250 	return (status);
7251 
7252 error_exit:
7253 	return (NXGE_ERROR);
7254 }
7255 
7256 boolean_t
7257 nxge_is_valid_local_mac(ether_addr_st mac_addr)
7258 {
7259 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
7260 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
7261 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
7262 		return (B_FALSE);
7263 	else
7264 		return (B_TRUE);
7265 }
7266 
7267 static void
7268 nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
7269 
7270 	npi_status_t rs = NPI_SUCCESS;
7271 	uint8_t xcvr_portn;
7272 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
7273 
7274 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
7275 
7276 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
7277 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
7278 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
7279 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
7280 	}
7281 	/*
7282 	 * For Altas 4-1G copper, Xcvr port numbers are
7283 	 * swapped with ethernet port number. This is
7284 	 * designed for better signal integrity in routing.
7285 	 */
7286 	switch (portn) {
7287 	case 0:
7288 		xcvr_portn += 3;
7289 		break;
7290 	case 1:
7291 		xcvr_portn += 2;
7292 		break;
7293 	case 2:
7294 		xcvr_portn += 1;
7295 		break;
7296 	case 3:
7297 	default:
7298 		break;
7299 	}
7300 
7301 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
7302 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
7303 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
7304 	if (rs != NPI_SUCCESS) {
7305 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7306 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
7307 		    "returned error 0x[%x]", rs));
7308 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7309 		return;
7310 	}
7311 
7312 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
7313 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
7314 	if (rs != NPI_SUCCESS) {
7315 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7316 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
7317 		    "returned error 0x[%x]", rs));
7318 	}
7319 
7320 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
7321 }
7322 
7323 static nxge_status_t
7324 nxge_mii_get_link_mode(p_nxge_t nxgep)
7325 {
7326 	p_nxge_stats_t	statsp;
7327 	uint8_t		xcvr_portn;
7328 	p_mii_regs_t	mii_regs;
7329 	mii_mode_control_stat_t	mode;
7330 	int		status = NXGE_OK;
7331 
7332 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
7333 
7334 	statsp = nxgep->statsp;
7335 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7336 	mii_regs = NULL;
7337 	mode.value = 0;
7338 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7339 #if defined(__i386)
7340 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7341 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7342 	    mode.value)) != NXGE_OK) {
7343 		goto fail;
7344 #else
7345 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7346 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7347 	    mode.value)) != NXGE_OK) {
7348 		goto fail;
7349 #endif
7350 	}
7351 #if defined(__i386)
7352 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7353 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7354 	    &mode.value)) != NXGE_OK) {
7355 		goto fail;
7356 	}
7357 #else
7358 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7359 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7360 	    &mode.value)) != NXGE_OK) {
7361 		goto fail;
7362 	}
7363 #endif
7364 
7365 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
7366 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
7367 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7368 		    "nxge_mii_get_link_mode: fiber mode"));
7369 	}
7370 
7371 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7372 	    "nxge_mii_get_link_mode: "
7373 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
7374 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
7375 	    mode.value, nxgep->mac.portmode));
7376 
7377 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7378 	    "<== nxge_mii_get_link_mode"));
7379 	return (status);
7380 fail:
7381 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7382 	    "<== nxge_mii_get_link_mode (failed)"));
7383 	return (NXGE_ERROR);
7384 }
7385 
7386 nxge_status_t
7387 nxge_mac_set_framesize(p_nxge_t nxgep)
7388 {
7389 	npi_attr_t		ap;
7390 	uint8_t			portn;
7391 	npi_handle_t		handle;
7392 	npi_status_t		rs = NPI_SUCCESS;
7393 
7394 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
7395 
7396 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
7397 	handle = nxgep->npi_handle;
7398 
7399 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7400 	    "==> nxge_mac_sec_framesize: port<%d> "
7401 	    "min framesize %d max framesize %d ",
7402 	    portn,
7403 	    nxgep->mac.minframesize,
7404 	    nxgep->mac.maxframesize));
7405 
7406 	SET_MAC_ATTR2(handle, ap, portn,
7407 	    MAC_PORT_FRAME_SIZE,
7408 	    nxgep->mac.minframesize,
7409 	    nxgep->mac.maxframesize,
7410 	    rs);
7411 	if (rs != NPI_SUCCESS) {
7412 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7413 		    "<== nxge_mac_set_framesize: failed to configure "
7414 		    "max/min frame size port %d", portn));
7415 
7416 		return (NXGE_ERROR | rs);
7417 	}
7418 
7419 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7420 	    "<== nxge_mac_set_framesize: port<%d>", portn));
7421 
7422 	return (NXGE_OK);
7423 }
7424 
7425 static nxge_status_t
7426 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
7427     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
7428 {
7429 	uint8_t i;
7430 
7431 	for (i = 0; i < 4; i++) {
7432 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
7433 			return (NXGE_ERROR);
7434 	}
7435 
7436 	*num_xaui = 0;
7437 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
7438 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
7439 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
7440 	    == TN1010_DEV_ID) &&
7441 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
7442 	    == TN1010_DEV_ID))) {
7443 		(*num_xaui) ++;
7444 	}
7445 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
7446 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
7447 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
7448 	    == TN1010_DEV_ID) &&
7449 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
7450 	    == TN1010_DEV_ID))) {
7451 		(*num_xaui) ++;
7452 	}
7453 	return (NXGE_OK);
7454 }
7455 
7456 /*
7457  * Instruction from Teranetics:  Once you detect link is up, go
7458  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
7459  * may want to qualify it by first checking Register 30.1.7:6 and
7460  * making sure it reads "01" (Auto-Neg Complete).
7461  *
7462  * If this function is called when the link is down or before auto-
7463  * negotiation has completed, then the speed of the PHY is not certain.
7464  * In such cases, this function returns 1G as the default speed with
7465  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
7466  * driver based on a default speed because this function will be called
7467  * again when the link comes up.  Returning NXGE_ERROR, which may
7468  * cause brutal chain reaction in caller functions, is not necessary.
7469  */
7470 static nxge_status_t
7471 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
7472 {
7473 	uint8_t		phy_port_addr, autoneg_stat, link_up;
7474 	nxge_status_t	status = NXGE_OK;
7475 	uint16_t	val;
7476 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
7477 
7478 	/* Set default speed to 10G */
7479 	*speed = TN1010_SPEED_10G;
7480 
7481 	/* Set Clause 45 */
7482 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
7483 
7484 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7485 
7486 	/* Check Device 1 Register 0xA bit0 for link up status */
7487 	status = nxge_mdio_read(nxgep, phy_port_addr,
7488 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
7489 	if (status != NXGE_OK)
7490 		goto fail;
7491 
7492 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
7493 	    ? B_TRUE : B_FALSE);
7494 	if (link_up == B_FALSE) {
7495 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7496 		    "nxge_get_tn1010_speed: link is down"));
7497 		goto nxge_get_tn1010_speed_exit;
7498 	}
7499 
7500 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
7501 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
7502 	    &val)) != NXGE_OK) {
7503 		goto fail;
7504 	}
7505 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
7506 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
7507 
7508 	/*
7509 	 * Return NXGE_OK even when we can not get a settled speed. In
7510 	 * such case, the speed reported should not be trusted but that
7511 	 * is OK, we will call this function periodically and will get
7512 	 * the correct speed after the link is up.
7513 	 */
7514 	switch (autoneg_stat) {
7515 	case TN1010_AN_IN_PROG:
7516 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7517 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
7518 		break;
7519 	case TN1010_AN_COMPLETE:
7520 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
7521 		    TN1010_VENDOR_MMD1_DEV_ADDR,
7522 		    TN1010_VENDOR_MMD1_STATUS_REG,
7523 		    &val)) != NXGE_OK) {
7524 			goto fail;
7525 		}
7526 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
7527 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
7528 		break;
7529 	case TN1010_AN_RSVD:
7530 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7531 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
7532 		break;
7533 	case TN1010_AN_FAILED:
7534 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7535 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
7536 		break;
7537 	default:
7538 		break;
7539 	}
7540 nxge_get_tn1010_speed_exit:
7541 	return (NXGE_OK);
7542 fail:
7543 	return (status);
7544 }
7545 
7546 
7547 /*
7548  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
7549  * figures out the speed of the PHY determined by the autonegotiation
7550  * process and sets the following 3 parameters,
7551  * 	nxgep->mac.portmode
7552  *     	nxgep->statsp->mac_stats.link_speed
7553  *	nxgep->statsp->mac_stats.xcvr_inuse
7554  */
7555 static nxge_status_t
7556 nxge_set_tn1010_param(p_nxge_t nxgep)
7557 {
7558 	uint16_t speed;
7559 
7560 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
7561 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7562 		    "nxge_set_tn1010_param: "
7563 		    "Failed to get TN1010 speed"));
7564 		return (NXGE_ERROR);
7565 	}
7566 	if (speed == TN1010_SPEED_1G) {
7567 		nxgep->mac.portmode = PORT_1G_TN1010;
7568 		nxgep->statsp->mac_stats.link_speed = 1000;
7569 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
7570 	} else {
7571 		nxgep->mac.portmode = PORT_10G_TN1010;
7572 		nxgep->statsp->mac_stats.link_speed = 10000;
7573 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
7574 	}
7575 	return (NXGE_OK);
7576 }
7577 
7578 #ifdef NXGE_DEBUG
7579 static void
7580 nxge_mii_dump(p_nxge_t nxgep)
7581 {
7582 	p_nxge_stats_t	statsp;
7583 	uint8_t		xcvr_portn;
7584 	p_mii_regs_t	mii_regs;
7585 	mii_bmcr_t	bmcr;
7586 	mii_bmsr_t	bmsr;
7587 	mii_idr1_t	idr1;
7588 	mii_idr2_t	idr2;
7589 	mii_mode_control_stat_t	mode;
7590 	p_nxge_param_t	param_arr;
7591 
7592 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
7593 
7594 	statsp = nxgep->statsp;
7595 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7596 
7597 	mii_regs = NULL;
7598 
7599 #if defined(__i386)
7600 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7601 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
7602 #else
7603 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7604 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
7605 #endif
7606 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7607 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
7608 	    xcvr_portn, bmcr.value));
7609 
7610 #if defined(__i386)
7611 	(void) nxge_mii_read(nxgep,
7612 	    nxgep->statsp->mac_stats.xcvr_portn,
7613 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
7614 #else
7615 	(void) nxge_mii_read(nxgep,
7616 	    nxgep->statsp->mac_stats.xcvr_portn,
7617 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
7618 #endif
7619 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7620 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
7621 	    xcvr_portn, bmsr.value));
7622 
7623 #if defined(__i386)
7624 	(void) nxge_mii_read(nxgep,
7625 	    nxgep->statsp->mac_stats.xcvr_portn,
7626 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
7627 #else
7628 	(void) nxge_mii_read(nxgep,
7629 	    nxgep->statsp->mac_stats.xcvr_portn,
7630 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
7631 #endif
7632 
7633 
7634 #if defined(__i386)
7635 	(void) nxge_mii_read(nxgep,
7636 	    nxgep->statsp->mac_stats.xcvr_portn,
7637 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
7638 #else
7639 	(void) nxge_mii_read(nxgep,
7640 	    nxgep->statsp->mac_stats.xcvr_portn,
7641 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
7642 #endif
7643 
7644 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7645 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
7646 	    xcvr_portn, idr1.value));
7647 
7648 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7649 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
7650 	    xcvr_portn, idr2.value));
7651 
7652 	mode.value = 0;
7653 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7654 
7655 #if defined(__i386)
7656 	(void) nxge_mii_write(nxgep, xcvr_portn,
7657 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
7658 
7659 	(void) nxge_mii_read(nxgep, xcvr_portn,
7660 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
7661 #else
7662 	(void) nxge_mii_write(nxgep, xcvr_portn,
7663 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
7664 
7665 	(void) nxge_mii_read(nxgep, xcvr_portn,
7666 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
7667 #endif
7668 
7669 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7670 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
7671 	    xcvr_portn, mode.value));
7672 }
7673 #endif
7674