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