xref: /titanic_50/usr/src/uts/common/io/nxge/nxge_mac.c (revision 1d03c31e0733adea0edef54f0d5d2ea9639ecd2a)
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 2007 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 
31 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
32 #define	LM_WAIT_MULTIPLIER	8
33 
34 extern uint32_t nxge_no_link_notify;
35 extern boolean_t nxge_no_msg;
36 extern uint32_t nxge_lb_dbg;
37 extern nxge_os_mutex_t	nxge_mdio_lock;
38 extern nxge_os_mutex_t	nxge_mii_lock;
39 extern boolean_t nxge_jumbo_enable;
40 
41 typedef enum {
42 	CHECK_LINK_RESCHEDULE,
43 	CHECK_LINK_STOP
44 } check_link_state_t;
45 
46 static check_link_state_t nxge_check_link_stop(nxge_t *);
47 
48 /*
49  * Ethernet broadcast address definition.
50  */
51 static ether_addr_st etherbroadcastaddr =
52 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
53 /*
54  * Ethernet zero address definition.
55  */
56 static ether_addr_st etherzeroaddr =
57 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
58 /*
59  * Supported chip types
60  */
61 static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID};
62 static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID};
63 
64 #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
65 				sizeof (uint32_t))
66 #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
67 				sizeof (uint32_t))
68 /*
69  * static functions
70  */
71 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
72 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
73 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
74 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
75 static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
76 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
77 static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
78 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
79 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
80 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
81 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
82 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
83 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
84 static nxge_status_t nxge_check_mii_link(p_nxge_t);
85 static nxge_status_t nxge_check_10g_link(p_nxge_t);
86 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
87 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
88 static void nxge_bcm5464_link_led_off(p_nxge_t);
89 
90 /*
91  * xcvr tables for supported transceivers
92  */
93 
94 static nxge_xcvr_table_t nxge_n2_10G_table = {
95 	nxge_n2_serdes_init,
96 	nxge_10G_xcvr_init,
97 	nxge_10G_link_intr_stop,
98 	nxge_10G_link_intr_start,
99 	nxge_check_10g_link,
100 	PCS_XCVR,
101 	BCM8704_N2_PORT_ADDR_BASE
102 };
103 
104 static nxge_xcvr_table_t nxge_n2_1G_table = {
105 	nxge_n2_serdes_init,
106 	nxge_1G_xcvr_init,
107 	nxge_1G_fiber_link_intr_stop,
108 	nxge_1G_fiber_link_intr_start,
109 	nxge_check_mii_link,
110 	PCS_XCVR,
111 	0
112 };
113 
114 static nxge_xcvr_table_t nxge_10G_fiber_table = {
115 	nxge_neptune_10G_serdes_init,
116 	nxge_10G_xcvr_init,
117 	nxge_10G_link_intr_stop,
118 	nxge_10G_link_intr_start,
119 	nxge_check_10g_link,
120 	PCS_XCVR,
121 	BCM8704_NEPTUNE_PORT_ADDR_BASE
122 };
123 
124 static nxge_xcvr_table_t nxge_1G_copper_table = {
125 	NULL,
126 	nxge_1G_xcvr_init,
127 	nxge_1G_copper_link_intr_stop,
128 	nxge_1G_copper_link_intr_start,
129 	nxge_check_mii_link,
130 	INT_MII_XCVR,
131 	BCM5464_NEPTUNE_PORT_ADDR_BASE
132 };
133 
134 static nxge_xcvr_table_t nxge_1G_fiber_table = {
135 	nxge_1G_serdes_init,
136 	nxge_1G_xcvr_init,
137 	nxge_1G_fiber_link_intr_stop,
138 	nxge_1G_fiber_link_intr_start,
139 	nxge_check_mii_link,
140 	PCS_XCVR,
141 	0
142 };
143 
144 static nxge_xcvr_table_t nxge_10G_copper_table = {
145 	nxge_neptune_10G_serdes_init,
146 	NULL,
147 	NULL,
148 	NULL,
149 	NULL,
150 	PCS_XCVR,
151 	0
152 };
153 
154 nxge_status_t nxge_mac_init(p_nxge_t);
155 
156 nxge_status_t
157 nxge_get_xcvr_type(p_nxge_t nxgep)
158 {
159 	nxge_status_t status = NXGE_OK;
160 	char *phy_type;
161 	char *prop_val;
162 
163 	nxgep->mac.portmode = 0;
164 
165 	/* Get property from the driver conf. file */
166 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
167 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
168 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
169 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
170 		    "found  conf file: phy-type %s", prop_val));
171 		if (strcmp("xgsd", prop_val) == 0) {
172 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
173 			nxgep->mac.portmode = PORT_10G_SERDES;
174 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
175 			    "found: 10G Serdes"));
176 		} else if (strcmp("gsd", prop_val) == 0) {
177 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
178 			nxgep->mac.portmode = PORT_1G_SERDES;
179 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
180 		} else if (strcmp("mif", prop_val) == 0) {
181 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
182 			nxgep->mac.portmode = PORT_1G_COPPER;
183 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
184 		} else if (strcmp("pcs", prop_val) == 0) {
185 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
186 			nxgep->mac.portmode = PORT_1G_FIBER;
187 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
188 		}
189 
190 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
191 		    "phy-type", prop_val);
192 		ddi_prop_free(prop_val);
193 
194 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
195 		    "Got phy type [0x%x] from conf file",
196 		    nxgep->mac.portmode));
197 
198 		return (NXGE_OK);
199 	}
200 /*
201  * TODO add MDIO support for Monza RTM card, Glendale (also Goa) -
202  * only N2-NIU
203  */
204 	if (nxgep->niu_type == N2_NIU) {
205 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
206 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
207 			if (strcmp("xgf", prop_val) == 0) {
208 				nxgep->statsp->mac_stats.xcvr_inuse =
209 				    XPCS_XCVR;
210 				nxgep->mac.portmode = PORT_10G_FIBER;
211 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
212 				    "10G Fiber Xcvr"));
213 			} else if (strcmp("mif", prop_val) == 0) {
214 				nxgep->statsp->mac_stats.xcvr_inuse =
215 				    INT_MII_XCVR;
216 				nxgep->mac.portmode = PORT_1G_COPPER;
217 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
218 				    "1G Copper Xcvr"));
219 			} else if (strcmp("pcs", prop_val) == 0) {
220 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
221 				nxgep->mac.portmode = PORT_1G_FIBER;
222 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
223 				    "1G Fiber Xcvr"));
224 			} else if (strcmp("xgc", prop_val) == 0) {
225 				nxgep->statsp->mac_stats.xcvr_inuse =
226 				    XPCS_XCVR;
227 				nxgep->mac.portmode = PORT_10G_COPPER;
228 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
229 				    "10G Copper Xcvr"));
230 			} else if (strcmp("xgsd", prop_val) == 0) {
231 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
232 				nxgep->mac.portmode = PORT_10G_SERDES;
233 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
234 				    "OBP: 10G Serdes"));
235 			} else if (strcmp("gsd", prop_val) == 0) {
236 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
237 				nxgep->mac.portmode = PORT_1G_SERDES;
238 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
239 				    "OBP: 1G Serdes"));
240 			} else {
241 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
242 				    "Unknown phy-type: %s", prop_val));
243 				ddi_prop_free(prop_val);
244 				return (NXGE_ERROR);
245 			}
246 			status = NXGE_OK;
247 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
248 			    nxgep->dip, "phy-type", prop_val);
249 			ddi_prop_free(prop_val);
250 
251 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
252 			    "Got phy type [0x%x] from OBP",
253 			    nxgep->mac.portmode));
254 
255 			return (status);
256 		} else {
257 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
258 			    "Exiting...phy-type property not found"));
259 			return (NXGE_ERROR);
260 		}
261 	}
262 
263 
264 	if (!nxgep->vpd_info.present) {
265 		return (NXGE_OK);
266 	}
267 
268 	if (!nxgep->vpd_info.ver_valid) {
269 		goto read_seeprom;
270 	}
271 
272 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
273 	    "Reading phy type from expansion ROM"));
274 	/*
275 	 * Try to read the phy type from the vpd data read off the
276 	 * expansion ROM.
277 	 */
278 	phy_type = nxgep->vpd_info.phy_type;
279 
280 	if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') {
281 		nxgep->mac.portmode = PORT_1G_COPPER;
282 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
283 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
284 	    phy_type[2] == 'f') {
285 		nxgep->mac.portmode = PORT_10G_FIBER;
286 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
287 	} else if (phy_type[0] == 'p' && phy_type[1] == 'c' &&
288 	    phy_type[2] == 's') {
289 		nxgep->mac.portmode = PORT_1G_FIBER;
290 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
291 	} else if (phy_type[0] == 'x' && phy_type[1] == 'g' &&
292 	    phy_type[2] == 'c') {
293 		nxgep->mac.portmode = PORT_10G_COPPER;
294 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
295 	} else {
296 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
297 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
298 		    phy_type[0], phy_type[1], phy_type[2]));
299 		goto read_seeprom;
300 	}
301 
302 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
303 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
304 
305 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
306 	return (status);
307 
308 read_seeprom:
309 	/*
310 	 * read the phy type from the SEEPROM - NCR registers
311 	 */
312 	status = nxge_espc_phy_type_get(nxgep);
313 	if (status != NXGE_OK) {
314 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
315 		    "Failed to get phy type"));
316 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
317 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
318 	}
319 
320 	return (status);
321 
322 }
323 
324 /* Set up the PHY specific values. */
325 
326 nxge_status_t
327 nxge_setup_xcvr_table(p_nxge_t nxgep)
328 {
329 	nxge_status_t	status = NXGE_OK;
330 	uint32_t	port_type;
331 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
332 	uint32_t	pcs_id = 0;
333 	uint32_t	pma_pmd_id = 0;
334 	uint32_t	phy_id = 0;
335 
336 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
337 	    portn));
338 
339 	switch (nxgep->niu_type) {
340 	case N2_NIU:
341 		switch (nxgep->mac.portmode) {
342 		case PORT_1G_FIBER:
343 		case PORT_1G_SERDES:
344 			nxgep->xcvr = nxge_n2_1G_table;
345 			nxgep->xcvr.xcvr_addr = portn;
346 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
347 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
348 			    "Serdes"));
349 			break;
350 		case PORT_10G_FIBER:
351 		case PORT_10G_SERDES:
352 			nxgep->xcvr = nxge_n2_10G_table;
353 			nxgep->xcvr.xcvr_addr += portn;
354 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
355 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
356 			    "Serdes"));
357 			break;
358 		default:
359 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
360 			    "<== nxge_setup_xcvr_table: "
361 			    "Unable to determine NIU portmode"));
362 			return (NXGE_ERROR);
363 		}
364 		break;
365 	default:
366 		if (nxgep->mac.portmode == 0) {
367 			/*
368 			 * Would be the case for platforms like Maramba
369 			 * in which the phy type could not be got from conf
370 			 * file, OBP, VPD or Serial PROM.
371 			 */
372 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
373 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
374 				    "<== nxge_setup_xcvr_table:"
375 				    " Invalid Neptune type [0x%x]",
376 				    nxgep->niu_type));
377 				return (NXGE_ERROR);
378 			}
379 
380 			port_type = nxgep->niu_type >>
381 			    (NXGE_PORT_TYPE_SHIFT * portn);
382 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
383 
384 			switch (port_type) {
385 
386 			case NXGE_PORT_1G_COPPER:
387 				nxgep->mac.portmode = PORT_1G_COPPER;
388 				break;
389 			case NXGE_PORT_10G_COPPER:
390 				nxgep->mac.portmode = PORT_10G_COPPER;
391 				break;
392 			case NXGE_PORT_1G_FIBRE:
393 				nxgep->mac.portmode = PORT_1G_FIBER;
394 				break;
395 			case NXGE_PORT_10G_FIBRE:
396 				nxgep->mac.portmode = PORT_10G_FIBER;
397 				break;
398 			case NXGE_PORT_1G_SERDES:
399 				nxgep->mac.portmode = PORT_1G_SERDES;
400 				break;
401 			case NXGE_PORT_10G_SERDES:
402 				nxgep->mac.portmode = PORT_10G_SERDES;
403 				break;
404 			case NXGE_PORT_1G_RGMII_FIBER:
405 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
406 				break;
407 			default:
408 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
409 				    "<== nxge_setup_xcvr_table: "
410 				    "Unknown port-type: 0x%x", port_type));
411 				return (NXGE_ERROR);
412 			}
413 		}
414 
415 		switch (nxgep->mac.portmode) {
416 		case PORT_1G_COPPER:
417 		case PORT_1G_RGMII_FIBER:
418 			nxgep->xcvr = nxge_1G_copper_table;
419 
420 			/*
421 			 * For Altas 4-1G copper, Xcvr port numbers are
422 			 * swapped with ethernet port number. This is
423 			 * designed for better signal integrity in
424 			 * routing. This is also the case for the
425 			 * on-board Neptune copper ports on the Maramba
426 			 * platform.
427 			 */
428 			switch (nxgep->platform_type) {
429 			case P_NEPTUNE_MARAMBA_P1:
430 				nxgep->xcvr.xcvr_addr =
431 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
432 				break;
433 			case P_NEPTUNE_MARAMBA_P0:
434 				nxgep->xcvr.xcvr_addr =
435 				    BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
436 				break;
437 			default:
438 				break;
439 			}
440 			/*
441 			 * For Altas 4-1G copper, Xcvr port numbers are
442 			 * swapped with ethernet port number. This is
443 			 * designed for better signal integrity in
444 			 * routing. This is also the case for the
445 			 * on-board Neptune copper ports on the Maramba
446 			 * platform.
447 			 */
448 			switch (nxgep->platform_type) {
449 			case P_NEPTUNE_ATLAS_4PORT:
450 			case P_NEPTUNE_MARAMBA_P0:
451 			case P_NEPTUNE_MARAMBA_P1:
452 				switch (portn) {
453 				case 0:
454 					nxgep->xcvr.xcvr_addr += 3;
455 					break;
456 				case 1:
457 					nxgep->xcvr.xcvr_addr += 2;
458 					break;
459 				case 2:
460 					nxgep->xcvr.xcvr_addr += 1;
461 					break;
462 				case 3:
463 					break;
464 				default:
465 					return (NXGE_ERROR);
466 				}
467 				break;
468 			default:
469 				break;
470 			}
471 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
472 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
473 			    "Copper" : "RGMII Fiber"));
474 			break;
475 		case PORT_10G_COPPER:
476 			nxgep->xcvr = nxge_10G_copper_table;
477 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
478 			break;
479 		case PORT_1G_FIBER:
480 		case PORT_1G_SERDES:
481 			nxgep->xcvr = nxge_1G_fiber_table;
482 			nxgep->xcvr.xcvr_addr = portn;
483 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
484 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
485 			    "Fiber" : "Serdes"));
486 			break;
487 		case PORT_10G_FIBER:
488 		case PORT_10G_SERDES:
489 			nxgep->xcvr = nxge_10G_fiber_table;
490 			switch (nxgep->platform_type) {
491 			case P_NEPTUNE_MARAMBA_P0:
492 			case P_NEPTUNE_MARAMBA_P1:
493 				nxgep->xcvr.xcvr_addr =
494 				    BCM8704_MARAMBA_PORT_ADDR_BASE;
495 				/*
496 				 * Switch off LED for corresponding copper
497 				 * port
498 				 */
499 				nxge_bcm5464_link_led_off(nxgep);
500 				break;
501 			default:
502 				break;
503 			}
504 			nxgep->xcvr.xcvr_addr += portn;
505 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
506 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
507 			    "Fiber" : "Serdes"));
508 			break;
509 		default:
510 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
511 			    "Unknown port-type: 0x%x", port_type));
512 			return (NXGE_ERROR);
513 		}
514 	}
515 
516 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
517 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr;
518 
519 	/*
520 	 * Get the actual device ID value returned by MDIO read.
521 	 */
522 	nxgep->statsp->mac_stats.xcvr_id = 0;
523 
524 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr.xcvr_addr);
525 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
526 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
527 	} else {
528 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr.xcvr_addr);
529 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
530 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
531 		} else {
532 			phy_id = nxge_get_cl22_phy_id(nxgep,
533 			    nxgep->xcvr.xcvr_addr);
534 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
535 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
536 			}
537 		}
538 	}
539 
540 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
541 
542 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
543 	    "[0x%x] platform type[0x%x]", nxgep->niu_type,
544 	    nxgep->platform_type));
545 
546 	return (status);
547 }
548 
549 /* Initialize the entire MAC and physical layer */
550 
551 nxge_status_t
552 nxge_mac_init(p_nxge_t nxgep)
553 {
554 	uint8_t			portn;
555 	nxge_status_t		status = NXGE_OK;
556 
557 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
558 
559 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
560 
561 	nxgep->mac.portnum = portn;
562 	nxgep->mac.porttype = PORT_TYPE_XMAC;
563 
564 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
565 		nxgep->mac.porttype = PORT_TYPE_BMAC;
566 
567 	/* Initialize XIF to configure a network mode */
568 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
569 		goto fail;
570 	}
571 
572 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
573 		goto fail;
574 	}
575 
576 	/* Initialize TX and RX MACs */
577 	/*
578 	 * Always perform XIF init first, before TX and RX MAC init
579 	 */
580 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
581 		goto fail;
582 
583 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
584 		goto fail;
585 
586 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
587 		goto fail;
588 
589 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
590 		goto fail;
591 
592 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
593 		goto fail;
594 
595 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
596 		goto fail;
597 
598 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
599 
600 
601 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
602 
603 	return (NXGE_OK);
604 fail:
605 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
606 			"nxge_mac_init: failed to initialize MAC port<%d>",
607 			portn));
608 	return (status);
609 }
610 
611 /* Initialize the Ethernet Link */
612 
613 nxge_status_t
614 nxge_link_init(p_nxge_t nxgep)
615 {
616 	nxge_status_t		status = NXGE_OK;
617 	nxge_port_mode_t	portmode;
618 #ifdef	NXGE_DEBUG
619 	uint8_t			portn;
620 
621 	portn = nxgep->mac.portnum;
622 
623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
624 #endif
625 
626 	portmode = nxgep->mac.portmode;
627 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
628 	    (portmode != PORT_1G_SERDES)) {
629 		/* Workaround to get link up in both NIU ports */
630 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
631 			goto fail;
632 		}
633 	}
634 	NXGE_DELAY(200000);
635 	/* Initialize internal serdes */
636 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
637 		goto fail;
638 	NXGE_DELAY(200000);
639 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
640 		goto fail;
641 
642 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
643 
644 	return (NXGE_OK);
645 
646 fail:
647 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
648 		"nxge_link_init: ",
649 		"failed to initialize Ethernet link on port<%d>",
650 		portn));
651 
652 	return (status);
653 }
654 
655 
656 /* Initialize the XIF sub-block within the MAC */
657 
658 nxge_status_t
659 nxge_xif_init(p_nxge_t nxgep)
660 {
661 	uint32_t		xif_cfg = 0;
662 	npi_attr_t		ap;
663 	uint8_t			portn;
664 	nxge_port_t		portt;
665 	nxge_port_mode_t	portmode;
666 	p_nxge_stats_t		statsp;
667 	npi_status_t		rs = NPI_SUCCESS;
668 	npi_handle_t		handle;
669 
670 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
671 
672 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
673 
674 	handle = nxgep->npi_handle;
675 	portmode = nxgep->mac.portmode;
676 	portt = nxgep->mac.porttype;
677 	statsp = nxgep->statsp;
678 
679 	if (portt == PORT_TYPE_XMAC) {
680 
681 		/* Setup XIF Configuration for XMAC */
682 
683 		if ((portmode == PORT_10G_FIBER) ||
684 		    (portmode == PORT_10G_COPPER) ||
685 		    (portmode == PORT_10G_SERDES))
686 			xif_cfg |= CFG_XMAC_XIF_LFS;
687 
688 		if (portmode == PORT_1G_COPPER) {
689 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
690 		}
691 
692 		/* Set MAC Internal Loopback if necessary */
693 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
694 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
695 
696 		if (statsp->mac_stats.link_speed == 100)
697 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
698 
699 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
700 
701 		if ((portmode == PORT_10G_FIBER) ||
702 		    (portmode == PORT_10G_SERDES)) {
703 			if (statsp->mac_stats.link_up) {
704 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
705 			} else {
706 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
707 			}
708 		}
709 
710 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
711 		if (rs != NPI_SUCCESS)
712 			goto fail;
713 
714 		nxgep->mac.xif_config = xif_cfg;
715 
716 		/* Set Port Mode */
717 		if ((portmode == PORT_10G_FIBER) ||
718 		    (portmode == PORT_10G_COPPER) ||
719 		    (portmode == PORT_10G_SERDES)) {
720 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
721 						MAC_XGMII_MODE, rs);
722 			if (rs != NPI_SUCCESS)
723 				goto fail;
724 			if (statsp->mac_stats.link_up) {
725 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
726 					goto fail;
727 			} else {
728 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
729 					goto fail;
730 			}
731 		} else if ((portmode == PORT_1G_FIBER) ||
732 		    (portmode == PORT_1G_COPPER) ||
733 		    (portmode == PORT_1G_SERDES)) {
734 			if (statsp->mac_stats.link_speed == 1000) {
735 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
736 							MAC_GMII_MODE, rs);
737 			} else {
738 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
739 							MAC_MII_MODE, rs);
740 			}
741 			if (rs != NPI_SUCCESS)
742 				goto fail;
743 		} else {
744 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
745 					"nxge_xif_init: Unknown port mode (%d)"
746 					" for port<%d>", portmode, portn));
747 			goto fail;
748 		}
749 
750 	} else if (portt == PORT_TYPE_BMAC) {
751 
752 		/* Setup XIF Configuration for BMAC */
753 
754 		if (portmode == PORT_1G_COPPER) {
755 			if (statsp->mac_stats.link_speed == 100)
756 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
757 		}
758 
759 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
760 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
761 
762 		if (statsp->mac_stats.link_speed == 1000)
763 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
764 
765 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
766 
767 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
768 		if (rs != NPI_SUCCESS)
769 			goto fail;
770 		nxgep->mac.xif_config = xif_cfg;
771 	}
772 
773 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
774 	return (NXGE_OK);
775 fail:
776 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
777 			"nxge_xif_init: Failed to initialize XIF port<%d>",
778 			portn));
779 	return (NXGE_ERROR | rs);
780 }
781 
782 /* Initialize the PCS sub-block in the MAC */
783 
784 nxge_status_t
785 nxge_pcs_init(p_nxge_t nxgep)
786 {
787 	pcs_cfg_t		pcs_cfg;
788 	uint32_t		val;
789 	uint8_t			portn;
790 	nxge_port_mode_t	portmode;
791 	npi_handle_t		handle;
792 	p_nxge_stats_t		statsp;
793 	npi_status_t		rs = NPI_SUCCESS;
794 
795 	handle = nxgep->npi_handle;
796 	portmode = nxgep->mac.portmode;
797 	portn = nxgep->mac.portnum;
798 	statsp = nxgep->statsp;
799 
800 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
801 
802 	if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) {
803 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) {
804 			goto fail;
805 		}
806 
807 		/* Initialize port's PCS */
808 		pcs_cfg.value = 0;
809 		pcs_cfg.bits.w0.enable = 1;
810 		pcs_cfg.bits.w0.mask = 1;
811 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
812 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
813 
814 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
815 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
816 		    portn, pcs_cfg.value));
817 	} else if ((portmode == PORT_10G_FIBER) ||
818 	    (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) {
819 		/* Use internal XPCS, bypass 1G PCS */
820 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
821 		val &= ~XMAC_XIF_XPCS_BYPASS;
822 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
823 
824 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
825 			goto fail;
826 
827 		/* Set XPCS Internal Loopback if necessary */
828 		if ((rs = npi_xmac_xpcs_read(handle, portn,
829 						XPCS_REG_CONTROL1, &val))
830 						!= NPI_SUCCESS)
831 			goto fail;
832 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
833 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
834 			val |= XPCS_CTRL1_LOOPBK;
835 		else
836 			val &= ~XPCS_CTRL1_LOOPBK;
837 		if ((rs = npi_xmac_xpcs_write(handle, portn,
838 						XPCS_REG_CONTROL1, val))
839 						!= NPI_SUCCESS)
840 			goto fail;
841 
842 		/* Clear descw errors */
843 		if ((rs = npi_xmac_xpcs_write(handle, portn,
844 						XPCS_REG_DESCWERR_COUNTER, 0))
845 						!= NPI_SUCCESS)
846 			goto fail;
847 		/* Clear symbol errors */
848 		if ((rs = npi_xmac_xpcs_read(handle, portn,
849 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
850 					!= NPI_SUCCESS)
851 			goto fail;
852 		if ((rs = npi_xmac_xpcs_read(handle, portn,
853 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
854 					!= NPI_SUCCESS)
855 			goto fail;
856 
857 	} else if (portmode == PORT_1G_COPPER) {
858 		if (portn < 4) {
859 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
860 					PCS_DATAPATH_MODE_MII);
861 		}
862 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
863 			goto fail;
864 
865 	} else {
866 		goto fail;
867 	}
868 pass:
869 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
870 	return (NXGE_OK);
871 fail:
872 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
873 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
874 			portn));
875 	return (NXGE_ERROR | rs);
876 }
877 
878 /* Initialize the Internal Serdes */
879 
880 nxge_status_t
881 nxge_serdes_init(p_nxge_t nxgep)
882 {
883 	p_nxge_stats_t		statsp;
884 #ifdef	NXGE_DEBUG
885 	uint8_t			portn;
886 #endif
887 	nxge_status_t		status = NXGE_OK;
888 
889 #ifdef	NXGE_DEBUG
890 	portn = nxgep->mac.portnum;
891 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
892 	    "==> nxge_serdes_init port<%d>", portn));
893 #endif
894 
895 	if (nxgep->xcvr.serdes_init) {
896 		statsp = nxgep->statsp;
897 		status = nxgep->xcvr.serdes_init(nxgep);
898 		if (status != NXGE_OK)
899 			goto fail;
900 		statsp->mac_stats.serdes_inits++;
901 	}
902 
903 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
904 	    portn));
905 
906 	return (NXGE_OK);
907 
908 fail:
909 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
910 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
911 	    portn));
912 
913 	return (status);
914 }
915 
916 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
917 
918 static nxge_status_t
919 nxge_n2_serdes_init(p_nxge_t nxgep)
920 {
921 	uint8_t portn;
922 	int chan;
923 	esr_ti_cfgpll_l_t pll_cfg_l;
924 	esr_ti_cfgpll_l_t pll_sts_l;
925 	esr_ti_cfgrx_l_t rx_cfg_l;
926 	esr_ti_cfgrx_h_t rx_cfg_h;
927 	esr_ti_cfgtx_l_t tx_cfg_l;
928 	esr_ti_cfgtx_h_t tx_cfg_h;
929 #ifdef NXGE_DEBUG
930 	esr_ti_testcfg_t cfg;
931 #endif
932 	esr_ti_testcfg_t test_cfg;
933 	nxge_status_t status = NXGE_OK;
934 
935 	portn = nxgep->mac.portnum;
936 
937 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
938 			portn));
939 
940 	tx_cfg_l.value = 0;
941 	tx_cfg_h.value = 0;
942 	rx_cfg_l.value = 0;
943 	rx_cfg_h.value = 0;
944 	pll_cfg_l.value = 0;
945 	pll_sts_l.value = 0;
946 	test_cfg.value = 0;
947 
948 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
949 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
950 		/* 0x0E01 */
951 		tx_cfg_l.bits.entx = 1;
952 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
953 
954 		/* 0x9101 */
955 		rx_cfg_l.bits.enrx = 1;
956 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
957 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
958 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
959 
960 		/* 0x0008 */
961 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
962 
963 		/* Set loopback mode if necessary */
964 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
965 			tx_cfg_l.bits.entest = 1;
966 			rx_cfg_l.bits.entest = 1;
967 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
968 			if ((status = nxge_mdio_write(nxgep, portn,
969 				ESR_N2_DEV_ADDR,
970 				ESR_N2_TEST_CFG_REG, test_cfg.value))
971 				!= NXGE_OK)
972 			goto fail;
973 		}
974 
975 		/* Use default PLL value */
976 
977 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
978 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
979 
980 		/* 0x0E21 */
981 		tx_cfg_l.bits.entx = 1;
982 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
983 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
984 
985 		/* 0x9121 */
986 		rx_cfg_l.bits.enrx = 1;
987 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
988 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
989 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
990 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
991 
992 		if (portn == 0) {
993 			/* 0x8 */
994 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
995 		}
996 
997 		/* MPY = 0x100 */
998 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
999 
1000 		/* Set PLL */
1001 		pll_cfg_l.bits.enpll = 1;
1002 		pll_sts_l.bits.enpll = 1;
1003 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1004 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
1005 				!= NXGE_OK)
1006 			goto fail;
1007 
1008 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1009 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
1010 			goto fail;
1011 
1012 #ifdef  NXGE_DEBUG
1013 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1014 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1015 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1016 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1017 		    portn, pll_cfg_l.value, cfg.value));
1018 
1019 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1020 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1021 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1022 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
1023 		    portn, pll_sts_l.value, cfg.value));
1024 #endif
1025 
1026 		/* Set loopback mode if necessary */
1027 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1028 			tx_cfg_l.bits.entest = 1;
1029 			rx_cfg_l.bits.entest = 1;
1030 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1031 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1032 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
1033 			    portn, test_cfg.value));
1034 			if ((status = nxge_mdio_write(nxgep, portn,
1035 			    ESR_N2_DEV_ADDR,
1036 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1037 				goto fail;
1038 			}
1039 		}
1040 	} else {
1041 		goto fail;
1042 	}
1043 
1044 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
1045 
1046 	NXGE_DELAY(20);
1047 
1048 	/* init TX channels */
1049 	for (chan = 0; chan < 4; chan++) {
1050 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1051 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
1052 				!= NXGE_OK)
1053 			goto fail;
1054 
1055 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1056 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
1057 				!= NXGE_OK)
1058 			goto fail;
1059 
1060 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1061 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
1062 		    portn, chan, tx_cfg_l.value));
1063 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1064 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
1065 		    portn, chan, tx_cfg_h.value));
1066 	}
1067 
1068 	/* init RX channels */
1069 	for (chan = 0; chan < 4; chan++) {
1070 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1071 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
1072 				!= NXGE_OK)
1073 			goto fail;
1074 
1075 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1076 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
1077 				!= NXGE_OK)
1078 			goto fail;
1079 
1080 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1081 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
1082 		    portn, chan, rx_cfg_l.value));
1083 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1084 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
1085 		    portn, chan, rx_cfg_h.value));
1086 	}
1087 
1088 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
1089 			portn));
1090 
1091 	return (NXGE_OK);
1092 fail:
1093 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1094 	"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
1095 				portn));
1096 
1097 	return (status);
1098 }
1099 
1100 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
1101 
1102 static nxge_status_t
1103 nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
1104 {
1105 	npi_handle_t		handle;
1106 	uint8_t			portn;
1107 	int			chan;
1108 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1109 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1110 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1111 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
1112 	uint64_t		val;
1113 	uint16_t		val16l;
1114 	uint16_t		val16h;
1115 	nxge_status_t		status = NXGE_OK;
1116 
1117 	portn = nxgep->mac.portnum;
1118 
1119 	if ((portn != 0) && (portn != 1))
1120 		return (NXGE_OK);
1121 
1122 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1123 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
1124 
1125 	handle = nxgep->npi_handle;
1126 	switch (portn) {
1127 	case 0:
1128 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
1129 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
1130 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
1131 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
1132 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
1133 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
1134 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
1135 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
1136 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
1137 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
1138 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
1139 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
1140 
1141 		/* Set Serdes0 Internal Loopback if necessary */
1142 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1143 			ESR_REG_WR(handle,
1144 			    ESR_0_TEST_CONFIG_REG,
1145 			    ESR_PAD_LOOPBACK_CH3 |
1146 			    ESR_PAD_LOOPBACK_CH2 |
1147 			    ESR_PAD_LOOPBACK_CH1 |
1148 			    ESR_PAD_LOOPBACK_CH0);
1149 		} else {
1150 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1151 		}
1152 		break;
1153 	case 1:
1154 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
1155 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
1156 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
1157 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
1158 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
1159 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
1160 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
1161 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
1162 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
1163 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
1164 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
1165 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
1166 
1167 		/* Set Serdes1 Internal Loopback if necessary */
1168 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1169 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
1170 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
1171 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
1172 		} else {
1173 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
1174 		}
1175 		break;
1176 	default:
1177 		/* Nothing to do here */
1178 		goto done;
1179 	}
1180 
1181 	/* init TX RX channels */
1182 	for (chan = 0; chan < 4; chan++) {
1183 		if ((status = nxge_mdio_read(nxgep, portn,
1184 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1185 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
1186 			goto fail;
1187 		if ((status = nxge_mdio_read(nxgep, portn,
1188 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1189 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
1190 			goto fail;
1191 		if ((status = nxge_mdio_read(nxgep, portn,
1192 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1193 		    &glue_ctrl0_l.value)) != NXGE_OK)
1194 			goto fail;
1195 		if ((status = nxge_mdio_read(nxgep, portn,
1196 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1197 		    &glue_ctrl0_h.value)) != NXGE_OK)
1198 			goto fail;
1199 		rx_tx_ctrl_l.bits.enstretch = 1;
1200 		rx_tx_ctrl_h.bits.vmuxlo = 2;
1201 		rx_tx_ctrl_h.bits.vpulselo = 2;
1202 		glue_ctrl0_l.bits.rxlosenable = 1;
1203 		glue_ctrl0_l.bits.samplerate = 0xF;
1204 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
1205 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
1206 		if ((status = nxge_mdio_write(nxgep, portn,
1207 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
1208 		    rx_tx_ctrl_l.value)) != NXGE_OK)
1209 			goto fail;
1210 		if ((status = nxge_mdio_write(nxgep, portn,
1211 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
1212 		    rx_tx_ctrl_h.value)) != NXGE_OK)
1213 			goto fail;
1214 		if ((status = nxge_mdio_write(nxgep, portn,
1215 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
1216 		    glue_ctrl0_l.value)) != NXGE_OK)
1217 			goto fail;
1218 		if ((status = nxge_mdio_write(nxgep, portn,
1219 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
1220 		    glue_ctrl0_h.value)) != NXGE_OK)
1221 			goto fail;
1222 		}
1223 
1224 	/* Apply Tx core reset */
1225 	if ((status = nxge_mdio_write(nxgep, portn,
1226 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
1227 	    (uint16_t)0)) != NXGE_OK)
1228 		goto fail;
1229 
1230 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1231 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
1232 	    NXGE_OK)
1233 		goto fail;
1234 
1235 	NXGE_DELAY(200);
1236 
1237 	/* Apply Rx core reset */
1238 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1239 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
1240 	    NXGE_OK)
1241 		goto fail;
1242 
1243 	NXGE_DELAY(200);
1244 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1245 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
1246 		goto fail;
1247 
1248 	NXGE_DELAY(200);
1249 	if ((status = nxge_mdio_read(nxgep, portn,
1250 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
1251 	    &val16l)) != NXGE_OK)
1252 		goto fail;
1253 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
1254 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
1255 		goto fail;
1256 	if ((val16l != 0) || (val16h != 0)) {
1257 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1258 		    "Failed to reset port<%d> XAUI Serdes", portn));
1259 	}
1260 
1261 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1262 
1263 	if (portn == 0) {
1264 		if ((val & ESR_SIG_P0_BITS_MASK) !=
1265 				(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1266 					ESR_SIG_XSERDES_RDY_P0 |
1267 					ESR_SIG_XDETECT_P0_CH3 |
1268 					ESR_SIG_XDETECT_P0_CH2 |
1269 					ESR_SIG_XDETECT_P0_CH1 |
1270 					ESR_SIG_XDETECT_P0_CH0)) {
1271 			goto fail;
1272 		}
1273 	} else if (portn == 1) {
1274 		if ((val & ESR_SIG_P1_BITS_MASK) !=
1275 				(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1276 					ESR_SIG_XSERDES_RDY_P1 |
1277 					ESR_SIG_XDETECT_P1_CH3 |
1278 					ESR_SIG_XDETECT_P1_CH2 |
1279 					ESR_SIG_XDETECT_P1_CH1 |
1280 					ESR_SIG_XDETECT_P1_CH0)) {
1281 			goto fail;
1282 		}
1283 	}
1284 
1285 done:
1286 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1287 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
1288 
1289 	return (NXGE_OK);
1290 fail:
1291 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1292 	    "nxge_neptune_10G_serdes_init: "
1293 	    "Failed to initialize Neptune serdes for port<%d>", portn));
1294 
1295 	return (status);
1296 }
1297 
1298 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
1299 
1300 static nxge_status_t
1301 nxge_1G_serdes_init(p_nxge_t nxgep)
1302 {
1303 	npi_handle_t		handle;
1304 	uint8_t			portn;
1305 	uint64_t		val;
1306 
1307 	portn = nxgep->mac.portnum;
1308 
1309 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1310 	    "==> nxge_1G_serdes_init port<%d>", portn));
1311 
1312 	handle = nxgep->npi_handle;
1313 
1314 	ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val);
1315 	val &= ~ESR_PLL_CFG_FBDIV_2;
1316 	switch (portn) {
1317 	case 0:
1318 		val |= ESR_PLL_CFG_HALF_RATE_0;
1319 		break;
1320 	case 1:
1321 		val |= ESR_PLL_CFG_HALF_RATE_1;
1322 		break;
1323 	case 2:
1324 		val |= ESR_PLL_CFG_HALF_RATE_2;
1325 		break;
1326 	case 3:
1327 		val |= ESR_PLL_CFG_HALF_RATE_3;
1328 		break;
1329 	default:
1330 		goto fail;
1331 	}
1332 
1333 	ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val);
1334 
1335 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1336 	    "<== nxge_1G_serdes_init port<%d>", portn));
1337 	return (NXGE_OK);
1338 fail:
1339 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1340 	    "nxge_1G_serdes_init: "
1341 	    "Failed to initialize Neptune serdes for port<%d>",
1342 	    portn));
1343 
1344 	return (NXGE_ERROR);
1345 }
1346 
1347 /* Initialize the 10G (BCM8704) Transceiver */
1348 
1349 static nxge_status_t
1350 nxge_10G_xcvr_init(p_nxge_t nxgep)
1351 {
1352 	p_nxge_stats_t		statsp;
1353 	uint16_t		val;
1354 #ifdef	NXGE_DEBUG
1355 	uint8_t			portn;
1356 	uint16_t		val1;
1357 #endif
1358 	uint8_t			phy_port_addr;
1359 	pmd_tx_control_t	tx_ctl;
1360 	control_t		ctl;
1361 	phyxs_control_t		phyxs_ctl;
1362 	pcs_control_t		pcs_ctl;
1363 	uint32_t		delay = 0;
1364 	optics_dcntr_t		op_ctr;
1365 	nxge_status_t		status = NXGE_OK;
1366 #ifdef	NXGE_DEBUG
1367 	portn = nxgep->mac.portnum;
1368 #endif
1369 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
1370 	    portn));
1371 
1372 	statsp = nxgep->statsp;
1373 
1374 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
1375 		goto done;
1376 	}
1377 
1378 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
1379 
1380 	/* Disable Link LEDs */
1381 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
1382 		goto fail;
1383 
1384 	/* Set Clause 45 */
1385 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
1386 
1387 	/* Reset the transceiver */
1388 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1389 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
1390 		goto fail;
1391 
1392 	phyxs_ctl.bits.reset = 1;
1393 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
1394 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
1395 		goto fail;
1396 
1397 	do {
1398 		drv_usecwait(500);
1399 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1400 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
1401 		    &phyxs_ctl.value)) != NXGE_OK)
1402 			goto fail;
1403 		delay++;
1404 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
1405 	if (delay == 100) {
1406 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
1407 		    "failed to reset Transceiver on port<%d>", portn));
1408 		status = NXGE_ERROR;
1409 		goto fail;
1410 	}
1411 
1412 	/* Set to 0x7FBF */
1413 	ctl.value = 0;
1414 	ctl.bits.res1 = 0x3F;
1415 	ctl.bits.optxon_lvl = 1;
1416 	ctl.bits.oprxflt_lvl = 1;
1417 	ctl.bits.optrxlos_lvl = 1;
1418 	ctl.bits.optxflt_lvl = 1;
1419 	ctl.bits.opprflt_lvl = 1;
1420 	ctl.bits.obtmpflt_lvl = 1;
1421 	ctl.bits.opbiasflt_lvl = 1;
1422 	ctl.bits.optxrst_lvl = 1;
1423 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1424 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
1425 	    != NXGE_OK)
1426 		goto fail;
1427 
1428 	/* Set to 0x164 */
1429 	tx_ctl.value = 0;
1430 	tx_ctl.bits.tsck_lpwren = 1;
1431 	tx_ctl.bits.tx_dac_txck = 0x2;
1432 	tx_ctl.bits.tx_dac_txd = 0x1;
1433 	tx_ctl.bits.xfp_clken = 1;
1434 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1435 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
1436 	    tx_ctl.value)) != NXGE_OK)
1437 		goto fail;
1438 	/*
1439 	 * According to Broadcom's instruction, SW needs to read
1440 	 * back these registers twice after written.
1441 	 */
1442 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1443 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1444 	    != NXGE_OK)
1445 		goto fail;
1446 
1447 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1448 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
1449 	    != NXGE_OK)
1450 		goto fail;
1451 
1452 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1453 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1454 	    != NXGE_OK)
1455 		goto fail;
1456 
1457 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1458 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
1459 	    != NXGE_OK)
1460 		goto fail;
1461 
1462 	/* Enable Tx and Rx LEDs to be driven by traffic */
1463 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1464 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1465 	    &op_ctr.value)) != NXGE_OK)
1466 		goto fail;
1467 	op_ctr.bits.gpio_sel = 0x3;
1468 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1469 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
1470 	    op_ctr.value)) != NXGE_OK)
1471 		goto fail;
1472 
1473 	NXGE_DELAY(1000000);
1474 
1475 	/* Set BCM8704 Internal Loopback mode if necessary */
1476 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
1477 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
1478 	    != NXGE_OK)
1479 		goto fail;
1480 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
1481 		pcs_ctl.bits.loopback = 1;
1482 	else
1483 		pcs_ctl.bits.loopback = 0;
1484 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
1485 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
1486 	    != NXGE_OK)
1487 		goto fail;
1488 
1489 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
1490 	if (status != NXGE_OK)
1491 		goto fail;
1492 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1493 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
1494 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
1495 	if (status != NXGE_OK)
1496 		goto fail;
1497 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1498 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
1499 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
1500 	if (status != NXGE_OK)
1501 		goto fail;
1502 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1503 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
1504 
1505 #ifdef	NXGE_DEBUG
1506 	/* Diagnose link issue if link is not up */
1507 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
1508 	    BCM8704_USER_ANALOG_STATUS0_REG,
1509 	    &val);
1510 	if (status != NXGE_OK)
1511 		goto fail;
1512 
1513 	status = nxge_mdio_read(nxgep, phy_port_addr,
1514 				BCM8704_USER_DEV3_ADDR,
1515 				BCM8704_USER_ANALOG_STATUS0_REG,
1516 				&val);
1517 	if (status != NXGE_OK)
1518 		goto fail;
1519 
1520 	status = nxge_mdio_read(nxgep, phy_port_addr,
1521 				BCM8704_USER_DEV3_ADDR,
1522 				BCM8704_USER_TX_ALARM_STATUS_REG,
1523 				&val1);
1524 	if (status != NXGE_OK)
1525 		goto fail;
1526 
1527 	status = nxge_mdio_read(nxgep, phy_port_addr,
1528 				BCM8704_USER_DEV3_ADDR,
1529 				BCM8704_USER_TX_ALARM_STATUS_REG,
1530 				&val1);
1531 	if (status != NXGE_OK)
1532 		goto fail;
1533 
1534 	if (val != 0x3FC) {
1535 		if ((val == 0x43BC) && (val1 != 0)) {
1536 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1537 			    "Cable not connected to peer or bad"
1538 			    " cable on port<%d>\n", portn));
1539 		} else if (val == 0x639C) {
1540 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1541 			    "Optical module (XFP) is bad or absent"
1542 			    " on port<%d>\n", portn));
1543 		}
1544 	}
1545 #endif
1546 
1547 done:
1548 	statsp->mac_stats.cap_10gfdx = 1;
1549 	statsp->mac_stats.lp_cap_10gfdx = 1;
1550 
1551 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
1552 	    portn));
1553 	return (NXGE_OK);
1554 
1555 fail:
1556 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1557 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
1558 	    "port<%d>", portn));
1559 	return (status);
1560 }
1561 
1562 /* Initialize the 1G copper (BCM 5464) Transceiver */
1563 
1564 static nxge_status_t
1565 nxge_1G_xcvr_init(p_nxge_t nxgep)
1566 {
1567 	p_nxge_param_t		param_arr = nxgep->param_arr;
1568 	p_nxge_stats_t		statsp = nxgep->statsp;
1569 	nxge_status_t		status = NXGE_OK;
1570 
1571 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
1572 		statsp->mac_stats.cap_1000fdx =
1573 		    param_arr[param_anar_1000fdx].value;
1574 		goto done;
1575 	}
1576 
1577 	/* Set Clause 22 */
1578 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
1579 
1580 	/* Set capability flags */
1581 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
1582 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
1583 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
1584 		statsp->mac_stats.cap_100fdx =
1585 		    param_arr[param_anar_100fdx].value;
1586 		statsp->mac_stats.cap_10fdx =
1587 		    param_arr[param_anar_10fdx].value;
1588 	}
1589 
1590 	status = nxge_mii_xcvr_init(nxgep);
1591 done:
1592 	return (status);
1593 }
1594 
1595 /* Initialize transceiver */
1596 
1597 nxge_status_t
1598 nxge_xcvr_init(p_nxge_t nxgep)
1599 {
1600 	p_nxge_stats_t		statsp;
1601 #ifdef	NXGE_DEBUG
1602 	uint8_t			portn;
1603 #endif
1604 
1605 	nxge_status_t		status = NXGE_OK;
1606 #ifdef	NXGE_DEBUG
1607 	portn = nxgep->mac.portnum;
1608 #endif
1609 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
1610 	statsp = nxgep->statsp;
1611 
1612 	/*
1613 	 * Initialize the xcvr statistics.
1614 	 */
1615 	statsp->mac_stats.cap_autoneg = 0;
1616 	statsp->mac_stats.cap_100T4 = 0;
1617 	statsp->mac_stats.cap_100fdx = 0;
1618 	statsp->mac_stats.cap_100hdx = 0;
1619 	statsp->mac_stats.cap_10fdx = 0;
1620 	statsp->mac_stats.cap_10hdx = 0;
1621 	statsp->mac_stats.cap_asmpause = 0;
1622 	statsp->mac_stats.cap_pause = 0;
1623 	statsp->mac_stats.cap_1000fdx = 0;
1624 	statsp->mac_stats.cap_1000hdx = 0;
1625 	statsp->mac_stats.cap_10gfdx = 0;
1626 	statsp->mac_stats.cap_10ghdx = 0;
1627 
1628 	/*
1629 	 * Initialize the link statistics.
1630 	 */
1631 	statsp->mac_stats.link_T4 = 0;
1632 	statsp->mac_stats.link_asmpause = 0;
1633 	statsp->mac_stats.link_pause = 0;
1634 
1635 	if (nxgep->xcvr.xcvr_init) {
1636 		status = nxgep->xcvr.xcvr_init(nxgep);
1637 		if (status != NXGE_OK)
1638 			goto fail;
1639 		statsp->mac_stats.xcvr_inits++;
1640 	}
1641 
1642 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
1643 	    portn));
1644 	return (NXGE_OK);
1645 
1646 fail:
1647 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1648 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
1649 	    portn));
1650 	return (status);
1651 }
1652 
1653 /* Look for transceiver type */
1654 
1655 nxge_status_t
1656 nxge_xcvr_find(p_nxge_t nxgep)
1657 {
1658 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1659 	    "==> nxge_xcvr_find: port<%d>", nxgep->mac.portnum));
1660 
1661 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
1662 		return (NXGE_ERROR);
1663 
1664 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
1665 		return (NXGE_ERROR);
1666 
1667 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
1668 	    nxgep->statsp->mac_stats.xcvr_inuse));
1669 
1670 	return (NXGE_OK);
1671 }
1672 
1673 /* Initialize the TxMAC sub-block */
1674 
1675 nxge_status_t
1676 nxge_tx_mac_init(p_nxge_t nxgep)
1677 {
1678 	npi_attr_t		ap;
1679 	uint8_t			portn;
1680 	nxge_port_mode_t	portmode;
1681 	nxge_port_t		portt;
1682 	npi_handle_t		handle;
1683 	npi_status_t		rs = NPI_SUCCESS;
1684 
1685 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1686 	portt    = nxgep->mac.porttype;
1687 	handle   = nxgep->npi_handle;
1688 	portmode = nxgep->mac.portmode;
1689 
1690 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
1691 			portn));
1692 
1693 	/* Set Max and Min Frame Size */
1694 	if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
1695 		SET_MAC_ATTR2(handle, ap, portn,
1696 		    MAC_PORT_FRAME_SIZE, 64, 0x2400, rs);
1697 	} else {
1698 		SET_MAC_ATTR2(handle, ap, portn,
1699 		    MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs);
1700 	}
1701 
1702 	if (rs != NPI_SUCCESS)
1703 		goto fail;
1704 	if (nxgep->param_arr[param_accept_jumbo].value ||
1705 		nxgep->mac.is_jumbo == B_TRUE)
1706 		nxgep->mac.maxframesize = 0x2400;
1707 	else
1708 		nxgep->mac.maxframesize = 0x5EE + 4;
1709 	nxgep->mac.minframesize = 64;
1710 
1711 	if (portt == PORT_TYPE_XMAC) {
1712 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
1713 				0)) != NPI_SUCCESS)
1714 			goto fail;
1715 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
1716 		if ((portmode == PORT_10G_FIBER) ||
1717 		    (portmode == PORT_10G_COPPER) ||
1718 		    (portmode == PORT_10G_SERDES)) {
1719 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
1720 					XGMII_IPG_12_15, rs);
1721 			if (rs != NPI_SUCCESS)
1722 				goto fail;
1723 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
1724 		} else {
1725 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
1726 					MII_GMII_IPG_12, rs);
1727 			if (rs != NPI_SUCCESS)
1728 				goto fail;
1729 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
1730 		}
1731 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
1732 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
1733 			goto fail;
1734 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
1735 		nxgep->mac.maxburstsize = 0;	/* not programmable */
1736 		nxgep->mac.ctrltype = 0;	/* not programmable */
1737 		nxgep->mac.pa_size = 0;		/* not programmable */
1738 
1739 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
1740 							!= NPI_SUCCESS)
1741 			goto fail;
1742 
1743 	} else {
1744 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
1745 				0)) != NPI_SUCCESS)
1746 			goto fail;
1747 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
1748 
1749 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
1750 				rs);
1751 		if (rs != NPI_SUCCESS)
1752 			goto fail;
1753 		nxgep->mac.ctrltype = 0x8808;
1754 
1755 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
1756 		if (rs != NPI_SUCCESS)
1757 			goto fail;
1758 		nxgep->mac.pa_size = 0x7;
1759 
1760 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
1761 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
1762 			goto fail;
1763 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
1764 	}
1765 
1766 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
1767 			portn));
1768 
1769 	return (NXGE_OK);
1770 fail:
1771 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1772 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
1773 					portn));
1774 
1775 	return (NXGE_ERROR | rs);
1776 }
1777 
1778 /* Initialize the RxMAC sub-block */
1779 
1780 nxge_status_t
1781 nxge_rx_mac_init(p_nxge_t nxgep)
1782 {
1783 	npi_attr_t		ap;
1784 	uint32_t		i;
1785 	uint16_t		hashtab_e;
1786 	p_hash_filter_t		hash_filter;
1787 	nxge_port_t		portt;
1788 	uint8_t			portn;
1789 	npi_handle_t		handle;
1790 	npi_status_t		rs = NPI_SUCCESS;
1791 	uint16_t 		*addr16p;
1792 	uint16_t 		addr0, addr1, addr2;
1793 	xmac_rx_config_t	xconfig;
1794 	bmac_rx_config_t	bconfig;
1795 
1796 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1797 
1798 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
1799 			portn));
1800 	handle = nxgep->npi_handle;
1801 	portt = nxgep->mac.porttype;
1802 
1803 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
1804 	addr0 = ntohs(addr16p[2]);
1805 	addr1 = ntohs(addr16p[1]);
1806 	addr2 = ntohs(addr16p[0]);
1807 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
1808 		rs);
1809 
1810 	if (rs != NPI_SUCCESS)
1811 		goto fail;
1812 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
1813 	if (rs != NPI_SUCCESS)
1814 		goto fail;
1815 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
1816 	if (rs != NPI_SUCCESS)
1817 		goto fail;
1818 
1819 	/*
1820 	 * Load the multicast hash filter bits.
1821 	 */
1822 	hash_filter = nxgep->hash_filter;
1823 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
1824 		if (hash_filter != NULL) {
1825 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
1826 				(NMCFILTER_REGS - 1) - i];
1827 		} else {
1828 			hashtab_e = 0;
1829 		}
1830 
1831 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
1832 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
1833 			goto fail;
1834 	}
1835 
1836 	if (portt == PORT_TYPE_XMAC) {
1837 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
1838 				0)) != NPI_SUCCESS)
1839 			goto fail;
1840 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
1841 
1842 		(void) nxge_fflp_init_hostinfo(nxgep);
1843 
1844 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
1845 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
1846 			~CFG_XMAC_RX_STRIP_CRC;
1847 
1848 		if (nxgep->filter.all_phys_cnt != 0)
1849 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
1850 
1851 		if (nxgep->filter.all_multicast_cnt != 0)
1852 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
1853 
1854 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
1855 
1856 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
1857 					xconfig)) != NPI_SUCCESS)
1858 			goto fail;
1859 		nxgep->mac.rx_config = xconfig;
1860 
1861 		/* Comparison of mac unique address is always enabled on XMAC */
1862 
1863 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
1864 							!= NPI_SUCCESS)
1865 			goto fail;
1866 	} else {
1867 		(void) nxge_fflp_init_hostinfo(nxgep);
1868 
1869 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
1870 					0) != NPI_SUCCESS)
1871 			goto fail;
1872 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
1873 
1874 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
1875 			~CFG_BMAC_RX_STRIP_CRC;
1876 
1877 		if (nxgep->filter.all_phys_cnt != 0)
1878 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
1879 
1880 		if (nxgep->filter.all_multicast_cnt != 0)
1881 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
1882 
1883 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
1884 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
1885 					bconfig)) != NPI_SUCCESS)
1886 			goto fail;
1887 		nxgep->mac.rx_config = bconfig;
1888 
1889 		/* Always enable comparison of mac unique address */
1890 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
1891 					!= NPI_SUCCESS)
1892 			goto fail;
1893 	}
1894 
1895 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
1896 			portn));
1897 
1898 	return (NXGE_OK);
1899 
1900 fail:
1901 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1902 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
1903 				portn));
1904 
1905 	return (NXGE_ERROR | rs);
1906 }
1907 
1908 /* Enable TXMAC */
1909 
1910 nxge_status_t
1911 nxge_tx_mac_enable(p_nxge_t nxgep)
1912 {
1913 	npi_handle_t	handle;
1914 	npi_status_t	rs = NPI_SUCCESS;
1915 	nxge_status_t	status = NXGE_OK;
1916 
1917 	handle = nxgep->npi_handle;
1918 
1919 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
1920 			nxgep->mac.portnum));
1921 
1922 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
1923 		goto fail;
1924 
1925 	/* based on speed */
1926 	nxgep->msg_min = ETHERMIN;
1927 
1928 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1929 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
1930 						CFG_XMAC_TX)) != NPI_SUCCESS)
1931 			goto fail;
1932 	} else {
1933 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
1934 						CFG_BMAC_TX)) != NPI_SUCCESS)
1935 			goto fail;
1936 	}
1937 
1938 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
1939 			nxgep->mac.portnum));
1940 
1941 	return (NXGE_OK);
1942 fail:
1943 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1944 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
1945 			nxgep->mac.portnum));
1946 	if (rs != NPI_SUCCESS)
1947 		return (NXGE_ERROR | rs);
1948 	else
1949 		return (status);
1950 }
1951 
1952 /* Disable TXMAC */
1953 
1954 nxge_status_t
1955 nxge_tx_mac_disable(p_nxge_t nxgep)
1956 {
1957 	npi_handle_t	handle;
1958 	npi_status_t	rs = NPI_SUCCESS;
1959 
1960 	handle = nxgep->npi_handle;
1961 
1962 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
1963 			nxgep->mac.portnum));
1964 
1965 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
1966 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
1967 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
1968 			goto fail;
1969 	} else {
1970 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
1971 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
1972 			goto fail;
1973 	}
1974 
1975 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
1976 			nxgep->mac.portnum));
1977 	return (NXGE_OK);
1978 fail:
1979 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1980 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
1981 			nxgep->mac.portnum));
1982 	return (NXGE_ERROR | rs);
1983 }
1984 
1985 /* Enable RXMAC */
1986 
1987 nxge_status_t
1988 nxge_rx_mac_enable(p_nxge_t nxgep)
1989 {
1990 	npi_handle_t	handle;
1991 	uint8_t 	portn;
1992 	npi_status_t	rs = NPI_SUCCESS;
1993 	nxge_status_t	status = NXGE_OK;
1994 
1995 	handle = nxgep->npi_handle;
1996 	portn = nxgep->mac.portnum;
1997 
1998 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
1999 			portn));
2000 
2001 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
2002 		goto fail;
2003 
2004 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2005 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
2006 						CFG_XMAC_RX)) != NPI_SUCCESS)
2007 			goto fail;
2008 	} else {
2009 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
2010 						CFG_BMAC_RX)) != NPI_SUCCESS)
2011 			goto fail;
2012 	}
2013 
2014 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>",
2015 			portn));
2016 
2017 	return (NXGE_OK);
2018 fail:
2019 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2020 			"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC",
2021 			portn));
2022 
2023 	if (rs != NPI_SUCCESS)
2024 		return (NXGE_ERROR | rs);
2025 	else
2026 		return (status);
2027 }
2028 
2029 /* Disable RXMAC */
2030 
2031 nxge_status_t
2032 nxge_rx_mac_disable(p_nxge_t nxgep)
2033 {
2034 	npi_handle_t	handle;
2035 	uint8_t		portn;
2036 	npi_status_t	rs = NPI_SUCCESS;
2037 
2038 	handle = nxgep->npi_handle;
2039 	portn = nxgep->mac.portnum;
2040 
2041 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
2042 			portn));
2043 
2044 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2045 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
2046 						CFG_XMAC_RX)) != NPI_SUCCESS)
2047 			goto fail;
2048 	} else {
2049 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
2050 						CFG_BMAC_RX)) != NPI_SUCCESS)
2051 			goto fail;
2052 	}
2053 
2054 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
2055 			portn));
2056 	return (NXGE_OK);
2057 fail:
2058 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2059 			"nxgep_rx_mac_disable: ",
2060 			"Failed to disable port<%d> RxMAC",
2061 			portn));
2062 
2063 	return (NXGE_ERROR | rs);
2064 }
2065 
2066 /* Reset TXMAC */
2067 
2068 nxge_status_t
2069 nxge_tx_mac_reset(p_nxge_t nxgep)
2070 {
2071 	npi_handle_t	handle;
2072 	uint8_t		portn;
2073 	npi_status_t	rs = NPI_SUCCESS;
2074 
2075 	handle = nxgep->npi_handle;
2076 	portn = nxgep->mac.portnum;
2077 
2078 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
2079 			portn));
2080 
2081 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2082 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
2083 		    != NPI_SUCCESS)
2084 			goto fail;
2085 	} else {
2086 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
2087 					!= NPI_SUCCESS)
2088 			goto fail;
2089 	}
2090 
2091 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
2092 			portn));
2093 
2094 	return (NXGE_OK);
2095 fail:
2096 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2097 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
2098 			portn));
2099 
2100 	return (NXGE_ERROR | rs);
2101 }
2102 
2103 /* Reset RXMAC */
2104 
2105 nxge_status_t
2106 nxge_rx_mac_reset(p_nxge_t nxgep)
2107 {
2108 	npi_handle_t	handle;
2109 	uint8_t		portn;
2110 	npi_status_t	rs = NPI_SUCCESS;
2111 
2112 	handle = nxgep->npi_handle;
2113 	portn = nxgep->mac.portnum;
2114 
2115 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
2116 			portn));
2117 
2118 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
2119 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
2120 		    != NPI_SUCCESS)
2121 		goto fail;
2122 	} else {
2123 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
2124 					!= NPI_SUCCESS)
2125 		goto fail;
2126 	}
2127 
2128 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
2129 			portn));
2130 
2131 	return (NXGE_OK);
2132 fail:
2133 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2134 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
2135 			portn));
2136 	return (NXGE_ERROR | rs);
2137 }
2138 
2139 /* 10G fiber link interrupt start routine */
2140 
2141 static nxge_status_t
2142 nxge_10G_link_intr_start(p_nxge_t nxgep)
2143 {
2144 	npi_status_t	rs = NPI_SUCCESS;
2145 	uint8_t		portn = nxgep->mac.portnum;
2146 
2147 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
2148 
2149 	if (rs != NPI_SUCCESS)
2150 		return (NXGE_ERROR | rs);
2151 	else
2152 		return (NXGE_OK);
2153 }
2154 
2155 /* 10G fiber link interrupt stop routine */
2156 
2157 static nxge_status_t
2158 nxge_10G_link_intr_stop(p_nxge_t nxgep)
2159 {
2160 	npi_status_t	rs = NPI_SUCCESS;
2161 	uint8_t		portn = nxgep->mac.portnum;
2162 
2163 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
2164 
2165 	if (rs != NPI_SUCCESS)
2166 		return (NXGE_ERROR | rs);
2167 	else
2168 		return (NXGE_OK);
2169 }
2170 
2171 /* 1G fiber link interrupt start routine */
2172 
2173 static nxge_status_t
2174 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
2175 {
2176 	npi_status_t	rs = NPI_SUCCESS;
2177 	uint8_t		portn = nxgep->mac.portnum;
2178 
2179 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
2180 	if (rs != NPI_SUCCESS)
2181 		return (NXGE_ERROR | rs);
2182 	else
2183 		return (NXGE_OK);
2184 }
2185 
2186 /* 1G fiber link interrupt stop routine */
2187 
2188 static nxge_status_t
2189 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
2190 {
2191 	npi_status_t	rs = NPI_SUCCESS;
2192 	uint8_t		portn = nxgep->mac.portnum;
2193 
2194 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
2195 
2196 	if (rs != NPI_SUCCESS)
2197 		return (NXGE_ERROR | rs);
2198 	else
2199 		return (NXGE_OK);
2200 }
2201 
2202 /* 1G copper link interrupt start routine */
2203 
2204 static nxge_status_t
2205 nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
2206 {
2207 	npi_status_t	rs = NPI_SUCCESS;
2208 	uint8_t		portn = nxgep->mac.portnum;
2209 
2210 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
2211 	    MII_BMSR, BMSR_LSTATUS);
2212 
2213 	if (rs != NPI_SUCCESS)
2214 		return (NXGE_ERROR | rs);
2215 	else
2216 		return (NXGE_OK);
2217 }
2218 
2219 /* 1G copper link interrupt stop routine */
2220 
2221 static nxge_status_t
2222 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
2223 {
2224 	npi_status_t	rs = NPI_SUCCESS;
2225 	uint8_t		portn = nxgep->mac.portnum;
2226 
2227 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
2228 
2229 	if (rs != NPI_SUCCESS)
2230 		return (NXGE_ERROR | rs);
2231 	else
2232 		return (NXGE_OK);
2233 }
2234 
2235 /* Enable/Disable Link Status change interrupt */
2236 
2237 nxge_status_t
2238 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
2239 {
2240 	uint8_t		portn;
2241 	nxge_status_t	status = NXGE_OK;
2242 
2243 	portn = nxgep->mac.portnum;
2244 
2245 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
2246 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
2247 		return (NXGE_OK);
2248 
2249 	if (enable == LINK_INTR_START)
2250 		status = nxgep->xcvr.link_intr_start(nxgep);
2251 	else if (enable == LINK_INTR_STOP)
2252 		status = nxgep->xcvr.link_intr_stop(nxgep);
2253 	if (status != NXGE_OK)
2254 		goto fail;
2255 
2256 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
2257 
2258 	return (NXGE_OK);
2259 fail:
2260 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2261 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
2262 			portn));
2263 
2264 	return (status);
2265 }
2266 
2267 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
2268 
2269 nxge_status_t
2270 nxge_mii_xcvr_init(p_nxge_t nxgep)
2271 {
2272 	p_nxge_param_t	param_arr;
2273 	p_nxge_stats_t	statsp;
2274 	uint8_t		xcvr_portn;
2275 	p_mii_regs_t	mii_regs;
2276 	mii_bmcr_t	bmcr;
2277 	mii_bmsr_t	bmsr;
2278 	mii_anar_t	anar;
2279 	mii_gcr_t	gcr;
2280 	mii_esr_t	esr;
2281 	mii_aux_ctl_t	bcm5464r_aux;
2282 	int		status = NXGE_OK;
2283 
2284 	uint_t delay;
2285 
2286 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
2287 
2288 	param_arr = nxgep->param_arr;
2289 	statsp = nxgep->statsp;
2290 	xcvr_portn = statsp->mac_stats.xcvr_portn;
2291 
2292 	mii_regs = NULL;
2293 
2294 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2295 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
2296 
2297 	/*
2298 	 * Reset the transceiver.
2299 	 */
2300 	delay = 0;
2301 	bmcr.value = 0;
2302 	bmcr.bits.reset = 1;
2303 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2304 #if defined(__i386)
2305 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2306 #else
2307 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
2308 #endif
2309 		goto fail;
2310 	do {
2311 		drv_usecwait(500);
2312 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
2313 #if defined(__i386)
2314 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
2315 #else
2316 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
2317 #endif
2318 				!= NXGE_OK)
2319 			goto fail;
2320 		delay++;
2321 	} while ((bmcr.bits.reset) && (delay < 1000));
2322 	if (delay == 1000) {
2323 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
2324 		goto fail;
2325 	}
2326 
2327 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2328 #if defined(__i386)
2329 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
2330 #else
2331 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
2332 #endif
2333 			&bmsr.value)) != NXGE_OK)
2334 		goto fail;
2335 
2336 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
2337 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
2338 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
2339 	param_arr[param_anar_100hdx].value = 0;
2340 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
2341 	param_arr[param_anar_10hdx].value = 0;
2342 
2343 	/*
2344 	 * Initialize the xcvr statistics.
2345 	 */
2346 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
2347 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
2348 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
2349 	statsp->mac_stats.cap_100hdx = 0;
2350 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
2351 	statsp->mac_stats.cap_10hdx = 0;
2352 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
2353 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
2354 
2355 	/*
2356 	 * Initialise the xcvr advertised capability statistics.
2357 	 */
2358 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
2359 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
2360 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
2361 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
2362 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
2363 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
2364 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
2365 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
2366 	statsp->mac_stats.adv_cap_asmpause =
2367 					param_arr[param_anar_asmpause].value;
2368 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
2369 
2370 
2371 	/*
2372 	 * Check for extended status just in case we're
2373 	 * running a Gigibit phy.
2374 	 */
2375 	if (bmsr.bits.extend_status) {
2376 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
2377 #if defined(__i386)
2378 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
2379 #else
2380 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
2381 #endif
2382 				!= NXGE_OK)
2383 			goto fail;
2384 		param_arr[param_anar_1000fdx].value &=
2385 					esr.bits.link_1000fdx;
2386 		param_arr[param_anar_1000hdx].value = 0;
2387 
2388 		statsp->mac_stats.cap_1000fdx =
2389 			(esr.bits.link_1000Xfdx ||
2390 				esr.bits.link_1000fdx);
2391 		statsp->mac_stats.cap_1000hdx = 0;
2392 	} else {
2393 		param_arr[param_anar_1000fdx].value = 0;
2394 		param_arr[param_anar_1000hdx].value = 0;
2395 	}
2396 
2397 	/*
2398 	 * Initialize 1G Statistics once the capability is established.
2399 	 */
2400 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
2401 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
2402 
2403 	/*
2404 	 * Initialise the link statistics.
2405 	 */
2406 	statsp->mac_stats.link_T4 = 0;
2407 	statsp->mac_stats.link_asmpause = 0;
2408 	statsp->mac_stats.link_pause = 0;
2409 	statsp->mac_stats.link_speed = 0;
2410 	statsp->mac_stats.link_duplex = 0;
2411 	statsp->mac_stats.link_up = 0;
2412 
2413 	/*
2414 	 * Switch off Auto-negotiation, 100M and full duplex.
2415 	 */
2416 	bmcr.value = 0;
2417 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2418 #if defined(__i386)
2419 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
2420 #else
2421 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
2422 #endif
2423 		goto fail;
2424 
2425 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
2426 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
2427 		bmcr.bits.loopback = 1;
2428 		bmcr.bits.enable_autoneg = 0;
2429 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
2430 			bmcr.bits.speed_1000_sel = 1;
2431 		bmcr.bits.duplex_mode = 1;
2432 		param_arr[param_autoneg].value = 0;
2433 	} else {
2434 		bmcr.bits.loopback = 0;
2435 	}
2436 
2437 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
2438 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
2439 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
2440 		param_arr[param_autoneg].value = 0;
2441 		bcm5464r_aux.value = 0;
2442 		bcm5464r_aux.bits.ext_lb = 1;
2443 		bcm5464r_aux.bits.write_1 = 1;
2444 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
2445 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
2446 				!= NXGE_OK)
2447 			goto fail;
2448 	}
2449 
2450 	if (param_arr[param_autoneg].value) {
2451 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2452 				"Restarting Auto-negotiation."));
2453 		/*
2454 		 * Setup our Auto-negotiation advertisement register.
2455 		 */
2456 		anar.value = 0;
2457 		anar.bits.selector = 1;
2458 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
2459 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
2460 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
2461 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
2462 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
2463 		anar.bits.cap_asmpause = 0;
2464 		anar.bits.cap_pause = 0;
2465 		if (param_arr[param_anar_1000fdx].value ||
2466 			param_arr[param_anar_100fdx].value ||
2467 			param_arr[param_anar_10fdx].value) {
2468 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
2469 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
2470 		}
2471 
2472 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
2473 #if defined(__i386)
2474 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
2475 #else
2476 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
2477 #endif
2478 				!= NXGE_OK)
2479 			goto fail;
2480 		if (bmsr.bits.extend_status) {
2481 			gcr.value = 0;
2482 			gcr.bits.ms_mode_en =
2483 				param_arr[param_master_cfg_enable].value;
2484 			gcr.bits.master =
2485 				param_arr[param_master_cfg_value].value;
2486 			gcr.bits.link_1000fdx =
2487 				param_arr[param_anar_1000fdx].value;
2488 			gcr.bits.link_1000hdx =
2489 				param_arr[param_anar_1000hdx].value;
2490 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2491 #if defined(__i386)
2492 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
2493 #else
2494 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
2495 #endif
2496 				!= NXGE_OK)
2497 				goto fail;
2498 		}
2499 
2500 		bmcr.bits.enable_autoneg = 1;
2501 		bmcr.bits.restart_autoneg = 1;
2502 
2503 	} else {
2504 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
2505 		bmcr.bits.speed_1000_sel =
2506 			param_arr[param_anar_1000fdx].value |
2507 				param_arr[param_anar_1000hdx].value;
2508 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
2509 			(param_arr[param_anar_100fdx].value |
2510 				param_arr[param_anar_100hdx].value);
2511 		if (bmcr.bits.speed_1000_sel) {
2512 			statsp->mac_stats.link_speed = 1000;
2513 			gcr.value = 0;
2514 			gcr.bits.ms_mode_en =
2515 				param_arr[param_master_cfg_enable].value;
2516 			gcr.bits.master =
2517 				param_arr[param_master_cfg_value].value;
2518 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
2519 #if defined(__i386)
2520 				(uint8_t)(uint32_t)(&mii_regs->gcr),
2521 #else
2522 				(uint8_t)(uint64_t)(&mii_regs->gcr),
2523 #endif
2524 				gcr.value))
2525 				!= NXGE_OK)
2526 				goto fail;
2527 			if (param_arr[param_anar_1000fdx].value) {
2528 				bmcr.bits.duplex_mode = 1;
2529 				statsp->mac_stats.link_duplex = 2;
2530 			} else
2531 				statsp->mac_stats.link_duplex = 1;
2532 		} else if (bmcr.bits.speed_sel) {
2533 			statsp->mac_stats.link_speed = 100;
2534 			if (param_arr[param_anar_100fdx].value) {
2535 				bmcr.bits.duplex_mode = 1;
2536 				statsp->mac_stats.link_duplex = 2;
2537 			} else
2538 				statsp->mac_stats.link_duplex = 1;
2539 		} else {
2540 			statsp->mac_stats.link_speed = 10;
2541 			if (param_arr[param_anar_10fdx].value) {
2542 				bmcr.bits.duplex_mode = 1;
2543 				statsp->mac_stats.link_duplex = 2;
2544 			} else
2545 				statsp->mac_stats.link_duplex = 1;
2546 		}
2547 		if (statsp->mac_stats.link_duplex != 1) {
2548 			statsp->mac_stats.link_asmpause =
2549 						statsp->mac_stats.cap_asmpause;
2550 			statsp->mac_stats.link_pause =
2551 						statsp->mac_stats.cap_pause;
2552 		}
2553 
2554 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
2555 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
2556 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
2557 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
2558 				/* BCM5464R 1000mbps external loopback mode */
2559 				gcr.value = 0;
2560 				gcr.bits.ms_mode_en = 1;
2561 				gcr.bits.master = 1;
2562 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
2563 #if defined(__i386)
2564 					(uint8_t)(uint32_t)(&mii_regs->gcr),
2565 #else
2566 					(uint8_t)(uint64_t)(&mii_regs->gcr),
2567 #endif
2568 					gcr.value))
2569 					!= NXGE_OK)
2570 					goto fail;
2571 				bmcr.value = 0;
2572 				bmcr.bits.speed_1000_sel = 1;
2573 				statsp->mac_stats.link_speed = 1000;
2574 			} else if (statsp->port_stats.lb_mode
2575 			    == nxge_lb_ext100) {
2576 				/* BCM5464R 100mbps external loopback mode */
2577 				bmcr.value = 0;
2578 				bmcr.bits.speed_sel = 1;
2579 				bmcr.bits.duplex_mode = 1;
2580 				statsp->mac_stats.link_speed = 100;
2581 			} else if (statsp->port_stats.lb_mode
2582 			    == nxge_lb_ext10) {
2583 				/* BCM5464R 10mbps external loopback mode */
2584 				bmcr.value = 0;
2585 				bmcr.bits.duplex_mode = 1;
2586 				statsp->mac_stats.link_speed = 10;
2587 			}
2588 		}
2589 	}
2590 
2591 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
2592 #if defined(__i386)
2593 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
2594 #else
2595 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
2596 #endif
2597 			bmcr.value)) != NXGE_OK)
2598 		goto fail;
2599 
2600 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2601 #if defined(__i386)
2602 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
2603 #else
2604 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
2605 #endif
2606 		goto fail;
2607 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
2608 
2609 	/*
2610 	 * Initialize the xcvr status kept in the context structure.
2611 	 */
2612 	nxgep->soft_bmsr.value = 0;
2613 
2614 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
2615 #if defined(__i386)
2616 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
2617 #else
2618 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
2619 #endif
2620 			&nxgep->bmsr.value)) != NXGE_OK)
2621 		goto fail;
2622 
2623 	statsp->mac_stats.xcvr_inits++;
2624 	nxgep->bmsr.value = 0;
2625 
2626 fail:
2627 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2628 			"<== nxge_mii_xcvr_init status 0x%x", status));
2629 	return (status);
2630 }
2631 
2632 /* Read from a MII compliant register */
2633 
2634 nxge_status_t
2635 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
2636 		uint16_t *value)
2637 {
2638 	npi_status_t rs = NPI_SUCCESS;
2639 
2640 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
2641 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
2642 
2643 	MUTEX_ENTER(&nxge_mii_lock);
2644 
2645 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
2646 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
2647 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2648 			goto fail;
2649 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
2650 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
2651 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
2652 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2653 			goto fail;
2654 	} else
2655 		goto fail;
2656 
2657 	MUTEX_EXIT(&nxge_mii_lock);
2658 
2659 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
2660 			"xcvr_reg<%d> value=0x%x",
2661 			xcvr_portn, xcvr_reg, *value));
2662 	return (NXGE_OK);
2663 fail:
2664 	MUTEX_EXIT(&nxge_mii_lock);
2665 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2666 			"nxge_mii_read: Failed to read mii on xcvr %d",
2667 			xcvr_portn));
2668 
2669 	return (NXGE_ERROR | rs);
2670 }
2671 
2672 /* Write to a MII compliant Register */
2673 
2674 nxge_status_t
2675 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
2676 		uint16_t value)
2677 {
2678 	npi_status_t rs = NPI_SUCCESS;
2679 
2680 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
2681 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
2682 			value));
2683 
2684 	MUTEX_ENTER(&nxge_mii_lock);
2685 
2686 	if (nxgep->mac.portmode == PORT_1G_COPPER) {
2687 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
2688 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2689 			goto fail;
2690 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
2691 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
2692 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
2693 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
2694 			goto fail;
2695 	} else
2696 		goto fail;
2697 
2698 	MUTEX_EXIT(&nxge_mii_lock);
2699 
2700 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
2701 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
2702 	return (NXGE_OK);
2703 fail:
2704 	MUTEX_EXIT(&nxge_mii_lock);
2705 
2706 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2707 			"nxge_mii_write: Failed to write mii on xcvr %d",
2708 			xcvr_portn));
2709 
2710 	return (NXGE_ERROR | rs);
2711 }
2712 
2713 /* Perform read from Clause45 serdes / transceiver device */
2714 
2715 nxge_status_t
2716 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
2717 		uint16_t xcvr_reg, uint16_t *value)
2718 {
2719 	npi_status_t rs = NPI_SUCCESS;
2720 
2721 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
2722 			xcvr_portn));
2723 
2724 	MUTEX_ENTER(&nxge_mdio_lock);
2725 
2726 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
2727 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
2728 		goto fail;
2729 
2730 	MUTEX_EXIT(&nxge_mdio_lock);
2731 
2732 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
2733 			xcvr_portn));
2734 	return (NXGE_OK);
2735 fail:
2736 	MUTEX_EXIT(&nxge_mdio_lock);
2737 
2738 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2739 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
2740 			xcvr_portn));
2741 
2742 	return (NXGE_ERROR | rs);
2743 }
2744 
2745 /* Perform write to Clause45 serdes / transceiver device */
2746 
2747 nxge_status_t
2748 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
2749 		uint16_t xcvr_reg, uint16_t value)
2750 {
2751 	npi_status_t rs = NPI_SUCCESS;
2752 
2753 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
2754 			xcvr_portn));
2755 
2756 	MUTEX_ENTER(&nxge_mdio_lock);
2757 
2758 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
2759 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
2760 		goto fail;
2761 
2762 	MUTEX_EXIT(&nxge_mdio_lock);
2763 
2764 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
2765 			xcvr_portn));
2766 	return (NXGE_OK);
2767 fail:
2768 	MUTEX_EXIT(&nxge_mdio_lock);
2769 
2770 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2771 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
2772 			xcvr_portn));
2773 
2774 	return (NXGE_ERROR | rs);
2775 }
2776 
2777 
2778 /* Check MII to see if there is any link status change */
2779 
2780 nxge_status_t
2781 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
2782 		nxge_link_state_t *link_up)
2783 {
2784 	p_nxge_param_t	param_arr;
2785 	p_nxge_stats_t	statsp;
2786 	p_mii_regs_t	mii_regs;
2787 	p_mii_bmsr_t	soft_bmsr;
2788 	mii_anar_t	anar;
2789 	mii_anlpar_t	anlpar;
2790 	mii_anar_t	an_common;
2791 	mii_aner_t	aner;
2792 	mii_gsr_t	gsr;
2793 	nxge_status_t	status = NXGE_OK;
2794 
2795 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
2796 
2797 	mii_regs = NULL;
2798 	param_arr = nxgep->param_arr;
2799 	statsp = nxgep->statsp;
2800 	soft_bmsr = &nxgep->soft_bmsr;
2801 	*link_up = LINK_NO_CHANGE;
2802 
2803 	if (bmsr_ints.bits.link_status) {
2804 		if (bmsr.bits.link_status) {
2805 			soft_bmsr->bits.link_status = 1;
2806 		} else {
2807 			statsp->mac_stats.link_up = 0;
2808 			soft_bmsr->bits.link_status = 0;
2809 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2810 					"Link down cable problem"));
2811 			*link_up = LINK_IS_DOWN;
2812 		}
2813 	}
2814 
2815 	if (param_arr[param_autoneg].value) {
2816 		if (bmsr_ints.bits.auto_neg_complete) {
2817 			if (bmsr.bits.auto_neg_complete)
2818 				soft_bmsr->bits.auto_neg_complete = 1;
2819 			else
2820 				soft_bmsr->bits.auto_neg_complete = 0;
2821 		}
2822 		if (soft_bmsr->bits.link_status == 0) {
2823 			statsp->mac_stats.link_T4 = 0;
2824 			statsp->mac_stats.link_speed = 0;
2825 			statsp->mac_stats.link_duplex = 0;
2826 			statsp->mac_stats.link_asmpause = 0;
2827 			statsp->mac_stats.link_pause = 0;
2828 			statsp->mac_stats.lp_cap_autoneg = 0;
2829 			statsp->mac_stats.lp_cap_100T4 = 0;
2830 			statsp->mac_stats.lp_cap_1000fdx = 0;
2831 			statsp->mac_stats.lp_cap_1000hdx = 0;
2832 			statsp->mac_stats.lp_cap_100fdx = 0;
2833 			statsp->mac_stats.lp_cap_100hdx = 0;
2834 			statsp->mac_stats.lp_cap_10fdx = 0;
2835 			statsp->mac_stats.lp_cap_10hdx = 0;
2836 			statsp->mac_stats.lp_cap_10gfdx = 0;
2837 			statsp->mac_stats.lp_cap_10ghdx = 0;
2838 			statsp->mac_stats.lp_cap_asmpause = 0;
2839 			statsp->mac_stats.lp_cap_pause = 0;
2840 		}
2841 	} else
2842 		soft_bmsr->bits.auto_neg_complete = 1;
2843 
2844 	if ((bmsr_ints.bits.link_status ||
2845 		bmsr_ints.bits.auto_neg_complete) &&
2846 		soft_bmsr->bits.link_status &&
2847 		soft_bmsr->bits.auto_neg_complete) {
2848 		statsp->mac_stats.link_up = 1;
2849 		if (param_arr[param_autoneg].value) {
2850 			if ((status = nxge_mii_read(nxgep,
2851 				statsp->mac_stats.xcvr_portn,
2852 #if defined(__i386)
2853 				(uint8_t)(uint32_t)(&mii_regs->anar),
2854 #else
2855 				(uint8_t)(uint64_t)(&mii_regs->anar),
2856 #endif
2857 					&anar.value)) != NXGE_OK)
2858 				goto fail;
2859 			if ((status = nxge_mii_read(nxgep,
2860 				statsp->mac_stats.xcvr_portn,
2861 #if defined(__i386)
2862 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
2863 #else
2864 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
2865 #endif
2866 					&anlpar.value)) != NXGE_OK)
2867 				goto fail;
2868 			if ((status = nxge_mii_read(nxgep,
2869 				statsp->mac_stats.xcvr_portn,
2870 #if defined(__i386)
2871 				(uint8_t)(uint32_t)(&mii_regs->aner),
2872 #else
2873 				(uint8_t)(uint64_t)(&mii_regs->aner),
2874 #endif
2875 					&aner.value)) != NXGE_OK)
2876 				goto fail;
2877 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
2878 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
2879 			statsp->mac_stats.lp_cap_100fdx =
2880 							anlpar.bits.cap_100fdx;
2881 			statsp->mac_stats.lp_cap_100hdx =
2882 							anlpar.bits.cap_100hdx;
2883 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
2884 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
2885 			statsp->mac_stats.lp_cap_asmpause =
2886 						anlpar.bits.cap_asmpause;
2887 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
2888 			an_common.value = anar.value & anlpar.value;
2889 			if (param_arr[param_anar_1000fdx].value ||
2890 				param_arr[param_anar_1000hdx].value) {
2891 				if ((status = nxge_mii_read(nxgep,
2892 					statsp->mac_stats.xcvr_portn,
2893 #if defined(__i386)
2894 					(uint8_t)(uint32_t)(&mii_regs->gsr),
2895 #else
2896 					(uint8_t)(uint64_t)(&mii_regs->gsr),
2897 #endif
2898 						&gsr.value))
2899 						!= NXGE_OK)
2900 					goto fail;
2901 				statsp->mac_stats.lp_cap_1000fdx =
2902 					gsr.bits.link_1000fdx;
2903 				statsp->mac_stats.lp_cap_1000hdx =
2904 					gsr.bits.link_1000hdx;
2905 				if (param_arr[param_anar_1000fdx].value &&
2906 					gsr.bits.link_1000fdx) {
2907 					statsp->mac_stats.link_speed = 1000;
2908 					statsp->mac_stats.link_duplex = 2;
2909 				} else if (
2910 					param_arr[param_anar_1000hdx].value &&
2911 						gsr.bits.link_1000hdx) {
2912 					statsp->mac_stats.link_speed = 1000;
2913 					statsp->mac_stats.link_duplex = 1;
2914 				}
2915 			}
2916 			if ((an_common.value != 0) &&
2917 					!(statsp->mac_stats.link_speed)) {
2918 				if (an_common.bits.cap_100T4) {
2919 					statsp->mac_stats.link_T4 = 1;
2920 					statsp->mac_stats.link_speed = 100;
2921 					statsp->mac_stats.link_duplex = 1;
2922 				} else if (an_common.bits.cap_100fdx) {
2923 					statsp->mac_stats.link_speed = 100;
2924 					statsp->mac_stats.link_duplex = 2;
2925 				} else if (an_common.bits.cap_100hdx) {
2926 					statsp->mac_stats.link_speed = 100;
2927 					statsp->mac_stats.link_duplex = 1;
2928 				} else if (an_common.bits.cap_10fdx) {
2929 					statsp->mac_stats.link_speed = 10;
2930 					statsp->mac_stats.link_duplex = 2;
2931 				} else if (an_common.bits.cap_10hdx) {
2932 					statsp->mac_stats.link_speed = 10;
2933 					statsp->mac_stats.link_duplex = 1;
2934 				} else {
2935 					goto fail;
2936 				}
2937 			}
2938 			if (statsp->mac_stats.link_duplex != 1) {
2939 				statsp->mac_stats.link_asmpause =
2940 					an_common.bits.cap_asmpause;
2941 				if (statsp->mac_stats.link_asmpause)
2942 				if ((statsp->mac_stats.cap_pause == 0) &&
2943 						(statsp->mac_stats.lp_cap_pause
2944 						== 1))
2945 						statsp->mac_stats.link_pause
2946 						= 0;
2947 					else
2948 						statsp->mac_stats.link_pause
2949 						= 1;
2950 				else
2951 					statsp->mac_stats.link_pause =
2952 						an_common.bits.cap_pause;
2953 			}
2954 		}
2955 		*link_up = LINK_IS_UP;
2956 	}
2957 
2958 	if (nxgep->link_notify) {
2959 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
2960 				LINK_IS_DOWN);
2961 		nxgep->link_notify = B_FALSE;
2962 	}
2963 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
2964 	return (NXGE_OK);
2965 fail:
2966 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2967 			"nxge_mii_check: Unable to check MII"));
2968 	return (status);
2969 }
2970 
2971 /* Check PCS to see if there is any link status change */
2972 nxge_status_t
2973 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
2974 {
2975 	p_nxge_stats_t	statsp;
2976 	nxge_status_t	status = NXGE_OK;
2977 	boolean_t	linkup;
2978 
2979 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
2980 
2981 	statsp = nxgep->statsp;
2982 	*link_up = LINK_NO_CHANGE;
2983 
2984 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
2985 	if (linkup) {
2986 		if (nxgep->link_notify ||
2987 		    nxgep->statsp->mac_stats.link_up == 0) {
2988 			statsp->mac_stats.link_up = 1;
2989 			statsp->mac_stats.link_speed = 1000;
2990 			statsp->mac_stats.link_duplex = 2;
2991 			*link_up = LINK_IS_UP;
2992 			nxgep->link_notify = B_FALSE;
2993 		}
2994 	} else {
2995 		if (nxgep->link_notify ||
2996 		    nxgep->statsp->mac_stats.link_up == 1) {
2997 			statsp->mac_stats.link_up = 0;
2998 			statsp->mac_stats.link_speed = 0;
2999 			statsp->mac_stats.link_duplex = 0;
3000 			*link_up = LINK_IS_DOWN;
3001 			nxgep->link_notify = B_FALSE;
3002 		}
3003 	}
3004 
3005 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
3006 	return (NXGE_OK);
3007 fail:
3008 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3009 	    "nxge_pcs_check: Unable to check PCS"));
3010 	return (status);
3011 }
3012 
3013 /* Add a multicast address entry into the HW hash table */
3014 
3015 nxge_status_t
3016 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
3017 {
3018 	uint32_t mchash;
3019 	p_hash_filter_t hash_filter;
3020 	uint16_t hash_bit;
3021 	boolean_t rx_init = B_FALSE;
3022 	uint_t j;
3023 	nxge_status_t status = NXGE_OK;
3024 
3025 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
3026 
3027 	RW_ENTER_WRITER(&nxgep->filter_lock);
3028 	mchash = crc32_mchash(addrp);
3029 	if (nxgep->hash_filter == NULL) {
3030 		NXGE_DEBUG_MSG((NULL, STR_CTL,
3031 			"Allocating hash filter storage."));
3032 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
3033 					KM_SLEEP);
3034 	}
3035 	hash_filter = nxgep->hash_filter;
3036 	j = mchash / HASH_REG_WIDTH;
3037 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
3038 	hash_filter->hash_filter_regs[j] |= hash_bit;
3039 	hash_filter->hash_bit_ref_cnt[mchash]++;
3040 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
3041 		hash_filter->hash_ref_cnt++;
3042 		rx_init = B_TRUE;
3043 	}
3044 	if (rx_init) {
3045 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
3046 			goto fail;
3047 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
3048 			goto fail;
3049 	}
3050 
3051 	RW_EXIT(&nxgep->filter_lock);
3052 
3053 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
3054 
3055 	return (NXGE_OK);
3056 fail:
3057 	RW_EXIT(&nxgep->filter_lock);
3058 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
3059 					"Unable to add multicast address"));
3060 	return (status);
3061 }
3062 
3063 /* Remove a multicast address entry from the HW hash table */
3064 
3065 nxge_status_t
3066 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
3067 {
3068 	uint32_t mchash;
3069 	p_hash_filter_t hash_filter;
3070 	uint16_t hash_bit;
3071 	boolean_t rx_init = B_FALSE;
3072 	uint_t j;
3073 	nxge_status_t status = NXGE_OK;
3074 
3075 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
3076 	RW_ENTER_WRITER(&nxgep->filter_lock);
3077 	mchash = crc32_mchash(addrp);
3078 	if (nxgep->hash_filter == NULL) {
3079 		NXGE_DEBUG_MSG((NULL, STR_CTL,
3080 			"Hash filter already de_allocated."));
3081 		RW_EXIT(&nxgep->filter_lock);
3082 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
3083 		return (NXGE_OK);
3084 	}
3085 	hash_filter = nxgep->hash_filter;
3086 	hash_filter->hash_bit_ref_cnt[mchash]--;
3087 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
3088 		j = mchash / HASH_REG_WIDTH;
3089 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
3090 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
3091 		hash_filter->hash_ref_cnt--;
3092 		rx_init = B_TRUE;
3093 	}
3094 	if (hash_filter->hash_ref_cnt == 0) {
3095 		NXGE_DEBUG_MSG((NULL, STR_CTL,
3096 			"De-allocating hash filter storage."));
3097 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
3098 		nxgep->hash_filter = NULL;
3099 	}
3100 
3101 	if (rx_init) {
3102 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
3103 			goto fail;
3104 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
3105 			goto fail;
3106 	}
3107 	RW_EXIT(&nxgep->filter_lock);
3108 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
3109 
3110 	return (NXGE_OK);
3111 fail:
3112 	RW_EXIT(&nxgep->filter_lock);
3113 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
3114 			"Unable to remove multicast address"));
3115 
3116 	return (status);
3117 }
3118 
3119 /* Set MAC address into MAC address HW registers */
3120 
3121 nxge_status_t
3122 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
3123 {
3124 	nxge_status_t status = NXGE_OK;
3125 
3126 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
3127 
3128 	MUTEX_ENTER(&nxgep->ouraddr_lock);
3129 	/*
3130 	 * Exit if the address is same as ouraddr or multicast or broadcast
3131 	 */
3132 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
3133 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
3134 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
3135 		goto nxge_set_mac_addr_exit;
3136 	}
3137 	nxgep->ouraddr = *addrp;
3138 	/*
3139 	 * Set new interface local address and re-init device.
3140 	 * This is destructive to any other streams attached
3141 	 * to this device.
3142 	 */
3143 	RW_ENTER_WRITER(&nxgep->filter_lock);
3144 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
3145 		goto fail;
3146 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
3147 		goto fail;
3148 
3149 	RW_EXIT(&nxgep->filter_lock);
3150 	MUTEX_EXIT(&nxgep->ouraddr_lock);
3151 	goto nxge_set_mac_addr_end;
3152 nxge_set_mac_addr_exit:
3153 	MUTEX_EXIT(&nxgep->ouraddr_lock);
3154 nxge_set_mac_addr_end:
3155 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
3156 
3157 	return (NXGE_OK);
3158 fail:
3159 	MUTEX_EXIT(&nxgep->ouraddr_lock);
3160 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
3161 			"Unable to set mac address"));
3162 	return (status);
3163 }
3164 
3165 static
3166 check_link_state_t
3167 nxge_check_link_stop(
3168 	nxge_t *nxge)
3169 {
3170 	/* If the poll has been cancelled, return STOP. */
3171 	MUTEX_ENTER(&nxge->poll_lock);
3172 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
3173 		nxge->poll_state = LINK_MONITOR_STOP;
3174 		nxge->nxge_link_poll_timerid = 0;
3175 		cv_broadcast(&nxge->poll_cv);
3176 		MUTEX_EXIT(&nxge->poll_lock);
3177 
3178 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
3179 		    "nxge_check_%s_link(port<%d>) stopped.",
3180 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
3181 		    nxge->mac.portnum));
3182 		return (CHECK_LINK_STOP);
3183 	}
3184 	MUTEX_EXIT(&nxge->poll_lock);
3185 
3186 	return (CHECK_LINK_RESCHEDULE);
3187 }
3188 
3189 /* Check status of MII (MIF or PCS) link */
3190 
3191 static nxge_status_t
3192 nxge_check_mii_link(p_nxge_t nxgep)
3193 {
3194 	mii_bmsr_t bmsr_ints, bmsr_data;
3195 	mii_anlpar_t anlpar;
3196 	mii_gsr_t gsr;
3197 	p_mii_regs_t mii_regs;
3198 	nxge_status_t status = NXGE_OK;
3199 	uint8_t portn;
3200 	nxge_link_state_t link_up;
3201 
3202 	if (nxgep->nxge_magic != NXGE_MAGIC)
3203 		return (NXGE_ERROR);
3204 
3205 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
3206 		return (NXGE_OK);
3207 
3208 	portn = nxgep->mac.portnum;
3209 
3210 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
3211 	    portn));
3212 
3213 	mii_regs = NULL;
3214 
3215 	RW_ENTER_WRITER(&nxgep->filter_lock);
3216 
3217 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
3218 		goto nxge_check_mii_link_exit;
3219 
3220 	switch (nxgep->mac.portmode) {
3221 	default:
3222 		if ((status = nxge_mii_read(nxgep,
3223 		    nxgep->statsp->mac_stats.xcvr_portn,
3224 #if defined(__i386)
3225 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3226 #else
3227 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3228 #endif
3229 		    &bmsr_data.value)) != NXGE_OK) {
3230 			goto fail;
3231 		}
3232 
3233 		if (nxgep->param_arr[param_autoneg].value) {
3234 			if ((status = nxge_mii_read(nxgep,
3235 				nxgep->statsp->mac_stats.xcvr_portn,
3236 #if defined(__i386)
3237 				(uint8_t)(uint32_t)(&mii_regs->gsr),
3238 #else
3239 				(uint8_t)(uint64_t)(&mii_regs->gsr),
3240 #endif
3241 				&gsr.value)) != NXGE_OK)
3242 				goto fail;
3243 			if ((status = nxge_mii_read(nxgep,
3244 				nxgep->statsp->mac_stats.xcvr_portn,
3245 #if defined(__i386)
3246 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
3247 #else
3248 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
3249 #endif
3250 				&anlpar.value)) != NXGE_OK)
3251 				goto fail;
3252 			if (nxgep->statsp->mac_stats.link_up &&
3253 				((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
3254 					gsr.bits.link_1000fdx) ||
3255 				(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
3256 					gsr.bits.link_1000hdx) ||
3257 				(nxgep->statsp->mac_stats.lp_cap_100T4 ^
3258 					anlpar.bits.cap_100T4) ||
3259 				(nxgep->statsp->mac_stats.lp_cap_100fdx ^
3260 					anlpar.bits.cap_100fdx) ||
3261 				(nxgep->statsp->mac_stats.lp_cap_100hdx ^
3262 					anlpar.bits.cap_100hdx) ||
3263 				(nxgep->statsp->mac_stats.lp_cap_10fdx ^
3264 					anlpar.bits.cap_10fdx) ||
3265 				(nxgep->statsp->mac_stats.lp_cap_10hdx ^
3266 					anlpar.bits.cap_10hdx))) {
3267 				bmsr_data.bits.link_status = 0;
3268 			}
3269 		}
3270 
3271 		/* Workaround for link down issue */
3272 		if (bmsr_data.value == 0) {
3273 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
3274 			goto nxge_check_mii_link_exit;
3275 		}
3276 
3277 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
3278 		nxgep->bmsr.value = bmsr_data.value;
3279 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
3280 		    &link_up)) != NXGE_OK) {
3281 			goto fail;
3282 		}
3283 		break;
3284 
3285 	case PORT_1G_SERDES:
3286 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3287 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
3288 		if ((status = nxge_pcs_check(nxgep, portn, &link_up))
3289 		    != NXGE_OK) {
3290 			goto fail;
3291 		}
3292 		break;
3293 	}
3294 
3295 nxge_check_mii_link_exit:
3296 	RW_EXIT(&nxgep->filter_lock);
3297 	if (link_up == LINK_IS_UP) {
3298 		nxge_link_is_up(nxgep);
3299 	} else if (link_up == LINK_IS_DOWN) {
3300 		nxge_link_is_down(nxgep);
3301 	}
3302 
3303 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
3304 
3305 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
3306 				portn));
3307 	return (NXGE_OK);
3308 
3309 fail:
3310 	RW_EXIT(&nxgep->filter_lock);
3311 
3312 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
3313 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3314 			"nxge_check_mii_link: Failed to check link port<%d>",
3315 			portn));
3316 	return (status);
3317 }
3318 
3319 
3320 /*ARGSUSED*/
3321 static nxge_status_t
3322 nxge_check_10g_link(p_nxge_t nxgep)
3323 {
3324 	uint8_t		portn;
3325 	nxge_status_t	status = NXGE_OK;
3326 	boolean_t	link_up;
3327 	boolean_t	xpcs_up, xmac_up;
3328 	uint32_t	val;
3329 	npi_status_t	rs;
3330 
3331 	if (nxgep->nxge_magic != NXGE_MAGIC)
3332 		return (NXGE_ERROR);
3333 
3334 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
3335 		return (NXGE_OK);
3336 
3337 	portn = nxgep->mac.portnum;
3338 
3339 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
3340 	    portn));
3341 
3342 	switch (nxgep->mac.portmode) {
3343 	default:
3344 		status = nxge_check_bcm8704_link(nxgep, &link_up);
3345 		if (status != NXGE_OK)
3346 			goto fail;
3347 		break;
3348 	case PORT_10G_SERDES:
3349 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3350 		    XPCS_REG_STATUS1, &val);
3351 		if (rs != 0)
3352 			goto fail;
3353 
3354 		link_up = B_FALSE;
3355 		xmac_up = B_FALSE;
3356 		xpcs_up = B_FALSE;
3357 		if (val & XPCS_STATUS1_RX_LINK_STATUS_UP) {
3358 			xpcs_up = B_TRUE;
3359 		}
3360 
3361 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3362 		    "==> nxge_check_10g_link port<%d> "
3363 		    "XPCS_REG_STATUS1 0x%x xpcs_up %d",
3364 		    portn, val, xpcs_up));
3365 		/*
3366 		 * Read the xMAC internal signal 2 register.
3367 		 * This register should be the superset of the XPCS when wanting
3368 		 * to get the link status. If this register read is proved to be
3369 		 * reliable, there is no need to read the XPCS register.
3370 		 */
3371 		xmac_up = B_TRUE;
3372 		XMAC_REG_RD(nxgep->npi_handle, portn, XMAC_INTERN2_REG, &val);
3373 		if (val & XMAC_IS2_LOCAL_FLT_OC_SYNC) { /* link is down */
3374 			xmac_up = B_FALSE;
3375 		}
3376 
3377 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3378 		    "==> nxge_check_10g_link port<%d> "
3379 		    "XMAC_INTERN2_REG 0x%x xmac_up %d",
3380 		    portn, val, xmac_up));
3381 
3382 		if (xpcs_up && xmac_up) {
3383 			link_up = B_TRUE;
3384 		}
3385 		break;
3386 	}
3387 
3388 	if (link_up) {
3389 		if (nxgep->link_notify ||
3390 			nxgep->statsp->mac_stats.link_up == 0) {
3391 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
3392 				goto fail;
3393 			nxgep->statsp->mac_stats.link_up = 1;
3394 			nxgep->statsp->mac_stats.link_speed = 10000;
3395 			nxgep->statsp->mac_stats.link_duplex = 2;
3396 
3397 			nxge_link_is_up(nxgep);
3398 			nxgep->link_notify = B_FALSE;
3399 		}
3400 	} else {
3401 		if (nxgep->link_notify ||
3402 			nxgep->statsp->mac_stats.link_up == 1) {
3403 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
3404 				goto fail;
3405 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3406 					"Link down cable problem"));
3407 			nxgep->statsp->mac_stats.link_up = 0;
3408 			nxgep->statsp->mac_stats.link_speed = 0;
3409 			nxgep->statsp->mac_stats.link_duplex = 0;
3410 
3411 			nxge_link_is_down(nxgep);
3412 			nxgep->link_notify = B_FALSE;
3413 		}
3414 	}
3415 
3416 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
3417 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
3418 	    portn));
3419 	return (NXGE_OK);
3420 
3421 fail:
3422 	(void) nxge_check_link_stop(nxgep);
3423 
3424 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3425 	    "nxge_check_10g_link: Failed to check link port<%d>",
3426 	    portn));
3427 	return (status);
3428 }
3429 
3430 
3431 /* Declare link down */
3432 
3433 void
3434 nxge_link_is_down(p_nxge_t nxgep)
3435 {
3436 	p_nxge_stats_t statsp;
3437 	char link_stat_msg[64];
3438 
3439 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
3440 
3441 	statsp = nxgep->statsp;
3442 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
3443 	    statsp->mac_stats.xcvr_portn);
3444 
3445 	if (nxge_no_msg == B_FALSE) {
3446 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
3447 	}
3448 
3449 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
3450 
3451 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
3452 }
3453 
3454 /* Declare link up */
3455 
3456 void
3457 nxge_link_is_up(p_nxge_t nxgep)
3458 {
3459 	p_nxge_stats_t statsp;
3460 	char link_stat_msg[64];
3461 	uint32_t val;
3462 
3463 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
3464 
3465 	statsp = nxgep->statsp;
3466 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
3467 	    statsp->mac_stats.xcvr_portn,
3468 	    statsp->mac_stats.link_speed);
3469 
3470 	if (statsp->mac_stats.link_T4)
3471 		(void) strcat(link_stat_msg, "T4");
3472 	else if (statsp->mac_stats.link_duplex == 2)
3473 		(void) strcat(link_stat_msg, "full duplex");
3474 	else
3475 		(void) strcat(link_stat_msg, "half duplex");
3476 
3477 	(void) nxge_xif_init(nxgep);
3478 
3479 	/* Clean up symbol errors incurred during link transition */
3480 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
3481 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
3482 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3483 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
3484 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3485 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
3486 	}
3487 
3488 	if (nxge_no_msg == B_FALSE) {
3489 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
3490 	}
3491 
3492 	mac_link_update(nxgep->mach, LINK_STATE_UP);
3493 
3494 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
3495 }
3496 
3497 /*
3498  * Calculate the bit in the multicast address filter
3499  * that selects the given * address.
3500  * Note: For GEM, the last 8-bits are used.
3501  */
3502 uint32_t
3503 crc32_mchash(p_ether_addr_t addr)
3504 {
3505 	uint8_t *cp;
3506 	uint32_t crc;
3507 	uint32_t c;
3508 	int byte;
3509 	int bit;
3510 
3511 	cp = (uint8_t *)addr;
3512 	crc = (uint32_t)0xffffffff;
3513 	for (byte = 0; byte < 6; byte++) {
3514 		c = (uint32_t)cp[byte];
3515 		for (bit = 0; bit < 8; bit++) {
3516 			if ((c & 0x1) ^ (crc & 0x1))
3517 				crc = (crc >> 1)^0xedb88320;
3518 			else
3519 				crc = (crc >> 1);
3520 			c >>= 1;
3521 		}
3522 	}
3523 	return ((~crc) >> (32 - HASH_BITS));
3524 }
3525 
3526 /* Reset serdes */
3527 
3528 nxge_status_t
3529 nxge_serdes_reset(p_nxge_t nxgep)
3530 {
3531 	npi_handle_t		handle;
3532 
3533 	handle = nxgep->npi_handle;
3534 
3535 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
3536 	drv_usecwait(500);
3537 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
3538 
3539 	return (NXGE_OK);
3540 }
3541 
3542 /* Monitor link status using interrupt or polling */
3543 
3544 nxge_status_t
3545 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
3546 {
3547 	nxge_status_t status = NXGE_OK;
3548 
3549 	/*
3550 	 * Return immediately if this is an imaginary XMAC port.
3551 	 * (At least, we don't have 4-port XMAC cards yet.)
3552 	 */
3553 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
3554 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
3555 	    (nxgep->mac.portnum > 1))
3556 		return (NXGE_OK);
3557 
3558 	if (nxgep->statsp == NULL) {
3559 		/* stats has not been allocated. */
3560 		return (NXGE_OK);
3561 	}
3562 	/* Don't check link if we're not in internal loopback mode */
3563 	if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal)
3564 		return (NXGE_OK);
3565 
3566 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3567 	    "==> nxge_link_monitor port<%d> enable=%d",
3568 	    nxgep->mac.portnum, enable));
3569 	if (enable == LINK_MONITOR_START) {
3570 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
3571 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
3572 			    != NXGE_OK)
3573 				goto fail;
3574 		} else {
3575 			timeout_id_t timerid;
3576 
3577 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
3578 				return (NXGE_OK);
3579 
3580 			if (nxgep->xcvr.check_link) {
3581 				timerid = timeout(
3582 				    (fptrv_t)(nxgep->xcvr.check_link),
3583 				    nxgep,
3584 				    drv_usectohz(LINK_MONITOR_PERIOD));
3585 				MUTEX_ENTER(&nxgep->poll_lock);
3586 				nxgep->nxge_link_poll_timerid = timerid;
3587 				MUTEX_EXIT(&nxgep->poll_lock);
3588 			} else {
3589 				return (NXGE_ERROR);
3590 			}
3591 		}
3592 	} else {
3593 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
3594 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
3595 			    != NXGE_OK)
3596 				goto fail;
3597 		} else {
3598 			clock_t rv;
3599 
3600 			MUTEX_ENTER(&nxgep->poll_lock);
3601 
3602 			/* If <timerid> == 0, the link monitor has */
3603 			/* never been started, or just now stopped. */
3604 			if (nxgep->nxge_link_poll_timerid == 0) {
3605 				MUTEX_EXIT(&nxgep->poll_lock);
3606 				return (NXGE_OK);
3607 			}
3608 
3609 			nxgep->poll_state = LINK_MONITOR_STOPPING;
3610 			rv = cv_timedwait(&nxgep->poll_cv,
3611 			    &nxgep->poll_lock,
3612 			    ddi_get_lbolt() +
3613 			    drv_usectohz(LM_WAIT_MULTIPLIER *
3614 			    LINK_MONITOR_PERIOD));
3615 			if (rv == -1) {
3616 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3617 				    "==> stopping port %d: "
3618 				    "cv_timedwait(%d) timed out",
3619 				    nxgep->mac.portnum, nxgep->poll_state));
3620 				nxgep->poll_state = LINK_MONITOR_STOP;
3621 				nxgep->nxge_link_poll_timerid = 0;
3622 			}
3623 
3624 			MUTEX_EXIT(&nxgep->poll_lock);
3625 		}
3626 	}
3627 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3628 	    "<== nxge_link_monitor port<%d> enable=%d",
3629 	    nxgep->mac.portnum, enable));
3630 	return (NXGE_OK);
3631 fail:
3632 	return (status);
3633 }
3634 
3635 /* Set promiscous mode */
3636 
3637 nxge_status_t
3638 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
3639 {
3640 	nxge_status_t status = NXGE_OK;
3641 
3642 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
3643 
3644 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
3645 
3646 	RW_ENTER_WRITER(&nxgep->filter_lock);
3647 
3648 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
3649 		goto fail;
3650 	}
3651 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
3652 		goto fail;
3653 	}
3654 
3655 	RW_EXIT(&nxgep->filter_lock);
3656 
3657 	if (on)
3658 		nxgep->statsp->mac_stats.promisc = B_TRUE;
3659 	else
3660 		nxgep->statsp->mac_stats.promisc = B_FALSE;
3661 
3662 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
3663 
3664 	return (NXGE_OK);
3665 fail:
3666 	RW_EXIT(&nxgep->filter_lock);
3667 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
3668 	    "Unable to set promisc (%d)", on));
3669 
3670 	return (status);
3671 }
3672 
3673 /*ARGSUSED*/
3674 uint_t
3675 nxge_mif_intr(void *arg1, void *arg2)
3676 {
3677 #ifdef	NXGE_DEBUG
3678 	p_nxge_t		nxgep = (p_nxge_t)arg2;
3679 #endif
3680 #if NXGE_MIF
3681 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
3682 	uint32_t		status;
3683 	npi_handle_t		handle;
3684 	uint8_t			portn;
3685 	p_nxge_stats_t		statsp;
3686 #endif
3687 
3688 #ifdef	NXGE_MIF
3689 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
3690 		nxgep = ldvp->nxgep;
3691 	}
3692 	nxgep = ldvp->nxgep;
3693 #endif
3694 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
3695 
3696 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
3697 	return (DDI_INTR_CLAIMED);
3698 
3699 mif_intr_fail:
3700 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
3701 	return (DDI_INTR_UNCLAIMED);
3702 }
3703 
3704 /*ARGSUSED*/
3705 uint_t
3706 nxge_mac_intr(void *arg1, void *arg2)
3707 {
3708 	p_nxge_t		nxgep = (p_nxge_t)arg2;
3709 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
3710 	p_nxge_ldg_t		ldgp;
3711 	uint32_t		status;
3712 	npi_handle_t		handle;
3713 	uint8_t			portn;
3714 	p_nxge_stats_t		statsp;
3715 	npi_status_t		rs = NPI_SUCCESS;
3716 
3717 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
3718 		nxgep = ldvp->nxgep;
3719 	}
3720 
3721 	ldgp = ldvp->ldgp;
3722 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
3723 	    "group %d", ldgp->ldg));
3724 
3725 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3726 	/*
3727 	 * This interrupt handler is for a specific
3728 	 * mac port.
3729 	 */
3730 	statsp = (p_nxge_stats_t)nxgep->statsp;
3731 	portn = nxgep->mac.portnum;
3732 
3733 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
3734 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
3735 
3736 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
3737 		rs = npi_xmac_tx_get_istatus(handle, portn,
3738 					(xmac_tx_iconfig_t *)&status);
3739 		if (rs != NPI_SUCCESS)
3740 			goto npi_fail;
3741 		if (status & ICFG_XMAC_TX_ALL) {
3742 			if (status & ICFG_XMAC_TX_UNDERRUN) {
3743 				statsp->xmac_stats.tx_underflow_err++;
3744 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3745 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
3746 			}
3747 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
3748 				statsp->xmac_stats.tx_maxpktsize_err++;
3749 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3750 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
3751 			}
3752 			if (status & ICFG_XMAC_TX_OVERFLOW) {
3753 				statsp->xmac_stats.tx_overflow_err++;
3754 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3755 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
3756 			}
3757 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
3758 				statsp->xmac_stats.tx_fifo_xfr_err++;
3759 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3760 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
3761 			}
3762 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
3763 				statsp->xmac_stats.tx_byte_cnt +=
3764 							XTXMAC_BYTE_CNT_MASK;
3765 			}
3766 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
3767 				statsp->xmac_stats.tx_frame_cnt +=
3768 							XTXMAC_FRM_CNT_MASK;
3769 			}
3770 		}
3771 
3772 		rs = npi_xmac_rx_get_istatus(handle, portn,
3773 					(xmac_rx_iconfig_t *)&status);
3774 		if (rs != NPI_SUCCESS)
3775 			goto npi_fail;
3776 		if (status & ICFG_XMAC_RX_ALL) {
3777 			if (status & ICFG_XMAC_RX_OVERFLOW)
3778 				statsp->xmac_stats.rx_overflow_err++;
3779 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
3780 				statsp->xmac_stats.rx_underflow_err++;
3781 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3782 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
3783 			}
3784 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
3785 				statsp->xmac_stats.rx_crc_err_cnt +=
3786 							XRXMAC_CRC_ER_CNT_MASK;
3787 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3788 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
3789 			}
3790 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
3791 				statsp->xmac_stats.rx_len_err_cnt +=
3792 							MAC_LEN_ER_CNT_MASK;
3793 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3794 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
3795 			}
3796 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
3797 				statsp->xmac_stats.rx_viol_err_cnt +=
3798 							XRXMAC_CD_VIO_CNT_MASK;
3799 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3800 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
3801 			}
3802 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
3803 				statsp->xmac_stats.rx_byte_cnt +=
3804 							XRXMAC_BT_CNT_MASK;
3805 			}
3806 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
3807 				statsp->xmac_stats.rx_hist1_cnt +=
3808 							XRXMAC_HIST_CNT1_MASK;
3809 			}
3810 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
3811 				statsp->xmac_stats.rx_hist2_cnt +=
3812 							XRXMAC_HIST_CNT2_MASK;
3813 			}
3814 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
3815 				statsp->xmac_stats.rx_hist3_cnt +=
3816 							XRXMAC_HIST_CNT3_MASK;
3817 			}
3818 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
3819 				statsp->xmac_stats.rx_hist4_cnt +=
3820 							XRXMAC_HIST_CNT4_MASK;
3821 			}
3822 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
3823 				statsp->xmac_stats.rx_hist5_cnt +=
3824 							XRXMAC_HIST_CNT5_MASK;
3825 			}
3826 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
3827 				statsp->xmac_stats.rx_hist6_cnt +=
3828 							XRXMAC_HIST_CNT6_MASK;
3829 			}
3830 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
3831 				statsp->xmac_stats.rx_broadcast_cnt +=
3832 							XRXMAC_BC_FRM_CNT_MASK;
3833 			}
3834 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
3835 				statsp->xmac_stats.rx_mult_cnt +=
3836 							XRXMAC_MC_FRM_CNT_MASK;
3837 			}
3838 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
3839 				statsp->xmac_stats.rx_frag_cnt +=
3840 							XRXMAC_FRAG_CNT_MASK;
3841 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3842 					NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP);
3843 			}
3844 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
3845 				statsp->xmac_stats.rx_frame_align_err_cnt +=
3846 							XRXMAC_AL_ER_CNT_MASK;
3847 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3848 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
3849 			}
3850 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
3851 				statsp->xmac_stats.rx_linkfault_err_cnt +=
3852 							XMAC_LINK_FLT_CNT_MASK;
3853 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3854 				NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP);
3855 			}
3856 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
3857 				statsp->xmac_stats.rx_remotefault_err++;
3858 			}
3859 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
3860 				statsp->xmac_stats.rx_localfault_err++;
3861 			}
3862 		}
3863 
3864 		rs = npi_xmac_ctl_get_istatus(handle, portn,
3865 						(xmac_ctl_iconfig_t *)&status);
3866 		if (rs != NPI_SUCCESS)
3867 			goto npi_fail;
3868 		if (status & ICFG_XMAC_CTRL_ALL) {
3869 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
3870 				statsp->xmac_stats.rx_pause_cnt++;
3871 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
3872 				statsp->xmac_stats.tx_pause_state++;
3873 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
3874 				statsp->xmac_stats.tx_nopause_state++;
3875 		}
3876 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
3877 		rs = npi_bmac_tx_get_istatus(handle, portn,
3878 						(bmac_tx_iconfig_t *)&status);
3879 		if (rs != NPI_SUCCESS)
3880 			goto npi_fail;
3881 		if (status & ICFG_BMAC_TX_ALL) {
3882 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
3883 				statsp->bmac_stats.tx_underrun_err++;
3884 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3885 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
3886 			}
3887 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
3888 				statsp->bmac_stats.tx_max_pkt_err++;
3889 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3890 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
3891 			}
3892 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
3893 				statsp->bmac_stats.tx_byte_cnt +=
3894 							BTXMAC_BYTE_CNT_MASK;
3895 			}
3896 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
3897 				statsp->bmac_stats.tx_frame_cnt +=
3898 							BTXMAC_FRM_CNT_MASK;
3899 			}
3900 		}
3901 
3902 		rs = npi_bmac_rx_get_istatus(handle, portn,
3903 						(bmac_rx_iconfig_t *)&status);
3904 		if (rs != NPI_SUCCESS)
3905 			goto npi_fail;
3906 		if (status & ICFG_BMAC_RX_ALL) {
3907 			if (status & ICFG_BMAC_RX_OVERFLOW) {
3908 				statsp->bmac_stats.rx_overflow_err++;
3909 			}
3910 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
3911 				statsp->bmac_stats.rx_frame_cnt +=
3912 							RXMAC_FRM_CNT_MASK;
3913 			}
3914 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
3915 				statsp->bmac_stats.rx_crc_err_cnt +=
3916 							BMAC_CRC_ER_CNT_MASK;
3917 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3918 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
3919 			}
3920 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
3921 				statsp->bmac_stats.rx_len_err_cnt +=
3922 							MAC_LEN_ER_CNT_MASK;
3923 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3924 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
3925 			}
3926 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
3927 				statsp->bmac_stats.rx_viol_err_cnt +=
3928 							BMAC_CD_VIO_CNT_MASK;
3929 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3930 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
3931 			}
3932 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
3933 				statsp->bmac_stats.rx_byte_cnt +=
3934 							BRXMAC_BYTE_CNT_MASK;
3935 			}
3936 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
3937 				statsp->bmac_stats.rx_align_err_cnt +=
3938 							BMAC_AL_ER_CNT_MASK;
3939 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
3940 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
3941 			}
3942 
3943 			rs = npi_bmac_ctl_get_istatus(handle, portn,
3944 						(bmac_ctl_iconfig_t *)&status);
3945 			if (rs != NPI_SUCCESS)
3946 				goto npi_fail;
3947 
3948 			if (status & ICFG_BMAC_CTL_ALL) {
3949 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
3950 					statsp->bmac_stats.rx_pause_cnt++;
3951 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
3952 					statsp->bmac_stats.tx_pause_state++;
3953 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
3954 					statsp->bmac_stats.tx_nopause_state++;
3955 			}
3956 		}
3957 
3958 	if (ldgp->nldvs == 1) {
3959 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
3960 			B_TRUE, ldgp->ldg_timer);
3961 	}
3962 
3963 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
3964 	return (DDI_INTR_CLAIMED);
3965 
3966 npi_fail:
3967 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
3968 	return (DDI_INTR_UNCLAIMED);
3969 }
3970 
3971 nxge_status_t
3972 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
3973 {
3974 	uint8_t		phy_port_addr;
3975 	nxge_status_t	status = NXGE_OK;
3976 	boolean_t	rx_sig_ok;
3977 	boolean_t	pcs_blk_lock;
3978 	boolean_t	link_align;
3979 	uint16_t	val1, val2, val3;
3980 #ifdef	NXGE_DEBUG_SYMBOL_ERR
3981 	uint16_t	val_debug;
3982 	uint16_t	val;
3983 #endif
3984 
3985 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
3986 
3987 #ifdef	NXGE_DEBUG_SYMBOL_ERR
3988 	/* Check Device 3 Register Device 3 0xC809 */
3989 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
3990 	if ((val_debug & ~0x200) != 0) {
3991 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
3992 				nxgep->mac.portnum, val_debug);
3993 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
3994 				&val_debug);
3995 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
3996 				nxgep->mac.portnum, val_debug);
3997 	}
3998 
3999 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4000 					XPCS_REG_DESCWERR_COUNTER, &val);
4001 	if (val != 0)
4002 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
4003 
4004 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4005 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
4006 	if (val != 0)
4007 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
4008 
4009 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
4010 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
4011 	if (val != 0)
4012 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
4013 #endif
4014 
4015 	/* Check from BCM8704 if 10G link is up or down */
4016 
4017 	/* Check Device 1 Register 0xA bit0 */
4018 	status = nxge_mdio_read(nxgep, phy_port_addr,
4019 			BCM8704_PMA_PMD_DEV_ADDR,
4020 			BCM8704_PMD_RECEIVE_SIG_DETECT,
4021 			&val1);
4022 	if (status != NXGE_OK)
4023 		goto fail;
4024 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
4025 
4026 	/* Check Device 3 Register 0x20 bit0 */
4027 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
4028 			BCM8704_PCS_DEV_ADDR,
4029 			BCM8704_10GBASE_R_PCS_STATUS_REG,
4030 			&val2)) != NPI_SUCCESS)
4031 		goto fail;
4032 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
4033 
4034 	/* Check Device 4 Register 0x18 bit12 */
4035 	status = nxge_mdio_read(nxgep, phy_port_addr,
4036 			BCM8704_PHYXS_ADDR,
4037 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
4038 			&val3);
4039 	if (status != NXGE_OK)
4040 		goto fail;
4041 	link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
4042 				XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
4043 				XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
4044 
4045 #ifdef	NXGE_DEBUG_ALIGN_ERR
4046 	/* Temp workaround for link down issue */
4047 	if (pcs_blk_lock == B_FALSE) {
4048 		if (val2 != 0x4) {
4049 			pcs_blk_lock = B_TRUE;
4050 			cmn_err(CE_NOTE,
4051 				"!LINK DEBUG: port%d PHY Dev3 "
4052 				"Reg 0x20 = 0x%x\n",
4053 				nxgep->mac.portnum, val2);
4054 		}
4055 	}
4056 
4057 	if (link_align == B_FALSE) {
4058 		if (val3 != 0x140f) {
4059 			link_align = B_TRUE;
4060 			cmn_err(CE_NOTE,
4061 				"!LINK DEBUG: port%d PHY Dev4 "
4062 				"Reg 0x18 = 0x%x\n",
4063 				nxgep->mac.portnum, val3);
4064 		}
4065 	}
4066 
4067 	if (rx_sig_ok == B_FALSE) {
4068 		if ((val2 == 0) || (val3 == 0)) {
4069 			rx_sig_ok = B_TRUE;
4070 			cmn_err(CE_NOTE,
4071 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
4072 				nxgep->mac.portnum);
4073 		}
4074 	}
4075 #endif
4076 
4077 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
4078 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
4079 
4080 	return (NXGE_OK);
4081 fail:
4082 	return (status);
4083 }
4084 
4085 nxge_status_t
4086 nxge_10g_link_led_on(p_nxge_t nxgep)
4087 {
4088 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
4089 	    != NPI_SUCCESS)
4090 		return (NXGE_ERROR);
4091 	else
4092 		return (NXGE_OK);
4093 }
4094 
4095 nxge_status_t
4096 nxge_10g_link_led_off(p_nxge_t nxgep)
4097 {
4098 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
4099 	    != NPI_SUCCESS)
4100 		return (NXGE_ERROR);
4101 	else
4102 		return (NXGE_OK);
4103 }
4104 
4105 /* Check if the given id read using the given MDIO Clause is supported */
4106 
4107 static boolean_t
4108 nxge_is_supported_phy(uint32_t id, uint8_t type)
4109 {
4110 	int		i;
4111 	int		cl45_arr_len = NUM_CLAUSE_45_IDS;
4112 	int		cl22_arr_len = NUM_CLAUSE_22_IDS;
4113 	boolean_t	found = B_FALSE;
4114 
4115 	switch (type) {
4116 	case CLAUSE_45_TYPE:
4117 		for (i = 0; i < cl45_arr_len; i++) {
4118 			if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
4119 			    (id & BCM_PHY_ID_MASK)) {
4120 				found = B_TRUE;
4121 				break;
4122 			}
4123 		}
4124 		break;
4125 	case CLAUSE_22_TYPE:
4126 		for (i = 0; i < cl22_arr_len; i++) {
4127 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
4128 			    (id & BCM_PHY_ID_MASK)) {
4129 				found = B_TRUE;
4130 				break;
4131 			}
4132 		}
4133 		break;
4134 	default:
4135 		break;
4136 	}
4137 
4138 	return (found);
4139 }
4140 
4141 static uint32_t
4142 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
4143 {
4144 	uint16_t	val1 = 0;
4145 	uint16_t	val2 = 0;
4146 	uint32_t	pma_pmd_dev_id = 0;
4147 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
4148 
4149 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
4150 	    NXGE_DEV_ID_REG_1, &val1);
4151 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
4152 	    NXGE_DEV_ID_REG_2, &val2);
4153 
4154 	pma_pmd_dev_id = val1;
4155 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
4156 	pma_pmd_dev_id |= val2;
4157 
4158 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
4159 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
4160 
4161 	return (pma_pmd_dev_id);
4162 }
4163 
4164 static uint32_t
4165 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
4166 {
4167 	uint16_t	val1 = 0;
4168 	uint16_t	val2 = 0;
4169 	uint32_t	pcs_dev_id = 0;
4170 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
4171 
4172 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
4173 	    NXGE_DEV_ID_REG_1, &val1);
4174 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
4175 	    NXGE_DEV_ID_REG_2, &val2);
4176 
4177 	pcs_dev_id = val1;
4178 	pcs_dev_id = (pcs_dev_id << 16);
4179 	pcs_dev_id |= val2;
4180 
4181 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
4182 	    "devid[0x%llx]", phy_port, pcs_dev_id));
4183 
4184 	return (pcs_dev_id);
4185 }
4186 
4187 static uint32_t
4188 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
4189 {
4190 	uint16_t	val1 = 0;
4191 	uint16_t	val2 = 0;
4192 	uint32_t	phy_id = 0;
4193 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
4194 	npi_status_t	npi_status = NPI_SUCCESS;
4195 
4196 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
4197 	    &val1);
4198 	if (npi_status != NPI_SUCCESS) {
4199 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
4200 		    "clause 22 read to reg 2 failed!!!"));
4201 		goto exit;
4202 	}
4203 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
4204 	    &val2);
4205 	if (npi_status != 0) {
4206 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
4207 		    "clause 22 read to reg 3 failed!!!"));
4208 		goto exit;
4209 	}
4210 	phy_id = val1;
4211 	phy_id = (phy_id << 16);
4212 	phy_id |= val2;
4213 
4214 exit:
4215 
4216 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
4217 	    phy_port, phy_id));
4218 
4219 	return (phy_id);
4220 }
4221 
4222 /*
4223  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
4224  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
4225  * read. Then use the values obtained to determine the phy type of each port
4226  * and the Neptune type.
4227  */
4228 
4229 nxge_status_t
4230 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
4231 {
4232 	int		i, j, k, l;
4233 	uint32_t	pma_pmd_dev_id = 0;
4234 	uint32_t	pcs_dev_id = 0;
4235 	uint32_t	phy_id = 0;
4236 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
4237 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
4238 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
4239 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
4240 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
4241 	uint8_t		phy_fd[NXGE_MAX_PHY_PORTS];
4242 	uint8_t		port_fd[NXGE_MAX_PHY_PORTS];
4243 	uint8_t		total_port_fd, total_phy_fd;
4244 	nxge_status_t	status = NXGE_OK;
4245 	int		prt_id = -1;
4246 
4247 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
4248 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4249 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
4250 	    nxgep->niu_type));
4251 
4252 	j = k = l = 0;
4253 	total_port_fd = total_phy_fd = 0;
4254 	/*
4255 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
4256 	 * for on chip serdes usages.
4257 	 */
4258 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
4259 
4260 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
4261 
4262 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
4263 			pma_pmd_dev_fd[i] = 1;
4264 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
4265 			    "PMA/PMD dev found", i));
4266 			if (j < NXGE_PORTS_NEPTUNE) {
4267 				port_pma_pmd_dev_id[j] = pma_pmd_dev_id &
4268 				    BCM_PHY_ID_MASK;
4269 				j++;
4270 			}
4271 		} else {
4272 			pma_pmd_dev_fd[i] = 0;
4273 		}
4274 
4275 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
4276 
4277 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
4278 			pcs_dev_fd[i] = 1;
4279 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
4280 			    "dev found", i));
4281 			if (k < NXGE_PORTS_NEPTUNE) {
4282 				port_pcs_dev_id[k] = pcs_dev_id &
4283 				    BCM_PHY_ID_MASK;
4284 				k++;
4285 			}
4286 		} else {
4287 			pcs_dev_fd[i] = 0;
4288 		}
4289 
4290 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i])
4291 			port_fd[i] = 1;
4292 		else
4293 			port_fd[i] = 0;
4294 		total_port_fd += port_fd[i];
4295 
4296 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
4297 
4298 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
4299 			phy_fd[i] = 1;
4300 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
4301 			    "found", i));
4302 			if (l < NXGE_PORTS_NEPTUNE) {
4303 				port_phy_id[l] = phy_id & BCM_PHY_ID_MASK;
4304 				l++;
4305 			}
4306 		} else {
4307 			phy_fd[i] = 0;
4308 		}
4309 		total_phy_fd += phy_fd[i];
4310 	}
4311 
4312 	switch (total_port_fd) {
4313 	case 2:
4314 		switch (total_phy_fd) {
4315 		case 2:
4316 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4317 			    "Unsupported neptune type 1"));
4318 			goto error_exit;
4319 		case 1:
4320 			/* TODO - 2 10G, 1 1G */
4321 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4322 			    "Unsupported neptune type 2 10G, 1 1G"));
4323 			goto error_exit;
4324 		case 0:
4325 			/* 2 10G */
4326 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
4327 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
4328 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
4329 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) {
4330 
4331 				/*
4332 				 * Check the first phy port address against
4333 				 * the known phy start addresses to determine
4334 				 * the platform type.
4335 				 */
4336 				for (i = NXGE_EXT_PHY_PORT_ST;
4337 				    i < NXGE_MAX_PHY_PORTS; i++) {
4338 					if (port_fd[i] == 1)
4339 						break;
4340 				}
4341 				if (i == BCM8704_NEPTUNE_PORT_ADDR_BASE) {
4342 					hw_p->niu_type = NEPTUNE_2_10GF;
4343 					hw_p->platform_type =
4344 					    P_NEPTUNE_ATLAS_2PORT;
4345 				} else {
4346 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4347 					    "Unsupported neptune type 2 - 1"));
4348 					goto error_exit;
4349 				}
4350 				hw_p->niu_type = NEPTUNE_2_10GF;
4351 			} else {
4352 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4353 				    "Unsupported neptune type 2"));
4354 				goto error_exit;
4355 			}
4356 			break;
4357 		case 4:
4358 			/* Maramba with 2 XAUI */
4359 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
4360 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
4361 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
4362 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
4363 			    ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
4364 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
4365 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
4366 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY))) {
4367 
4368 				/*
4369 				 * Check the first phy port address against
4370 				 * the known phy start addresses to determine
4371 				 * the platform type.
4372 				 */
4373 				for (i = NXGE_EXT_PHY_PORT_ST;
4374 				    i < NXGE_MAX_PHY_PORTS; i++) {
4375 					if (phy_fd[i] == 1)
4376 						break;
4377 				}
4378 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
4379 					hw_p->platform_type =
4380 					    P_NEPTUNE_MARAMBA_P0;
4381 				} else if (i ==
4382 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
4383 					hw_p->platform_type =
4384 					    P_NEPTUNE_MARAMBA_P1;
4385 				} else {
4386 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4387 					    "Unknown port %d...Cannot "
4388 					    "determine platform type", i));
4389 					goto error_exit;
4390 				}
4391 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
4392 
4393 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4394 				    "Maramba with 2 XAUI"));
4395 			} else {
4396 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4397 				    "Unsupported neptune type 3"));
4398 				goto error_exit;
4399 			}
4400 			break;
4401 		default:
4402 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4403 			    "Unsupported neptune type 5"));
4404 			goto error_exit;
4405 		}
4406 		break;
4407 	case 1:
4408 		switch (total_phy_fd) {
4409 		case 3:
4410 			/*
4411 			 * TODO 3 1G, 1 10G mode.
4412 			 * Differentiate between 1_1G_1_10G_2_1G and
4413 			 * 1_10G_3_1G
4414 			 */
4415 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4416 			    "Unsupported neptune type 7"));
4417 			goto error_exit;
4418 		case 2:
4419 			/*
4420 			 * TODO 2 1G, 1 10G mode.
4421 			 * Differentiate between 1_1G_1_10G_1_1G and
4422 			 * 1_10G_2_1G
4423 			 */
4424 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4425 			    "Unsupported neptune type 8"));
4426 			goto error_exit;
4427 		case 1:
4428 			/*
4429 			 * TODO 1 1G, 1 10G mode.
4430 			 * Differentiate between 1_1G_1_10G and
4431 			 * 1_10G_1_1G
4432 			 */
4433 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4434 			    "Unsupported neptune type 9"));
4435 			goto error_exit;
4436 		case 0:
4437 			/* TODO 1 10G mode */
4438 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4439 			    "Unsupported neptune type 10"));
4440 			goto error_exit;
4441 		case 4:
4442 			/* Maramba with 1 XAUI */
4443 			if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
4444 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) {
4445 
4446 				/*
4447 				 * Check the first phy port address against
4448 				 * the known phy start addresses to determine
4449 				 * the platform type.
4450 				 */
4451 				for (i = NXGE_EXT_PHY_PORT_ST;
4452 				    i < NXGE_MAX_PHY_PORTS; i++) {
4453 					if (phy_fd[i] == 1)
4454 						break;
4455 				}
4456 
4457 				if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) {
4458 					hw_p->platform_type =
4459 					    P_NEPTUNE_MARAMBA_P0;
4460 				} else if (i ==
4461 				    BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
4462 					hw_p->platform_type =
4463 					    P_NEPTUNE_MARAMBA_P1;
4464 				} else {
4465 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4466 					    "Unknown port %d...Cannot "
4467 					    "determine platform type", i));
4468 					goto error_exit;
4469 				}
4470 
4471 				/* The 10G port is BCM8704 */
4472 				for (i = NXGE_EXT_PHY_PORT_ST;
4473 				    i < NXGE_MAX_PHY_PORTS; i++) {
4474 					if (port_fd[i] == 1) {
4475 						prt_id = i;
4476 						break;
4477 					}
4478 				}
4479 
4480 				prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE;
4481 				if (prt_id == 0) {
4482 					hw_p->niu_type = NEPTUNE_1_10GF_3_1GC;
4483 				} else if (prt_id == 1) {
4484 					hw_p->niu_type =
4485 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
4486 				} else {
4487 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4488 					    "Unsupported neptune type 11"));
4489 					goto error_exit;
4490 				}
4491 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4492 				    "Maramba with 1 XAUI"));
4493 			} else {
4494 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4495 				    "Unsupported neptune type 12"));
4496 				goto error_exit;
4497 			}
4498 			break;
4499 		default:
4500 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4501 			    "Unsupported neptune type 13"));
4502 			goto error_exit;
4503 		}
4504 		break;
4505 	case 0:
4506 		switch (total_phy_fd) {
4507 		case 4:
4508 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
4509 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
4510 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
4511 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
4512 
4513 				/*
4514 				 * Check the first phy port address against
4515 				 * the known phy start addresses to determine
4516 				 * the platform type.
4517 				 */
4518 				for (i = NXGE_EXT_PHY_PORT_ST;
4519 				    i < NXGE_MAX_PHY_PORTS; i++) {
4520 					if (phy_fd[i] == 1)
4521 						break;
4522 				}
4523 
4524 				if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) {
4525 					hw_p->platform_type =
4526 					    P_NEPTUNE_MARAMBA_P1;
4527 				} else if (i ==
4528 				    BCM5464_NEPTUNE_PORT_ADDR_BASE) {
4529 					hw_p->platform_type =
4530 					    P_NEPTUNE_ATLAS_4PORT;
4531 				} else {
4532 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4533 					    "Unknown port %d...Cannot "
4534 					    "determine platform type", i));
4535 					goto error_exit;
4536 				}
4537 				hw_p->niu_type = NEPTUNE_4_1GC;
4538 			} else {
4539 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4540 				    "Unsupported neptune type 14"));
4541 				goto error_exit;
4542 			}
4543 			break;
4544 		case 3:
4545 			/* TODO 3 1G mode */
4546 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4547 			    "Unsupported neptune type 15"));
4548 			goto error_exit;
4549 		case 2:
4550 			/* TODO 2 1G mode */
4551 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4552 			    "Unsupported neptune type 16"));
4553 			goto error_exit;
4554 		case 1:
4555 			/* TODO 1 1G mode */
4556 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4557 			    "Unsupported neptune type 17"));
4558 			goto error_exit;
4559 		default:
4560 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4561 			    "Unsupported neptune type 18, total phy fd %d",
4562 			    total_phy_fd));
4563 			goto error_exit;
4564 		}
4565 		break;
4566 	default:
4567 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4568 		    "Unsupported neptune type 19"));
4569 		goto error_exit;
4570 	}
4571 
4572 scan_exit:
4573 
4574 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
4575 	    "niu type [0x%x]\n", hw_p->niu_type));
4576 	return (status);
4577 
4578 error_exit:
4579 	return (NXGE_ERROR);
4580 }
4581 
4582 boolean_t
4583 nxge_is_valid_local_mac(ether_addr_st mac_addr)
4584 {
4585 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
4586 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
4587 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
4588 		return (B_FALSE);
4589 	else
4590 		return (B_TRUE);
4591 }
4592 
4593 static void
4594 nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
4595 
4596 	npi_status_t rs = NPI_SUCCESS;
4597 	uint8_t xcvr_portn;
4598 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4599 
4600 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
4601 
4602 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
4603 		xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE;
4604 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
4605 		xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE;
4606 	}
4607 	/*
4608 	 * For Altas 4-1G copper, Xcvr port numbers are
4609 	 * swapped with ethernet port number. This is
4610 	 * designed for better signal integrity in routing.
4611 	 */
4612 	switch (portn) {
4613 	case 0:
4614 		xcvr_portn += 3;
4615 		break;
4616 	case 1:
4617 		xcvr_portn += 2;
4618 		break;
4619 	case 2:
4620 		xcvr_portn += 1;
4621 		break;
4622 	case 3:
4623 	default:
4624 		break;
4625 	}
4626 
4627 	MUTEX_ENTER(&nxge_mii_lock);
4628 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4629 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
4630 	if (rs != NPI_SUCCESS) {
4631 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4632 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4633 		    "returned error 0x[%x]", rs));
4634 		MUTEX_EXIT(&nxge_mii_lock);
4635 		return;
4636 	}
4637 
4638 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
4639 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
4640 	if (rs != NPI_SUCCESS) {
4641 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4642 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
4643 		    "returned error 0x[%x]", rs));
4644 		MUTEX_EXIT(&nxge_mii_lock);
4645 		return;
4646 	}
4647 
4648 	MUTEX_EXIT(&nxge_mii_lock);
4649 }
4650