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