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