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