xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 4df55fde)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
22e759c33aSMichael Speer  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #include <sys/nxge/nxge_impl.h>
2744961713Sgirish #include <sys/nxge/nxge_mac.h>
28678453a8Sspeer #include <sys/nxge/nxge_hio.h>
2944961713Sgirish 
3098ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3198ecde52Stm #define	LM_WAIT_MULTIPLIER	8
3298ecde52Stm 
33321febdeSsbehera #define	SERDES_RDY_WT_INTERVAL	50
34321febdeSsbehera #define	MAX_SERDES_RDY_RETRIES	10
35321febdeSsbehera 
3600161856Syc #define	TN1010_SPEED_1G		1
3700161856Syc #define	TN1010_SPEED_10G	0
3800161856Syc #define	TN1010_AN_IN_PROG	0	/* Auto negotiation in progress */
3900161856Syc #define	TN1010_AN_COMPLETE	1
4000161856Syc #define	TN1010_AN_RSVD		2
4100161856Syc #define	TN1010_AN_FAILED	3
4200161856Syc 
4344961713Sgirish extern uint32_t nxge_no_link_notify;
4459ac0c16Sdavemq extern boolean_t nxge_no_msg;
4544961713Sgirish extern uint32_t nxge_lb_dbg;
464202ea4bSsbehera extern uint32_t nxge_jumbo_mtu;
4744961713Sgirish 
4898ecde52Stm typedef enum {
4998ecde52Stm 	CHECK_LINK_RESCHEDULE,
5098ecde52Stm 	CHECK_LINK_STOP
5198ecde52Stm } check_link_state_t;
5298ecde52Stm 
5398ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
5498ecde52Stm 
5544961713Sgirish /*
5644961713Sgirish  * Ethernet broadcast address definition.
5744961713Sgirish  */
5844961713Sgirish static ether_addr_st etherbroadcastaddr =
5944961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
6059ac0c16Sdavemq /*
6159ac0c16Sdavemq  * Ethernet zero address definition.
6259ac0c16Sdavemq  */
6356d930aeSspeer static ether_addr_st etherzeroaddr =
6456d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
6559ac0c16Sdavemq /*
6659ac0c16Sdavemq  * Supported chip types
6759ac0c16Sdavemq  */
6852cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = {
6952cdd236Ssbehera 	BCM8704_DEV_ID,
7052cdd236Ssbehera 	MARVELL_88X_201X_DEV_ID,
7100161856Syc 	BCM8706_DEV_ID,
7200161856Syc 	TN1010_DEV_ID
7352cdd236Ssbehera };
7452cdd236Ssbehera 
75b1000363Sml static uint32_t nxge_supported_cl22_ids[] = {
76b1000363Sml     BCM5464R_PHY_ID,
77b1000363Sml     BCM5482_PHY_ID
78b1000363Sml };
7959ac0c16Sdavemq 
8059ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
8159ac0c16Sdavemq 				sizeof (uint32_t))
8259ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
8359ac0c16Sdavemq 				sizeof (uint32_t))
8459ac0c16Sdavemq /*
8559ac0c16Sdavemq  * static functions
8659ac0c16Sdavemq  */
872e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
882e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
892e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
9059ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
912d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
9259ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
93*4df55fdeSJanie Lu static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t);
9459ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
9559ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
9659ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
9759ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
9859ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
9959ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
10059ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
10159ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
10259ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
10359ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
10459ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1052d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1062d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
10759ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
10859ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
10900161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
11052cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
11100161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
11200161856Syc 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
11300161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
11400161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
11500161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
11600161856Syc 	nxge_link_state_t *link_up);
11700161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
11800161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
11900161856Syc 
12000161856Syc nxge_status_t nxge_mac_init(p_nxge_t);
12100161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
12200161856Syc 
12300161856Syc #ifdef NXGE_DEBUG
12400161856Syc static void nxge_mii_dump(p_nxge_t);
12500161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
12600161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
12700161856Syc #endif
12859ac0c16Sdavemq 
12959ac0c16Sdavemq /*
13059ac0c16Sdavemq  * xcvr tables for supported transceivers
13159ac0c16Sdavemq  */
13259ac0c16Sdavemq 
13300161856Syc /*
13400161856Syc  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
13500161856Syc  * The Teranetics TN1010 based copper XAUI card can also be used
13600161856Syc  * on N2-NIU systems in 10G mode, but it uses its own table
13700161856Syc  * nxge_n2_10G_tn1010_table below.
13800161856Syc  */
1392e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
14059ac0c16Sdavemq 	nxge_n2_serdes_init,
14159ac0c16Sdavemq 	nxge_10G_xcvr_init,
14259ac0c16Sdavemq 	nxge_10G_link_intr_stop,
14359ac0c16Sdavemq 	nxge_10G_link_intr_start,
14459ac0c16Sdavemq 	nxge_check_10g_link,
1452d17280bSsbehera 	PCS_XCVR
14659ac0c16Sdavemq };
14759ac0c16Sdavemq 
14800161856Syc /*
14900161856Syc  * For the Teranetics TN1010 based copper XAUI card
15000161856Syc  */
15100161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
15200161856Syc 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
15300161856Syc 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
15400161856Syc 	nxge_10G_link_intr_stop,
15500161856Syc 	nxge_10G_link_intr_start,
15600161856Syc 	nxge_check_tn1010_link,		/* Will figure out speed */
15700161856Syc 	XPCS_XCVR
15800161856Syc };
15900161856Syc 
1602e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1612e59129aSraghus 	nxge_n2_serdes_init,
1622e59129aSraghus 	nxge_1G_xcvr_init,
1632e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1642e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1652e59129aSraghus 	nxge_check_mii_link,
1662d17280bSsbehera 	PCS_XCVR
1672e59129aSraghus };
1682e59129aSraghus 
16900161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
17000161856Syc 	nxge_n2_serdes_init,
17100161856Syc 	nxge_tn1010_xcvr_init,
17200161856Syc 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
17300161856Syc 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
17400161856Syc 	nxge_check_tn1010_link,
17500161856Syc 	PCS_XCVR
17600161856Syc };
17700161856Syc 
17800161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = {
17900161856Syc 	nxge_neptune_10G_serdes_init,
18000161856Syc 	nxge_tn1010_xcvr_init,
18100161856Syc 	nxge_10G_link_intr_stop,
18200161856Syc 	nxge_10G_link_intr_start,
18300161856Syc 	nxge_check_tn1010_link,
18400161856Syc 	XPCS_XCVR
18500161856Syc };
18600161856Syc 
18700161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = {
18800161856Syc 	nxge_1G_serdes_init,
18900161856Syc 	nxge_tn1010_xcvr_init,
19000161856Syc 	nxge_1G_fiber_link_intr_stop,
19100161856Syc 	nxge_1G_fiber_link_intr_start,
19200161856Syc 	nxge_check_tn1010_link,
19300161856Syc 	PCS_XCVR
19400161856Syc };
19500161856Syc 
19659ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
19759ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
19859ac0c16Sdavemq 	nxge_10G_xcvr_init,
19959ac0c16Sdavemq 	nxge_10G_link_intr_stop,
20059ac0c16Sdavemq 	nxge_10G_link_intr_start,
20159ac0c16Sdavemq 	nxge_check_10g_link,
2022d17280bSsbehera 	PCS_XCVR
20359ac0c16Sdavemq };
20459ac0c16Sdavemq 
20559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
20659ac0c16Sdavemq 	NULL,
20759ac0c16Sdavemq 	nxge_1G_xcvr_init,
20859ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
20959ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
21059ac0c16Sdavemq 	nxge_check_mii_link,
2112d17280bSsbehera 	INT_MII_XCVR
21259ac0c16Sdavemq };
21359ac0c16Sdavemq 
21400161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */
21559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
21659ac0c16Sdavemq 	nxge_1G_serdes_init,
21759ac0c16Sdavemq 	nxge_1G_xcvr_init,
21859ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
21959ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
22059ac0c16Sdavemq 	nxge_check_mii_link,
2212d17280bSsbehera 	PCS_XCVR
22259ac0c16Sdavemq };
22359ac0c16Sdavemq 
22459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
22559ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
22659ac0c16Sdavemq 	NULL,
22759ac0c16Sdavemq 	NULL,
22859ac0c16Sdavemq 	NULL,
2292e59129aSraghus 	NULL,
2302d17280bSsbehera 	PCS_XCVR
23159ac0c16Sdavemq };
23244961713Sgirish 
23300161856Syc /*
23400161856Syc  * NXGE_PORT_TN1010 is defined as,
23500161856Syc  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
23600161856Syc  *	= 0 | 5 << 16 = 0x50000
23700161856Syc  *
23800161856Syc  * So NEPTUNE_2_TN1010 =
23900161856Syc  *      (NXGE_PORT_TN1010 |
24000161856Syc  *      (NXGE_PORT_TN1010 << 4) |
24100161856Syc  *      (NXGE_PORT_NONE << 8) |
24200161856Syc  *      (NXGE_PORT_NONE << 12)),
24300161856Syc  *      = 0x50000 | (0x50000 << 4)
24400161856Syc  *	= 0x550000
24500161856Syc  *
24600161856Syc  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
24700161856Syc  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
24800161856Syc  * = 0x50000
24900161856Syc  */
25000161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
25100161856Syc {
25200161856Syc 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
25300161856Syc 
25400161856Syc 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
25500161856Syc 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
25600161856Syc 		return (B_TRUE);
25700161856Syc 	} else {
25800161856Syc 		return (B_FALSE);
25900161856Syc 	}
26000161856Syc }
26144961713Sgirish 
262d81011f0Ssbehera 
26300161856Syc /*
26400161856Syc  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
26500161856Syc  * serial EEPROM or VPD if possible.  Note that not all systems could get
26600161856Syc  * the portmode information by calling this function.  For example, the
26700161856Syc  * Maramba system figures out the portmode information by calling function
26800161856Syc  * nxge_setup_xcvr_table.
26900161856Syc  */
2702e59129aSraghus nxge_status_t
2712e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
2722e59129aSraghus {
2732e59129aSraghus 	nxge_status_t status = NXGE_OK;
2742e59129aSraghus 	char *phy_type;
2752e59129aSraghus 	char *prop_val;
27600161856Syc 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2771c7408c9Stc 	uint32_t	val;
2781c7408c9Stc 	npi_status_t	rs;
2791c7408c9Stc 
2801c7408c9Stc 	/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
2811c7408c9Stc 	if (nxgep->mac.portmode == PORT_10G_SERDES &&
2821c7408c9Stc 	    nxgep->statsp->mac_stats.link_up) {
2831c7408c9Stc 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2841c7408c9Stc 		return (status);
2851c7408c9Stc 	}
2862e59129aSraghus 
2872e59129aSraghus 	nxgep->mac.portmode = 0;
2882d17280bSsbehera 	nxgep->xcvr_addr = 0;
2892e59129aSraghus 
2902d17280bSsbehera 	/*
2912d17280bSsbehera 	 * First check for hot swappable phy property.
2922d17280bSsbehera 	 */
2932d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
2942d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2952d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2962d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
2972d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
2982d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2992d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3002d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3012d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3022d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
3032d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
3042d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
3052d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3062d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3072d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3082d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3092d17280bSsbehera 	}
3102d17280bSsbehera 
3112d17280bSsbehera 	/*
3122d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3132d17280bSsbehera 	 */
3142d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3152d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
316ef523517SMichael Speer 		if (portn > 1) {
317ef523517SMichael Speer 			return (NXGE_ERROR);
318ef523517SMichael Speer 		}
319ef523517SMichael Speer 
3202d17280bSsbehera 		/*
3212d17280bSsbehera 		 * If this is the 2nd NIU port, then check 2 addresses
3222d17280bSsbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
3232d17280bSsbehera 		 * (in the eval board) or 20 (in the P0 board).
3242d17280bSsbehera 		 */
3252d17280bSsbehera 		if (portn == 1) {
3262d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
32700161856Syc 			    ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID,
3282d17280bSsbehera 			    BCM_PHY_ID_MASK)) {
3292d17280bSsbehera 				nxgep->xcvr_addr =
33000161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR;
3312d17280bSsbehera 				goto found_phy;
3322d17280bSsbehera 			}
3332d17280bSsbehera 		}
3342d17280bSsbehera 		if (nxge_is_phy_present(nxgep,
33500161856Syc 		    GOA_CLAUSE45_PORT_ADDR_BASE + portn,
3362d17280bSsbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
33700161856Syc 			nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE +
3382d17280bSsbehera 			    portn;
3392d17280bSsbehera 			goto found_phy;
3402d17280bSsbehera 		}
3412d17280bSsbehera 
3422d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
3431c7408c9Stc 
3441c7408c9Stc 		/* Check Serdes link to detect Opus NEM */
3451c7408c9Stc 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3461c7408c9Stc 		    XPCS_REG_STATUS, &val);
3471c7408c9Stc 
3481c7408c9Stc 		if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
3491c7408c9Stc 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3501c7408c9Stc 			nxgep->mac.portmode = PORT_10G_SERDES;
3511c7408c9Stc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3521c7408c9Stc 			    "HSP 10G Serdes FOUND!!"));
3531c7408c9Stc 		}
3542d17280bSsbehera 		goto check_phy_done;
3552d17280bSsbehera found_phy:
3562d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3572d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3582d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
3592d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3602d17280bSsbehera 		    "found for hot swappable phy"));
3612d17280bSsbehera check_phy_done:
3622d17280bSsbehera 		return (status);
3632d17280bSsbehera 	}
3642d17280bSsbehera 
36500161856Syc 	/* Get phy-type property (May have been set by nxge.conf) */
3662e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3672e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3682e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3692e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3702e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
3712e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
3722e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3732e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3742e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3752e59129aSraghus 			    "found: 10G Serdes"));
3762e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3772e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3782e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3792e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3802e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
3812e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3822e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3832e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3842e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3852e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3862e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3872e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
388321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
38900161856Syc 			/*
39000161856Syc 			 * Before OBP supports new phy-type property
39100161856Syc 			 * value "xgc", the 10G copper XAUI may carry
39200161856Syc 			 * "xgf" instead of "xgc". If the OBP is
39300161856Syc 			 * upgraded to a newer version which supports
39400161856Syc 			 * "xgc", then the TN1010 related code in this
39500161856Syc 			 * "xgf" case will not be used anymore.
39600161856Syc 			 */
39700161856Syc 			if (nxge_is_tn1010_phy(nxgep)) {
39800161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
39900161856Syc 				    != NXGE_OK) {
40000161856Syc 					return (status);
40100161856Syc 				}
40200161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
40300161856Syc 			} else {  /* For Fiber XAUI */
40400161856Syc 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
40500161856Syc 				nxgep->mac.portmode = PORT_10G_FIBER;
40600161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
40700161856Syc 				    "10G Fiber Xcvr"));
40800161856Syc 			}
40900161856Syc 		} else if (strcmp("xgc", prop_val) == 0) {
41000161856Syc 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
41100161856Syc 				return (status);
41200161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4132e59129aSraghus 		}
4142e59129aSraghus 
4152e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
4162e59129aSraghus 		    "phy-type", prop_val);
4172e59129aSraghus 		ddi_prop_free(prop_val);
4182e59129aSraghus 
4192e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4202e59129aSraghus 		    "Got phy type [0x%x] from conf file",
4212e59129aSraghus 		    nxgep->mac.portmode));
4222e59129aSraghus 
4232e59129aSraghus 		return (NXGE_OK);
4242e59129aSraghus 	}
4252d17280bSsbehera 
4262d17280bSsbehera 	/* Get phy-type property from OBP */
4272e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
4282e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4292e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4302e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
43100161856Syc 				/*
43200161856Syc 				 * Before OBP supports new phy-type property
43300161856Syc 				 * value "xgc", the 10G copper XAUI may carry
43400161856Syc 				 * "xgf" instead of "xgc". If the OBP is
43500161856Syc 				 * upgraded to a newer version which supports
43600161856Syc 				 * "xgc", then the TN1010 related code in this
43700161856Syc 				 * "xgf" case will not be used anymore.
43800161856Syc 				 */
43900161856Syc 				if (nxge_is_tn1010_phy(nxgep)) {
44000161856Syc 					if ((status =
44100161856Syc 					    nxge_set_tn1010_param(nxgep))
44200161856Syc 					    != NXGE_OK) {
44300161856Syc 						return (status);
44400161856Syc 					}
44500161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44600161856Syc 					    "TN1010 Xcvr"));
44700161856Syc 				} else {  /* For Fiber XAUI */
44800161856Syc 					nxgep->statsp->mac_stats.xcvr_inuse
44900161856Syc 					    = XPCS_XCVR;
45000161856Syc 					nxgep->mac.portmode = PORT_10G_FIBER;
45100161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45200161856Syc 					    "10G Fiber Xcvr"));
45300161856Syc 				}
4542e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
4552e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4562e59129aSraghus 				    INT_MII_XCVR;
4572e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4582e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4592e59129aSraghus 				    "1G Copper Xcvr"));
4602e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4612e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4622e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4632e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4642e59129aSraghus 				    "1G Fiber Xcvr"));
4652e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
46600161856Syc 				status = nxge_set_tn1010_param(nxgep);
46700161856Syc 				if (status != NXGE_OK)
46800161856Syc 					return (status);
46900161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4702e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4712e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4722e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4732e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4742e59129aSraghus 				    "OBP: 10G Serdes"));
4752e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4762e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4772e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4782e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4792e59129aSraghus 				    "OBP: 1G Serdes"));
4802e59129aSraghus 			} else {
4812e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4822e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
4832e59129aSraghus 				ddi_prop_free(prop_val);
4842e59129aSraghus 				return (NXGE_ERROR);
4852e59129aSraghus 			}
4862e59129aSraghus 			status = NXGE_OK;
4872e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4882e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
4892e59129aSraghus 			ddi_prop_free(prop_val);
4902e59129aSraghus 
4912e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4922e59129aSraghus 			    "Got phy type [0x%x] from OBP",
4932e59129aSraghus 			    nxgep->mac.portmode));
4942e59129aSraghus 
4952e59129aSraghus 			return (status);
4962e59129aSraghus 		} else {
4972e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4982e59129aSraghus 			    "Exiting...phy-type property not found"));
4992e59129aSraghus 			return (NXGE_ERROR);
5002e59129aSraghus 		}
5012e59129aSraghus 	}
5022e59129aSraghus 
5032e59129aSraghus 
5042e59129aSraghus 	if (!nxgep->vpd_info.present) {
5052e59129aSraghus 		return (NXGE_OK);
5062e59129aSraghus 	}
5072e59129aSraghus 
5082e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
5092e59129aSraghus 		goto read_seeprom;
5102e59129aSraghus 	}
5112e59129aSraghus 
5122e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5132e59129aSraghus 	    "Reading phy type from expansion ROM"));
5142e59129aSraghus 	/*
5152e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
5162e59129aSraghus 	 * expansion ROM.
5172e59129aSraghus 	 */
5182e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
5192e59129aSraghus 
520d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
5212e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
5222e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
523d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5242e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5252e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
526d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5272e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5282e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
529d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
53000161856Syc 		status = nxge_set_tn1010_param(nxgep);
53100161856Syc 		if (status != NXGE_OK) {
53200161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
53300161856Syc 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
53400161856Syc 			goto read_seeprom;
53500161856Syc 		}
536d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
537d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
538d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
539d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
540d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
541d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5422e59129aSraghus 	} else {
543d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5442e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5452e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5462e59129aSraghus 		goto read_seeprom;
5472e59129aSraghus 	}
5482e59129aSraghus 
5492e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5502e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5512e59129aSraghus 
5522e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5532e59129aSraghus 	return (status);
5542e59129aSraghus 
5552e59129aSraghus read_seeprom:
5562e59129aSraghus 	/*
5572e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
5582e59129aSraghus 	 */
5592e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
5602e59129aSraghus 	if (status != NXGE_OK) {
5612e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5622e59129aSraghus 		    "Failed to get phy type"));
5632e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5642e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5652e59129aSraghus 	}
5662e59129aSraghus 
5672e59129aSraghus 	return (status);
5682e59129aSraghus 
5692e59129aSraghus }
5702e59129aSraghus 
57159ac0c16Sdavemq /* Set up the PHY specific values. */
57259ac0c16Sdavemq 
57359ac0c16Sdavemq nxge_status_t
57459ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
57559ac0c16Sdavemq {
57659ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
57759ac0c16Sdavemq 	uint32_t	port_type;
57859ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5792e59129aSraghus 	uint32_t	pcs_id = 0;
5802e59129aSraghus 	uint32_t	pma_pmd_id = 0;
5812e59129aSraghus 	uint32_t	phy_id = 0;
5822d17280bSsbehera 	uint16_t	chip_id = 0;
58359ac0c16Sdavemq 
58459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
58559ac0c16Sdavemq 	    portn));
58659ac0c16Sdavemq 
5872e59129aSraghus 	switch (nxgep->niu_type) {
5882e59129aSraghus 	case N2_NIU:
5892e59129aSraghus 		switch (nxgep->mac.portmode) {
5902e59129aSraghus 		case PORT_1G_FIBER:
5912e59129aSraghus 		case PORT_1G_SERDES:
5922e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
5932d17280bSsbehera 			nxgep->xcvr_addr = portn;
5942e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5952e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5962e59129aSraghus 			    "Serdes"));
5972e59129aSraghus 			break;
5982e59129aSraghus 		case PORT_10G_FIBER:
5992e59129aSraghus 		case PORT_10G_SERDES:
6002e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
6012d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
6022d17280bSsbehera 				nxgep->xcvr_addr =
6032d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
6042d17280bSsbehera 			}
6052e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
6062e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
6072e59129aSraghus 			    "Serdes"));
6082e59129aSraghus 			break;
60900161856Syc 		case PORT_1G_TN1010:
61000161856Syc 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
61100161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61200161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61300161856Syc 			    "TN1010 Copper Xcvr in 1G"));
61400161856Syc 			break;
61500161856Syc 		case PORT_10G_TN1010:
61600161856Syc 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
61700161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61800161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61900161856Syc 			    "TN1010 Copper Xcvr in 10G"));
62000161856Syc 			break;
6212d17280bSsbehera 		case PORT_HSP_MODE:
6222d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
6232d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6242d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6252d17280bSsbehera 			    "Swappable Xcvr (not present)"));
6262d17280bSsbehera 			break;
6272e59129aSraghus 		default:
6282e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6292e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
6302e59129aSraghus 			    "Unable to determine NIU portmode"));
6312e59129aSraghus 			return (NXGE_ERROR);
6322e59129aSraghus 		}
6332e59129aSraghus 		break;
6342e59129aSraghus 	default:
6352e59129aSraghus 		if (nxgep->mac.portmode == 0) {
6362e59129aSraghus 			/*
6372e59129aSraghus 			 * Would be the case for platforms like Maramba
6382e59129aSraghus 			 * in which the phy type could not be got from conf
6392e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
6402e59129aSraghus 			 */
6412e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6422e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6432e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
6442e59129aSraghus 				    " Invalid Neptune type [0x%x]",
6452e59129aSraghus 				    nxgep->niu_type));
6462e59129aSraghus 				return (NXGE_ERROR);
6472e59129aSraghus 			}
6482e59129aSraghus 
6492e59129aSraghus 			port_type = nxgep->niu_type >>
6502e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
6512e59129aSraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6522e59129aSraghus 
6532e59129aSraghus 			switch (port_type) {
6542e59129aSraghus 
6552e59129aSraghus 			case NXGE_PORT_1G_COPPER:
6562e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
6572e59129aSraghus 				break;
6582e59129aSraghus 			case NXGE_PORT_10G_COPPER:
6592e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6602e59129aSraghus 				break;
6612e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
6622e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6632e59129aSraghus 				break;
6642e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
6652e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6662e59129aSraghus 				break;
6672e59129aSraghus 			case NXGE_PORT_1G_SERDES:
6682e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6692e59129aSraghus 				break;
6702e59129aSraghus 			case NXGE_PORT_10G_SERDES:
6712e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6722e59129aSraghus 				break;
67300161856Syc 			/* Ports 2 and 3 of Alonso or ARTM */
6742e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6752e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6762e59129aSraghus 				break;
67700161856Syc 			case NXGE_PORT_TN1010:
67800161856Syc 				/*
67900161856Syc 				 * If this port uses the TN1010 copper
68000161856Syc 				 * PHY, then its speed is not known yet
68100161856Syc 				 * because nxge_scan_ports_phy could only
68200161856Syc 				 * figure out the vendor of the PHY but
68300161856Syc 				 * not its speed. nxge_set_tn1010_param
68400161856Syc 				 * will read the PHY speed and set
68500161856Syc 				 * portmode accordingly.
68600161856Syc 				 */
68700161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
68800161856Syc 				    != NXGE_OK) {
68900161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69000161856Syc 					    "nxge_set_tn1010_param failed"));
69100161856Syc 					return (status);
69200161856Syc 				}
69300161856Syc 				break;
6942e59129aSraghus 			default:
6952e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6962e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
6972e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
6982e59129aSraghus 				return (NXGE_ERROR);
6992e59129aSraghus 			}
7002e59129aSraghus 		}
7012e59129aSraghus 
70200161856Syc 		/*
70300161856Syc 		 * Above switch has figured out nxge->mac.portmode, now set
70400161856Syc 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
70500161856Syc 		 * to portmode.
70600161856Syc 		 */
7072e59129aSraghus 		switch (nxgep->mac.portmode) {
7082e59129aSraghus 		case PORT_1G_COPPER:
7092e59129aSraghus 		case PORT_1G_RGMII_FIBER:
71059ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
7112d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
71259ac0c16Sdavemq 			/*
71359ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
71459ac0c16Sdavemq 			 * swapped with ethernet port number. This is
7152e59129aSraghus 			 * designed for better signal integrity in
7162e59129aSraghus 			 * routing. This is also the case for the
7172e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
7182e59129aSraghus 			 * platform.
71959ac0c16Sdavemq 			 */
7202e59129aSraghus 			switch (nxgep->platform_type) {
7212e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
7222e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7232e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
7242e59129aSraghus 				switch (portn) {
7252e59129aSraghus 				case 0:
7262d17280bSsbehera 					nxgep->xcvr_addr += 3;
7272e59129aSraghus 					break;
7282e59129aSraghus 				case 1:
7292d17280bSsbehera 					nxgep->xcvr_addr += 1;
7302e59129aSraghus 					break;
7312e59129aSraghus 				case 2:
7322d17280bSsbehera 					nxgep->xcvr_addr -= 1;
7332e59129aSraghus 					break;
7342e59129aSraghus 				case 3:
7352d17280bSsbehera 					nxgep->xcvr_addr -= 3;
7362e59129aSraghus 					break;
7372e59129aSraghus 				default:
7382e59129aSraghus 					return (NXGE_ERROR);
7392e59129aSraghus 				}
74059ac0c16Sdavemq 				break;
74159ac0c16Sdavemq 			default:
7422e59129aSraghus 				break;
74359ac0c16Sdavemq 			}
744d81011f0Ssbehera 
7452e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7462e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7472e59129aSraghus 			    "Copper" : "RGMII Fiber"));
74859ac0c16Sdavemq 			break;
74900161856Syc 
7502e59129aSraghus 		case PORT_10G_COPPER:
75159ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
75259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
75359ac0c16Sdavemq 			break;
75400161856Syc 
75500161856Syc 		case PORT_1G_TN1010:
75600161856Syc 			nxgep->xcvr = nxge_1G_tn1010_table;
75700161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
75800161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75900161856Syc 			    "1G TN1010 copper Xcvr"));
76000161856Syc 			break;
76100161856Syc 
76200161856Syc 		case PORT_10G_TN1010:
76300161856Syc 			nxgep->xcvr = nxge_10G_tn1010_table;
76400161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
76500161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
76600161856Syc 			    "10G TN1010 copper Xcvr"));
76700161856Syc 			break;
76800161856Syc 
7692e59129aSraghus 		case PORT_1G_FIBER:
7702e59129aSraghus 		case PORT_1G_SERDES:
77159ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7722d17280bSsbehera 			nxgep->xcvr_addr = portn;
7732e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7742e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7752e59129aSraghus 			    "Fiber" : "Serdes"));
77659ac0c16Sdavemq 			break;
7772e59129aSraghus 		case PORT_10G_FIBER:
7782e59129aSraghus 		case PORT_10G_SERDES:
77959ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7802d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7812d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7822d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
7832d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7842d17280bSsbehera 			    nxgep->xcvr_addr));
7852d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7862d17280bSsbehera 				nxgep->xcvr_addr =
7872d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7882d17280bSsbehera 			}
7892e59129aSraghus 			switch (nxgep->platform_type) {
7902e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7912e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
79259ac0c16Sdavemq 				/*
79359ac0c16Sdavemq 				 * Switch off LED for corresponding copper
79459ac0c16Sdavemq 				 * port
79559ac0c16Sdavemq 				 */
79659ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7972e59129aSraghus 				break;
7982e59129aSraghus 			default:
7992e59129aSraghus 				break;
80059ac0c16Sdavemq 			}
8012e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
8022e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
8032e59129aSraghus 			    "Fiber" : "Serdes"));
80459ac0c16Sdavemq 			break;
8052d17280bSsbehera 
8062d17280bSsbehera 		case PORT_HSP_MODE:
8072d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
8082d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
8092d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
8102d17280bSsbehera 			    "Swappable Xcvr (not present)"));
8112d17280bSsbehera 			break;
81259ac0c16Sdavemq 		default:
81359ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
81459ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
81559ac0c16Sdavemq 			return (NXGE_ERROR);
81659ac0c16Sdavemq 		}
81759ac0c16Sdavemq 	}
81859ac0c16Sdavemq 
8192d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
82052cdd236Ssbehera 		uint32_t pma_pmd_id;
82152cdd236Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
82252cdd236Ssbehera 		    nxgep->xcvr_addr);
82352cdd236Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
82452cdd236Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
82552cdd236Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
82652cdd236Ssbehera 			    "nxge_setup_xcvr_table: "
82752cdd236Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
82852cdd236Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8292d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8302d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
8312d17280bSsbehera 
8322d17280bSsbehera 			switch (chip_id) {
8332d17280bSsbehera 			case BCM8704_CHIP_ID:
8342d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8352d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8362d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8372d17280bSsbehera 				    chip_id));
8382d17280bSsbehera 				break;
8392d17280bSsbehera 			case BCM8706_CHIP_ID:
8402d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8412d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8422d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8432d17280bSsbehera 				    chip_id));
8442d17280bSsbehera 				break;
8452d17280bSsbehera 			default:
8462d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8472d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8482d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8492d17280bSsbehera 				    chip_id));
8502d17280bSsbehera 				break;
8512d17280bSsbehera 			}
8522d17280bSsbehera 		}
8532d17280bSsbehera 	}
8542d17280bSsbehera 
85559ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8562d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8572d17280bSsbehera 	nxgep->chip_id = chip_id;
8582e59129aSraghus 
8592e59129aSraghus 	/*
8602e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
8612e59129aSraghus 	 */
8622e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8632e59129aSraghus 
8642d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8652e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8662e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8672e59129aSraghus 	} else {
8682d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8692e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8702e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8712e59129aSraghus 		} else {
8722e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8732d17280bSsbehera 			    nxgep->xcvr_addr);
8742e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8752e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8762e59129aSraghus 			}
8772e59129aSraghus 		}
8782e59129aSraghus 	}
8792e59129aSraghus 
88059ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
88159ac0c16Sdavemq 
8822e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
88323b952a3SSantwona Behera 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
8842d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8852e59129aSraghus 
88659ac0c16Sdavemq 	return (status);
88759ac0c16Sdavemq }
88859ac0c16Sdavemq 
88944961713Sgirish /* Initialize the entire MAC and physical layer */
89044961713Sgirish 
89144961713Sgirish nxge_status_t
89244961713Sgirish nxge_mac_init(p_nxge_t nxgep)
89344961713Sgirish {
89444961713Sgirish 	uint8_t			portn;
89544961713Sgirish 	nxge_status_t		status = NXGE_OK;
89644961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
89744961713Sgirish 
89844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
89944961713Sgirish 
90044961713Sgirish 	nxgep->mac.portnum = portn;
90144961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
90244961713Sgirish 
90344961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
90444961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
90544961713Sgirish 
90600161856Syc 
90744961713Sgirish 	/* Initialize XIF to configure a network mode */
90844961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
90944961713Sgirish 		goto fail;
91044961713Sgirish 	}
91144961713Sgirish 
91244961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
91344961713Sgirish 		goto fail;
91444961713Sgirish 	}
91544961713Sgirish 
91644961713Sgirish 	/* Initialize TX and RX MACs */
91744961713Sgirish 	/*
91844961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
91944961713Sgirish 	 */
92044961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
92144961713Sgirish 		goto fail;
92244961713Sgirish 
92344961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
92444961713Sgirish 		goto fail;
92544961713Sgirish 
92644961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
92744961713Sgirish 		goto fail;
92844961713Sgirish 
92944961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
93044961713Sgirish 		goto fail;
93144961713Sgirish 
93244961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
93344961713Sgirish 		goto fail;
93444961713Sgirish 
935e759c33aSMichael Speer 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
936e759c33aSMichael Speer 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
937e759c33aSMichael Speer 			goto fail;
938e759c33aSMichael Speer 	}
93944961713Sgirish 
940cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
941cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
942cb9d3ae6Smisaki 		goto fail;
943cb9d3ae6Smisaki 	}
944cb9d3ae6Smisaki 
94544961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
94644961713Sgirish 
947d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
948d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
949d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
95000161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
951d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
952d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
953d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
954d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
955d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
956d81011f0Ssbehera 			goto fail;
957d81011f0Ssbehera 		}
958d81011f0Ssbehera 	}
959d81011f0Ssbehera 
9602e59129aSraghus 
96144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
96244961713Sgirish 
96344961713Sgirish 	return (NXGE_OK);
96444961713Sgirish fail:
96544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
96652ccf843Smisaki 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
96744961713Sgirish 	return (status);
96844961713Sgirish }
96944961713Sgirish 
97044961713Sgirish /* Initialize the Ethernet Link */
97144961713Sgirish 
97244961713Sgirish nxge_status_t
97344961713Sgirish nxge_link_init(p_nxge_t nxgep)
97444961713Sgirish {
97544961713Sgirish 	nxge_status_t		status = NXGE_OK;
9762e59129aSraghus 	nxge_port_mode_t	portmode;
97744961713Sgirish #ifdef	NXGE_DEBUG
97844961713Sgirish 	uint8_t			portn;
97944961713Sgirish 
98044961713Sgirish 	portn = nxgep->mac.portnum;
98144961713Sgirish 
98244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
98344961713Sgirish #endif
9841c7408c9Stc 	/* For Opus NEM, Serdes always needs to be initialized */
98544961713Sgirish 
9862e59129aSraghus 	portmode = nxgep->mac.portmode;
9872d17280bSsbehera 
98800161856Syc 	/*
98900161856Syc 	 * Workaround to get link up in both NIU ports. Some portmodes require
99000161856Syc 	 * that the xcvr be initialized twice, the first time before calling
99100161856Syc 	 * nxge_serdes_init.
99200161856Syc 	 */
9932e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
99400161856Syc 	    (portmode != PORT_10G_TN1010) &&
99500161856Syc 	    (portmode != PORT_1G_TN1010) &&
9962e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
9972e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
99844961713Sgirish 			goto fail;
9992e59129aSraghus 		}
100044961713Sgirish 	}
100100161856Syc 
100244961713Sgirish 	NXGE_DELAY(200000);
100344961713Sgirish 	/* Initialize internal serdes */
100444961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
100544961713Sgirish 		goto fail;
100644961713Sgirish 	NXGE_DELAY(200000);
100744961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
100844961713Sgirish 		goto fail;
100944961713Sgirish 
101044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
101144961713Sgirish 
101244961713Sgirish 	return (NXGE_OK);
101344961713Sgirish 
101444961713Sgirish fail:
101552ccf843Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
101652ccf843Smisaki 	    "failed to initialize Ethernet link on port<%d>", portn));
101744961713Sgirish 
101844961713Sgirish 	return (status);
101944961713Sgirish }
102044961713Sgirish 
102144961713Sgirish 
102244961713Sgirish /* Initialize the XIF sub-block within the MAC */
102344961713Sgirish 
102444961713Sgirish nxge_status_t
102544961713Sgirish nxge_xif_init(p_nxge_t nxgep)
102644961713Sgirish {
102744961713Sgirish 	uint32_t		xif_cfg = 0;
102844961713Sgirish 	npi_attr_t		ap;
102944961713Sgirish 	uint8_t			portn;
103044961713Sgirish 	nxge_port_t		portt;
103144961713Sgirish 	nxge_port_mode_t	portmode;
103244961713Sgirish 	p_nxge_stats_t		statsp;
103344961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
103444961713Sgirish 	npi_handle_t		handle;
103544961713Sgirish 
103644961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
103744961713Sgirish 
103844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
103944961713Sgirish 
104044961713Sgirish 	handle = nxgep->npi_handle;
104144961713Sgirish 	portmode = nxgep->mac.portmode;
104244961713Sgirish 	portt = nxgep->mac.porttype;
104344961713Sgirish 	statsp = nxgep->statsp;
104444961713Sgirish 
1045d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1046d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
104700161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
1048d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1049d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
1050d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1051d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
1052d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1053d81011f0Ssbehera 	}
1054d81011f0Ssbehera 
105544961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
105644961713Sgirish 
105744961713Sgirish 		/* Setup XIF Configuration for XMAC */
105844961713Sgirish 
105944961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
10602e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
106100161856Syc 		    (portmode == PORT_10G_TN1010) ||
10621c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
10632e59129aSraghus 		    (portmode == PORT_10G_SERDES))
106444961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
106544961713Sgirish 
106600161856Syc 		/* Bypass PCS so that RGMII will be used */
106744961713Sgirish 		if (portmode == PORT_1G_COPPER) {
106844961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
106944961713Sgirish 		}
107044961713Sgirish 
107144961713Sgirish 		/* Set MAC Internal Loopback if necessary */
107244961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
107344961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
107444961713Sgirish 
107544961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
107644961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
107744961713Sgirish 
107844961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
107944961713Sgirish 
10802e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
108100161856Syc 		    (portmode == PORT_10G_TN1010) ||
108200161856Syc 		    (portmode == PORT_1G_TN1010) ||
10831c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
10842e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
108500161856Syc 			/* Assume LED same for 1G and 10G */
108644961713Sgirish 			if (statsp->mac_stats.link_up) {
108744961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
108844961713Sgirish 			} else {
108944961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
109044961713Sgirish 			}
109144961713Sgirish 		}
109244961713Sgirish 
109344961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
109444961713Sgirish 		if (rs != NPI_SUCCESS)
109544961713Sgirish 			goto fail;
109644961713Sgirish 
109744961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
109844961713Sgirish 
109944961713Sgirish 		/* Set Port Mode */
110044961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
11012e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
110200161856Syc 		    (portmode == PORT_10G_TN1010) ||
11031c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
11042e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
110544961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
110652ccf843Smisaki 			    MAC_XGMII_MODE, rs);
110744961713Sgirish 			if (rs != NPI_SUCCESS)
110844961713Sgirish 				goto fail;
110944961713Sgirish 			if (statsp->mac_stats.link_up) {
111044961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
111144961713Sgirish 					goto fail;
111244961713Sgirish 			} else {
111344961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
111444961713Sgirish 					goto fail;
111544961713Sgirish 			}
111644961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
11172e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
1118d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
111900161856Syc 		    (portmode == PORT_1G_TN1010) ||
1120d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
1121d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1122d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1123d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
112444961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
112544961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
112652ccf843Smisaki 				    MAC_GMII_MODE, rs);
112744961713Sgirish 			} else {
112844961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
112952ccf843Smisaki 				    MAC_MII_MODE, rs);
113044961713Sgirish 			}
113144961713Sgirish 			if (rs != NPI_SUCCESS)
113244961713Sgirish 				goto fail;
113344961713Sgirish 		} else {
113444961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
113552ccf843Smisaki 			    "nxge_xif_init: Unknown port mode (%d)"
113652ccf843Smisaki 			    " for port<%d>", portmode, portn));
113744961713Sgirish 			goto fail;
113844961713Sgirish 		}
113944961713Sgirish 
1140d81011f0Ssbehera 		/* Enable ATCA mode */
1141d81011f0Ssbehera 
114244961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
114344961713Sgirish 
114444961713Sgirish 		/* Setup XIF Configuration for BMAC */
114544961713Sgirish 
1146d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
1147d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
114844961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
114944961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
115044961713Sgirish 		}
115144961713Sgirish 
115244961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
115344961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
115444961713Sgirish 
115544961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
115644961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
115744961713Sgirish 
115844961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
115944961713Sgirish 
116044961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
116144961713Sgirish 		if (rs != NPI_SUCCESS)
116244961713Sgirish 			goto fail;
116344961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
116444961713Sgirish 	}
116544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
116644961713Sgirish 	return (NXGE_OK);
116744961713Sgirish fail:
116844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
116952ccf843Smisaki 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
117044961713Sgirish 	return (NXGE_ERROR | rs);
117144961713Sgirish }
117244961713Sgirish 
117344961713Sgirish 
117400161856Syc /*
117500161856Syc  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
117600161856Syc  * support loopback like XPCS.
117700161856Syc  */
117844961713Sgirish nxge_status_t
117944961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
118044961713Sgirish {
118144961713Sgirish 	pcs_cfg_t		pcs_cfg;
118244961713Sgirish 	uint32_t		val;
118344961713Sgirish 	uint8_t			portn;
118444961713Sgirish 	nxge_port_mode_t	portmode;
118544961713Sgirish 	npi_handle_t		handle;
118644961713Sgirish 	p_nxge_stats_t		statsp;
118700161856Syc 	pcs_ctrl_t		pcs_ctrl;
118844961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
118900161856Syc 	uint8_t i;
119044961713Sgirish 
119144961713Sgirish 	handle = nxgep->npi_handle;
119244961713Sgirish 	portmode = nxgep->mac.portmode;
119344961713Sgirish 	portn = nxgep->mac.portnum;
119444961713Sgirish 	statsp = nxgep->statsp;
119544961713Sgirish 
119644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
119744961713Sgirish 
119800161856Syc 	if (portmode == PORT_1G_FIBER ||
119900161856Syc 	    portmode == PORT_1G_TN1010 ||
120000161856Syc 	    portmode == PORT_1G_SERDES) {
120100161856Syc 		if (portmode == PORT_1G_TN1010) {
120200161856Syc 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
120300161856Syc 			for (i = 0; i < 6; i ++) {
120400161856Syc 				if ((rs = npi_mac_pcs_reset(handle, portn))
120500161856Syc 				    != NPI_SUCCESS) {
120600161856Syc 					goto fail;
120700161856Syc 				}
120800161856Syc 			}
120900161856Syc 		} else {
121000161856Syc 			if ((rs = npi_mac_pcs_reset(handle, portn))
121100161856Syc 			    != NPI_SUCCESS)
121200161856Syc 				goto fail;
12132e59129aSraghus 		}
12142e59129aSraghus 
121544961713Sgirish 		/* Initialize port's PCS */
121644961713Sgirish 		pcs_cfg.value = 0;
121744961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
121844961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
121944961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
122044961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
122144961713Sgirish 
12222e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12232e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12242e59129aSraghus 		    portn, pcs_cfg.value));
122500161856Syc 
122600161856Syc 		if (portmode == PORT_1G_TN1010) {
122700161856Syc 			/*
122800161856Syc 			 * Must disable PCS auto-negotiation when the the driver
122900161856Syc 			 * is driving the TN1010 based XAUI card  Otherwise the
123000161856Syc 			 * autonegotiation between the PCS and the TN1010 PCS
123100161856Syc 			 * will never complete and the Neptune/NIU will not work
123200161856Syc 			 */
123300161856Syc 			pcs_ctrl.value = 0;
123400161856Syc 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
123500161856Syc 			    pcs_ctrl.value);
123600161856Syc 		}
123700161856Syc 	} else if (portmode == PORT_10G_FIBER ||
123800161856Syc 	    portmode == PORT_10G_COPPER ||
123900161856Syc 	    portmode == PORT_10G_TN1010 ||
12401c7408c9Stc 	    portmode == PORT_HSP_MODE ||
124100161856Syc 	    portmode == PORT_10G_SERDES) {
124244961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
124344961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
124444961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
124544961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
124644961713Sgirish 
124744961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
124844961713Sgirish 			goto fail;
124944961713Sgirish 
125044961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
125144961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
125252ccf843Smisaki 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
125344961713Sgirish 			goto fail;
125400161856Syc 
125544961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
125652ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
125744961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
125844961713Sgirish 		else
125944961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
126044961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
126152ccf843Smisaki 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
126244961713Sgirish 			goto fail;
126344961713Sgirish 
126444961713Sgirish 		/* Clear descw errors */
126544961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
126652ccf843Smisaki 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
126744961713Sgirish 			goto fail;
126844961713Sgirish 		/* Clear symbol errors */
126944961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
127052ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
127144961713Sgirish 			goto fail;
127244961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
127352ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
127444961713Sgirish 			goto fail;
127544961713Sgirish 
1276d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1277d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1278d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1279d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
128044961713Sgirish 		if (portn < 4) {
128144961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
128252ccf843Smisaki 			    PCS_DATAPATH_MODE_MII);
128344961713Sgirish 		}
128444961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
128544961713Sgirish 			goto fail;
128644961713Sgirish 
128744961713Sgirish 	} else {
128844961713Sgirish 		goto fail;
128944961713Sgirish 	}
129044961713Sgirish pass:
129144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
129244961713Sgirish 	return (NXGE_OK);
129344961713Sgirish fail:
129444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
129552ccf843Smisaki 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
129644961713Sgirish 	return (NXGE_ERROR | rs);
129744961713Sgirish }
129844961713Sgirish 
1299cb9d3ae6Smisaki /*
1300cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1301cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1302cb9d3ae6Smisaki  */
1303cb9d3ae6Smisaki nxge_status_t
1304cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1305cb9d3ae6Smisaki {
1306cb9d3ae6Smisaki 	uint8_t			portn;
1307cb9d3ae6Smisaki 	nxge_port_t		portt;
1308cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1309cb9d3ae6Smisaki 	npi_handle_t		handle;
1310cb9d3ae6Smisaki 	uint32_t		val;
1311cb9d3ae6Smisaki 
1312cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1313cb9d3ae6Smisaki 
1314cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1315cb9d3ae6Smisaki 	    portn));
1316cb9d3ae6Smisaki 
1317cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1318cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1319cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1320cb9d3ae6Smisaki 
1321cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
132200161856Syc 		/* Reading the current XMAC Config Register for XMAC */
1323cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1324cb9d3ae6Smisaki 
1325cb9d3ae6Smisaki 		/*
1326cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1327cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1328cb9d3ae6Smisaki 		 */
1329cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1330cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1331cb9d3ae6Smisaki 				/*
1332cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1333cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1334cb9d3ae6Smisaki 				 */
1335cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1336cb9d3ae6Smisaki 			} else {
1337cb9d3ae6Smisaki 				/*
1338cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1339cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1340cb9d3ae6Smisaki 				 * not supported.
1341cb9d3ae6Smisaki 				 */
1342cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1343cb9d3ae6Smisaki 			}
1344cb9d3ae6Smisaki 		} else {
13451bd6825cSml 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13461bd6825cSml 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13471bd6825cSml 			    portn));
1348cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13491bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13501bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13511bd6825cSml 				    "enable pause", portn));
1352cb9d3ae6Smisaki 				/*
1353cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1354cb9d3ae6Smisaki 				 * is 1, enable receive pause.
1355cb9d3ae6Smisaki 				 */
1356cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1357cb9d3ae6Smisaki 			} else {
1358cb9d3ae6Smisaki 				/*
1359cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1360cb9d3ae6Smisaki 				 * is 0, disable receive pause. Send pause is
1361cb9d3ae6Smisaki 				 * not supported
1362cb9d3ae6Smisaki 				 */
13631bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13641bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13651bd6825cSml 				    "disable pause", portn));
1366cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1367cb9d3ae6Smisaki 			}
1368cb9d3ae6Smisaki 		}
1369cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1370cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
137100161856Syc 		/* Reading the current MAC CTRL Config Register for BMAC */
1372cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1373cb9d3ae6Smisaki 
1374cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1375cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1376cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1377cb9d3ae6Smisaki 				/*
1378cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1379cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1380cb9d3ae6Smisaki 				 * is not supported
1381cb9d3ae6Smisaki 				 */
1382cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1383cb9d3ae6Smisaki 			} else {
1384cb9d3ae6Smisaki 				/*
1385cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1386cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1387cb9d3ae6Smisaki 				 * send pause.
1388cb9d3ae6Smisaki 				 */
1389cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1390cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1391cb9d3ae6Smisaki 			}
1392cb9d3ae6Smisaki 		} else {
1393cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1394cb9d3ae6Smisaki 				/*
1395cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1396cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1397cb9d3ae6Smisaki 				 * not supported.
1398cb9d3ae6Smisaki 				 */
1399cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1400cb9d3ae6Smisaki 			} else {
1401cb9d3ae6Smisaki 				/*
1402cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1403cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1404cb9d3ae6Smisaki 				 * either direction.
1405cb9d3ae6Smisaki 				 */
1406cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
140752ccf843Smisaki 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
1408cb9d3ae6Smisaki 			}
1409cb9d3ae6Smisaki 		}
1410cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1411cb9d3ae6Smisaki 	}
1412cb9d3ae6Smisaki 
1413cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1414cb9d3ae6Smisaki 	    portn));
1415cb9d3ae6Smisaki 
1416cb9d3ae6Smisaki 	return (NXGE_OK);
1417cb9d3ae6Smisaki }
1418cb9d3ae6Smisaki 
141944961713Sgirish /* Initialize the Internal Serdes */
142044961713Sgirish 
142144961713Sgirish nxge_status_t
142244961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
142344961713Sgirish {
142444961713Sgirish 	p_nxge_stats_t		statsp;
142544961713Sgirish #ifdef	NXGE_DEBUG
142644961713Sgirish 	uint8_t			portn;
142744961713Sgirish #endif
142844961713Sgirish 	nxge_status_t		status = NXGE_OK;
142944961713Sgirish 
143044961713Sgirish #ifdef	NXGE_DEBUG
143144961713Sgirish 	portn = nxgep->mac.portnum;
143244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
143359ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
143444961713Sgirish #endif
143544961713Sgirish 
143659ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
143759ac0c16Sdavemq 		statsp = nxgep->statsp;
143859ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
143959ac0c16Sdavemq 		if (status != NXGE_OK)
144044961713Sgirish 			goto fail;
144159ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
144244961713Sgirish 	}
144344961713Sgirish 
144444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
144559ac0c16Sdavemq 	    portn));
144644961713Sgirish 
144744961713Sgirish 	return (NXGE_OK);
144844961713Sgirish 
144944961713Sgirish fail:
145044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
145159ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
145259ac0c16Sdavemq 	    portn));
145344961713Sgirish 
145444961713Sgirish 	return (status);
145544961713Sgirish }
145644961713Sgirish 
145744961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
145844961713Sgirish 
145959ac0c16Sdavemq static nxge_status_t
146044961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
146144961713Sgirish {
146244961713Sgirish 	uint8_t portn;
146344961713Sgirish 	int chan;
146444961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
14652e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
146644961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
146744961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
146844961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
146944961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
14702e59129aSraghus #ifdef NXGE_DEBUG
14712e59129aSraghus 	esr_ti_testcfg_t cfg;
14722e59129aSraghus #endif
147344961713Sgirish 	esr_ti_testcfg_t test_cfg;
147444961713Sgirish 	nxge_status_t status = NXGE_OK;
147544961713Sgirish 
147644961713Sgirish 	portn = nxgep->mac.portnum;
147744961713Sgirish 
147844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
147952ccf843Smisaki 	    portn));
1480*4df55fdeSJanie Lu 	if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) {
1481*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1482*4df55fdeSJanie Lu 		    "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
1483*4df55fdeSJanie Lu 		return (nxge_n2_kt_serdes_init(nxgep));
1484*4df55fdeSJanie Lu 	}
148544961713Sgirish 
148644961713Sgirish 	tx_cfg_l.value = 0;
148744961713Sgirish 	tx_cfg_h.value = 0;
148844961713Sgirish 	rx_cfg_l.value = 0;
148944961713Sgirish 	rx_cfg_h.value = 0;
149044961713Sgirish 	pll_cfg_l.value = 0;
14912e59129aSraghus 	pll_sts_l.value = 0;
149244961713Sgirish 	test_cfg.value = 0;
149344961713Sgirish 
149400161856Syc 	/*
149500161856Syc 	 * If the nxge driver has been plumbed without a link, then it will
149600161856Syc 	 * detect a link up when a cable connecting to an anto-negotiation
149700161856Syc 	 * partner is plugged into the port. Because the TN1010 PHY supports
149800161856Syc 	 * both 1G and 10G speeds, the driver must re-configure the
149900161856Syc 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
150000161856Syc 	 * is called at the post-link-up reconfiguration time. Here it calls
150100161856Syc 	 * nxge_set_tn1010_param to set portmode before re-initializing
150200161856Syc 	 * the serdes.
150300161856Syc 	 */
150400161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
150500161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
150600161856Syc 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
150700161856Syc 			goto fail;
150800161856Syc 		}
150900161856Syc 	}
151000161856Syc 
151100161856Syc 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
151200161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
15131c7408c9Stc 	    nxgep->mac.portmode == PORT_HSP_MODE ||
151400161856Syc 	    nxgep->mac.portmode == PORT_10G_SERDES) {
151544961713Sgirish 		/* 0x0E01 */
151644961713Sgirish 		tx_cfg_l.bits.entx = 1;
151744961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
151844961713Sgirish 
151944961713Sgirish 		/* 0x9101 */
152044961713Sgirish 		rx_cfg_l.bits.enrx = 1;
152144961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
152244961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
152344961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
152444961713Sgirish 
152544961713Sgirish 		/* 0x0008 */
152644961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
152744961713Sgirish 
152844961713Sgirish 		/* Set loopback mode if necessary */
152944961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
153044961713Sgirish 			tx_cfg_l.bits.entest = 1;
153144961713Sgirish 			rx_cfg_l.bits.entest = 1;
153244961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
153344961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
153452ccf843Smisaki 			    ESR_N2_DEV_ADDR,
153552ccf843Smisaki 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
153644961713Sgirish 			goto fail;
153744961713Sgirish 		}
153844961713Sgirish 
153900161856Syc 		/* Initialize PLL for 10G */
154000161856Syc 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
154100161856Syc 		pll_cfg_l.bits.enpll = 1;
154200161856Syc 		pll_sts_l.bits.enpll = 1;
154300161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
154400161856Syc 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
154500161856Syc 			goto fail;
154600161856Syc 
154700161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
154800161856Syc 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
154900161856Syc 			goto fail;
155044961713Sgirish 
155100161856Syc #ifdef  NXGE_DEBUG
155200161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
155300161856Syc 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
155400161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
155500161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
155600161856Syc 		    portn, pll_cfg_l.value, cfg.value));
155744961713Sgirish 
155800161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
155900161856Syc 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
156000161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
156100161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
156200161856Syc 		    portn, pll_sts_l.value, cfg.value));
156300161856Syc #endif
156400161856Syc 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
156500161856Syc 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
156600161856Syc 	    nxgep->mac.portmode == PORT_1G_SERDES) {
156744961713Sgirish 		/* 0x0E21 */
156844961713Sgirish 		tx_cfg_l.bits.entx = 1;
156944961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
157044961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
157144961713Sgirish 
157244961713Sgirish 		/* 0x9121 */
157344961713Sgirish 		rx_cfg_l.bits.enrx = 1;
157444961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
157544961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
157644961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
157744961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
157844961713Sgirish 
15792e59129aSraghus 		if (portn == 0) {
15802e59129aSraghus 			/* 0x8 */
15812e59129aSraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15822e59129aSraghus 		}
158344961713Sgirish 
158400161856Syc 		/* Initialize PLL for 1G */
158544961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
158644961713Sgirish 		pll_cfg_l.bits.enpll = 1;
15872e59129aSraghus 		pll_sts_l.bits.enpll = 1;
158844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
158952ccf843Smisaki 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
159044961713Sgirish 			goto fail;
15912e59129aSraghus 
15922e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15932e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15942e59129aSraghus 			goto fail;
15952e59129aSraghus 
15962e59129aSraghus #ifdef  NXGE_DEBUG
15972e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15982e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15992e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16002e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
16012e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
16022e59129aSraghus 
16032e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
16042e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
16052e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16062e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
16072e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
16082e59129aSraghus #endif
16092e59129aSraghus 
16102e59129aSraghus 		/* Set loopback mode if necessary */
16112e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16122e59129aSraghus 			tx_cfg_l.bits.entest = 1;
16132e59129aSraghus 			rx_cfg_l.bits.entest = 1;
16142e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
16152e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16162e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
16172e59129aSraghus 			    portn, test_cfg.value));
16182e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
16192e59129aSraghus 			    ESR_N2_DEV_ADDR,
16202e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
16212e59129aSraghus 				goto fail;
16222e59129aSraghus 			}
16232e59129aSraghus 		}
162444961713Sgirish 	} else {
162544961713Sgirish 		goto fail;
162644961713Sgirish 	}
162744961713Sgirish 
162844961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
162944961713Sgirish 
163044961713Sgirish 	NXGE_DELAY(20);
163144961713Sgirish 
163244961713Sgirish 	/* init TX channels */
163344961713Sgirish 	for (chan = 0; chan < 4; chan++) {
163444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
163552ccf843Smisaki 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
163644961713Sgirish 			goto fail;
163744961713Sgirish 
163844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
163952ccf843Smisaki 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
164044961713Sgirish 			goto fail;
16412e59129aSraghus 
16422e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16432e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16442e59129aSraghus 		    portn, chan, tx_cfg_l.value));
16452e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16462e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16472e59129aSraghus 		    portn, chan, tx_cfg_h.value));
164844961713Sgirish 	}
164944961713Sgirish 
165044961713Sgirish 	/* init RX channels */
165144961713Sgirish 	for (chan = 0; chan < 4; chan++) {
165244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
165352ccf843Smisaki 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
165444961713Sgirish 			goto fail;
165544961713Sgirish 
165644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
165752ccf843Smisaki 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
165844961713Sgirish 			goto fail;
16592e59129aSraghus 
16602e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16612e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16622e59129aSraghus 		    portn, chan, rx_cfg_l.value));
166300161856Syc 
16642e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16652e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16662e59129aSraghus 		    portn, chan, rx_cfg_h.value));
166744961713Sgirish 	}
166844961713Sgirish 
166944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
167052ccf843Smisaki 	    portn));
167144961713Sgirish 
167244961713Sgirish 	return (NXGE_OK);
167344961713Sgirish fail:
16742d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16752d17280bSsbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16762d17280bSsbehera 	    portn));
167744961713Sgirish 
167844961713Sgirish 	return (status);
1679*4df55fdeSJanie Lu 
1680*4df55fdeSJanie Lu }
1681*4df55fdeSJanie Lu 
1682*4df55fdeSJanie Lu /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */
1683*4df55fdeSJanie Lu 
1684*4df55fdeSJanie Lu static nxge_status_t
1685*4df55fdeSJanie Lu nxge_n2_kt_serdes_init(p_nxge_t nxgep)
1686*4df55fdeSJanie Lu {
1687*4df55fdeSJanie Lu 	uint8_t portn;
1688*4df55fdeSJanie Lu 	int chan;
1689*4df55fdeSJanie Lu 	k_esr_ti_cfgpll_l_t pll_cfg_l;
1690*4df55fdeSJanie Lu 	k_esr_ti_cfgrx_l_t rx_cfg_l;
1691*4df55fdeSJanie Lu 	k_esr_ti_cfgrx_h_t rx_cfg_h;
1692*4df55fdeSJanie Lu 	k_esr_ti_cfgtx_l_t tx_cfg_l;
1693*4df55fdeSJanie Lu 	k_esr_ti_cfgtx_h_t tx_cfg_h;
1694*4df55fdeSJanie Lu #ifdef NXGE_DEBUG
1695*4df55fdeSJanie Lu 	k_esr_ti_testcfg_t cfg;
1696*4df55fdeSJanie Lu #endif
1697*4df55fdeSJanie Lu 	k_esr_ti_testcfg_t test_cfg;
1698*4df55fdeSJanie Lu 	nxge_status_t status = NXGE_OK;
1699*4df55fdeSJanie Lu 	boolean_t mode_1g = B_FALSE;
1700*4df55fdeSJanie Lu 
1701*4df55fdeSJanie Lu 	portn = nxgep->mac.portnum;
1702*4df55fdeSJanie Lu 
1703*4df55fdeSJanie Lu 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1704*4df55fdeSJanie Lu 	    "==> nxge_n2_kt_serdes_init port<%d>", portn));
1705*4df55fdeSJanie Lu 
1706*4df55fdeSJanie Lu 	tx_cfg_l.value = 0;
1707*4df55fdeSJanie Lu 	tx_cfg_h.value = 0;
1708*4df55fdeSJanie Lu 	rx_cfg_l.value = 0;
1709*4df55fdeSJanie Lu 	rx_cfg_h.value = 0;
1710*4df55fdeSJanie Lu 	pll_cfg_l.value = 0;
1711*4df55fdeSJanie Lu 	test_cfg.value = 0;
1712*4df55fdeSJanie Lu 
1713*4df55fdeSJanie Lu 	/*
1714*4df55fdeSJanie Lu 	 * The following setting assumes the reference clock frquency
1715*4df55fdeSJanie Lu 	 * is 156.25 MHz.
1716*4df55fdeSJanie Lu 	 */
1717*4df55fdeSJanie Lu 	/*
1718*4df55fdeSJanie Lu 	 * If the nxge driver has been plumbed without a link, then it will
1719*4df55fdeSJanie Lu 	 * detect a link up when a cable connecting to an anto-negotiation
1720*4df55fdeSJanie Lu 	 * partner is plugged into the port. Because the TN1010 PHY supports
1721*4df55fdeSJanie Lu 	 * both 1G and 10G speeds, the driver must re-configure the
1722*4df55fdeSJanie Lu 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
1723*4df55fdeSJanie Lu 	 * is called at the post-link-up reconfiguration time. Here it calls
1724*4df55fdeSJanie Lu 	 * nxge_set_tn1010_param to set portmode before re-initializing
1725*4df55fdeSJanie Lu 	 * the serdes.
1726*4df55fdeSJanie Lu 	 */
1727*4df55fdeSJanie Lu 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
1728*4df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_TN1010) {
1729*4df55fdeSJanie Lu 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
1730*4df55fdeSJanie Lu 			goto fail;
1731*4df55fdeSJanie Lu 		}
1732*4df55fdeSJanie Lu 	}
1733*4df55fdeSJanie Lu 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
1734*4df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
1735*4df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_SERDES) {
1736*4df55fdeSJanie Lu 		tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX;
1737*4df55fdeSJanie Lu 		/* 0x1e21 */
1738*4df55fdeSJanie Lu 		tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1739*4df55fdeSJanie Lu 		tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1740*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1741*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1742*4df55fdeSJanie Lu 		    portn, tx_cfg_l.value));
1743*4df55fdeSJanie Lu 
1744*4df55fdeSJanie Lu 		/* channel 0: enable syn. master */
1745*4df55fdeSJanie Lu 		/* 0x40 */
1746*4df55fdeSJanie Lu 		tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1747*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1748*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1749*4df55fdeSJanie Lu 		    portn, tx_cfg_h.value));
1750*4df55fdeSJanie Lu 		/* 0x4821 */
1751*4df55fdeSJanie Lu 		rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX;
1752*4df55fdeSJanie Lu 		rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1753*4df55fdeSJanie Lu 		rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1754*4df55fdeSJanie Lu 		rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1755*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1756*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1757*4df55fdeSJanie Lu 		    portn, rx_cfg_l.value));
1758*4df55fdeSJanie Lu 
1759*4df55fdeSJanie Lu 		/* 0x0008 */
1760*4df55fdeSJanie Lu 		rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE;
1761*4df55fdeSJanie Lu 
1762*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1763*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
1764*4df55fdeSJanie Lu 		    portn, rx_cfg_h.value));
1765*4df55fdeSJanie Lu 
1766*4df55fdeSJanie Lu 		/* Set loopback mode if necessary */
1767*4df55fdeSJanie Lu 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1768*4df55fdeSJanie Lu 			tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1769*4df55fdeSJanie Lu 			rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1770*4df55fdeSJanie Lu 			rx_cfg_l.bits.los = 0;
1771*4df55fdeSJanie Lu 
1772*4df55fdeSJanie Lu 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1773*4df55fdeSJanie Lu 			    "==> nxge_n2_kt_serdes_init port<%d>: "
1774*4df55fdeSJanie Lu 			    "loopback 0x%x", portn, tx_cfg_h.value));
1775*4df55fdeSJanie Lu 		}
1776*4df55fdeSJanie Lu 		/* 0xa1: Initialize PLL for 10G */
1777*4df55fdeSJanie Lu 		pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1778*4df55fdeSJanie Lu 		pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1779*4df55fdeSJanie Lu 
1780*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1781*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1782*4df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
1783*4df55fdeSJanie Lu 
1784*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1785*4df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
1786*4df55fdeSJanie Lu 			goto fail;
1787*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1788*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1789*4df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
1790*4df55fdeSJanie Lu #ifdef  NXGE_DEBUG
1791*4df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1792*4df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1793*4df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1794*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1795*4df55fdeSJanie Lu 		    "PLL cfg.l 0x%x (0x%x)",
1796*4df55fdeSJanie Lu 		    portn, pll_cfg_l.value, cfg.value));
1797*4df55fdeSJanie Lu 
1798*4df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1799*4df55fdeSJanie Lu 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1800*4df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1801*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1802*4df55fdeSJanie Lu 		    portn, cfg.value));
1803*4df55fdeSJanie Lu #endif
1804*4df55fdeSJanie Lu 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
1805*4df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
1806*4df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_1G_SERDES) {
1807*4df55fdeSJanie Lu 		mode_1g = B_TRUE;
1808*4df55fdeSJanie Lu 		/* 0x1e41 */
1809*4df55fdeSJanie Lu 		tx_cfg_l.bits.entx = 1;
1810*4df55fdeSJanie Lu 		tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1811*4df55fdeSJanie Lu 		tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
1812*4df55fdeSJanie Lu 
1813*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1814*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
1815*4df55fdeSJanie Lu 		    portn, tx_cfg_l.value));
1816*4df55fdeSJanie Lu 
1817*4df55fdeSJanie Lu 
1818*4df55fdeSJanie Lu 		/* channel 0: enable syn. master */
1819*4df55fdeSJanie Lu 		tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1820*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1821*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1822*4df55fdeSJanie Lu 		    portn, tx_cfg_h.value));
1823*4df55fdeSJanie Lu 
1824*4df55fdeSJanie Lu 
1825*4df55fdeSJanie Lu 		/* 0x4841 */
1826*4df55fdeSJanie Lu 		rx_cfg_l.bits.enrx = 1;
1827*4df55fdeSJanie Lu 		rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
1828*4df55fdeSJanie Lu 		rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
1829*4df55fdeSJanie Lu 		rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1830*4df55fdeSJanie Lu 
1831*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1832*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
1833*4df55fdeSJanie Lu 		    portn, rx_cfg_l.value));
1834*4df55fdeSJanie Lu 
1835*4df55fdeSJanie Lu 		/* 0x0008 */
1836*4df55fdeSJanie Lu 		rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF;
1837*4df55fdeSJanie Lu 
1838*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1839*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
1840*4df55fdeSJanie Lu 		    portn, rx_cfg_h.value));
1841*4df55fdeSJanie Lu 
1842*4df55fdeSJanie Lu 		/* 0xa1: Initialize PLL for 1G */
1843*4df55fdeSJanie Lu 		pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
1844*4df55fdeSJanie Lu 		pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1845*4df55fdeSJanie Lu 
1846*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1847*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
1848*4df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
1849*4df55fdeSJanie Lu 
1850*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1851*4df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
1852*4df55fdeSJanie Lu 		    != NXGE_OK)
1853*4df55fdeSJanie Lu 			goto fail;
1854*4df55fdeSJanie Lu 
1855*4df55fdeSJanie Lu 
1856*4df55fdeSJanie Lu #ifdef  NXGE_DEBUG
1857*4df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1858*4df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
1859*4df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1860*4df55fdeSJanie Lu 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
1861*4df55fdeSJanie Lu 		    portn, pll_cfg_l.value, cfg.value));
1862*4df55fdeSJanie Lu 
1863*4df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
1864*4df55fdeSJanie Lu 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
1865*4df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1866*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
1867*4df55fdeSJanie Lu 		    portn, cfg.value));
1868*4df55fdeSJanie Lu #endif
1869*4df55fdeSJanie Lu 
1870*4df55fdeSJanie Lu 		/* Set loopback mode if necessary */
1871*4df55fdeSJanie Lu 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1872*4df55fdeSJanie Lu 			tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
1873*4df55fdeSJanie Lu 
1874*4df55fdeSJanie Lu 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1875*4df55fdeSJanie Lu 			    "==> nxge_n2_kt_serdes_init port<%d>: "
1876*4df55fdeSJanie Lu 			    "loopback 0x%x", portn, test_cfg.value));
1877*4df55fdeSJanie Lu 			if ((status = nxge_mdio_write(nxgep, portn,
1878*4df55fdeSJanie Lu 			    ESR_N2_DEV_ADDR,
1879*4df55fdeSJanie Lu 			    ESR_N2_TX_CFG_L_REG_ADDR(0),
1880*4df55fdeSJanie Lu 			    tx_cfg_h.value)) != NXGE_OK) {
1881*4df55fdeSJanie Lu 				goto fail;
1882*4df55fdeSJanie Lu 			}
1883*4df55fdeSJanie Lu 		}
1884*4df55fdeSJanie Lu 	} else {
1885*4df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1886*4df55fdeSJanie Lu 		    "nxge_n2_kt_serdes_init:port<%d> - "
1887*4df55fdeSJanie Lu 		    "unsupported port mode %d",
1888*4df55fdeSJanie Lu 		    portn, nxgep->mac.portmode));
1889*4df55fdeSJanie Lu 		goto fail;
1890*4df55fdeSJanie Lu 	}
1891*4df55fdeSJanie Lu 
1892*4df55fdeSJanie Lu 	NXGE_DELAY(20);
1893*4df55fdeSJanie Lu 	/* Clear the test register (offset 0x8004) */
1894*4df55fdeSJanie Lu 	if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1895*4df55fdeSJanie Lu 	    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
1896*4df55fdeSJanie Lu 		goto fail;
1897*4df55fdeSJanie Lu 	}
1898*4df55fdeSJanie Lu 	NXGE_DELAY(20);
1899*4df55fdeSJanie Lu 
1900*4df55fdeSJanie Lu 	/* init TX channels */
1901*4df55fdeSJanie Lu 	for (chan = 0; chan < 4; chan++) {
1902*4df55fdeSJanie Lu 		if (mode_1g)
1903*4df55fdeSJanie Lu 			tx_cfg_l.value = 0;
1904*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1905*4df55fdeSJanie Lu 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
1906*4df55fdeSJanie Lu 			goto fail;
1907*4df55fdeSJanie Lu 
1908*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1909*4df55fdeSJanie Lu 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
1910*4df55fdeSJanie Lu 			goto fail;
1911*4df55fdeSJanie Lu 
1912*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1913*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1914*4df55fdeSJanie Lu 		    "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value));
1915*4df55fdeSJanie Lu 
1916*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1917*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1918*4df55fdeSJanie Lu 		    "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value));
1919*4df55fdeSJanie Lu 	}
1920*4df55fdeSJanie Lu 
1921*4df55fdeSJanie Lu 	/* init RX channels */
1922*4df55fdeSJanie Lu 	/* 1G mode only write to the first channel */
1923*4df55fdeSJanie Lu 	for (chan = 0; chan < 4; chan++) {
1924*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1925*4df55fdeSJanie Lu 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
1926*4df55fdeSJanie Lu 		    != NXGE_OK)
1927*4df55fdeSJanie Lu 			goto fail;
1928*4df55fdeSJanie Lu 
1929*4df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
1930*4df55fdeSJanie Lu 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
1931*4df55fdeSJanie Lu 		    != NXGE_OK)
1932*4df55fdeSJanie Lu 			goto fail;
1933*4df55fdeSJanie Lu 
1934*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1935*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1936*4df55fdeSJanie Lu 		    "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value));
1937*4df55fdeSJanie Lu 
1938*4df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1939*4df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
1940*4df55fdeSJanie Lu 		    "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value));
1941*4df55fdeSJanie Lu 	}
1942*4df55fdeSJanie Lu 
1943*4df55fdeSJanie Lu 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1944*4df55fdeSJanie Lu 	    "<== nxge_n2_kt_serdes_init port<%d>", portn));
1945*4df55fdeSJanie Lu 
1946*4df55fdeSJanie Lu 	return (NXGE_OK);
1947*4df55fdeSJanie Lu fail:
1948*4df55fdeSJanie Lu 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1949*4df55fdeSJanie Lu 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
1950*4df55fdeSJanie Lu 	    portn));
1951*4df55fdeSJanie Lu 
1952*4df55fdeSJanie Lu 	return (status);
195344961713Sgirish }
195444961713Sgirish 
195559ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
195644961713Sgirish 
195759ac0c16Sdavemq static nxge_status_t
195859ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
195944961713Sgirish {
196044961713Sgirish 	npi_handle_t		handle;
196144961713Sgirish 	uint8_t			portn;
1962321febdeSsbehera 	int			chan, i;
196344961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
196444961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
196544961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
196644961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
196744961713Sgirish 	uint64_t		val;
196844961713Sgirish 	uint16_t		val16l;
196944961713Sgirish 	uint16_t		val16h;
197044961713Sgirish 	nxge_status_t		status = NXGE_OK;
197144961713Sgirish 
197244961713Sgirish 	portn = nxgep->mac.portnum;
197344961713Sgirish 
197444961713Sgirish 	if ((portn != 0) && (portn != 1))
197544961713Sgirish 		return (NXGE_OK);
197644961713Sgirish 
197759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
197859ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
197944961713Sgirish 	handle = nxgep->npi_handle;
198059ac0c16Sdavemq 	switch (portn) {
198159ac0c16Sdavemq 	case 0:
19824202ea4bSsbehera 		/* Reset Serdes */
19834202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
19844202ea4bSsbehera 		NXGE_DELAY(20);
19854202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
19864202ea4bSsbehera 		NXGE_DELAY(2000);
19874202ea4bSsbehera 
19884202ea4bSsbehera 		/* Configure Serdes to 10G mode */
19894202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
19904202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
19914202ea4bSsbehera 
199259ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
199359ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
199459ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
199559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
199659ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
199759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
199859ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
199959ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
200059ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
200159ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
200259ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
200359ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
200459ac0c16Sdavemq 
200559ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
200659ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
200759ac0c16Sdavemq 			ESR_REG_WR(handle,
200859ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
200959ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
201059ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
201159ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
201259ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
201359ac0c16Sdavemq 		} else {
201459ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
201544961713Sgirish 		}
201659ac0c16Sdavemq 		break;
201759ac0c16Sdavemq 	case 1:
20184202ea4bSsbehera 		/* Reset Serdes */
20194202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
20204202ea4bSsbehera 		NXGE_DELAY(20);
20214202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
20224202ea4bSsbehera 		NXGE_DELAY(2000);
20234202ea4bSsbehera 
20244202ea4bSsbehera 		/* Configure Serdes to 10G mode */
20254202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
20264202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
20274202ea4bSsbehera 
202859ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
202959ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
203059ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
203159ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
203259ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
203359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
203459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
203559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
203659ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
203759ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
203859ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
203959ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
204059ac0c16Sdavemq 
204159ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
204259ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
204359ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
204459ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
204559ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
204659ac0c16Sdavemq 		} else {
204759ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
204844961713Sgirish 		}
204959ac0c16Sdavemq 		break;
205059ac0c16Sdavemq 	default:
205159ac0c16Sdavemq 		/* Nothing to do here */
205259ac0c16Sdavemq 		goto done;
205359ac0c16Sdavemq 	}
205444961713Sgirish 
205559ac0c16Sdavemq 	/* init TX RX channels */
205659ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
205759ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
205859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
205959ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
206044961713Sgirish 			goto fail;
206159ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
206259ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
206359ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
206444961713Sgirish 			goto fail;
206559ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
206659ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
206759ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
206859ac0c16Sdavemq 			goto fail;
206959ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
207059ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
207159ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
207259ac0c16Sdavemq 			goto fail;
207359ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
207459ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
207559ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
207659ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
207759ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
207859ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
207959ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
208044961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
208159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
208259ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
208344961713Sgirish 			goto fail;
208444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
208559ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
208659ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
208744961713Sgirish 			goto fail;
208859ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
208959ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
209059ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
209144961713Sgirish 			goto fail;
209259ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
209359ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
209459ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
209544961713Sgirish 			goto fail;
209644961713Sgirish 		}
209744961713Sgirish 
209859ac0c16Sdavemq 	/* Apply Tx core reset */
209959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
210059ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
210159ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
210259ac0c16Sdavemq 		goto fail;
210359ac0c16Sdavemq 
210459ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
210559ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
210659ac0c16Sdavemq 	    NXGE_OK)
210759ac0c16Sdavemq 		goto fail;
210859ac0c16Sdavemq 
210959ac0c16Sdavemq 	NXGE_DELAY(200);
211059ac0c16Sdavemq 
211159ac0c16Sdavemq 	/* Apply Rx core reset */
211259ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
211359ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
211459ac0c16Sdavemq 	    NXGE_OK)
211559ac0c16Sdavemq 		goto fail;
211659ac0c16Sdavemq 
211759ac0c16Sdavemq 	NXGE_DELAY(200);
211859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
211959ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
212059ac0c16Sdavemq 		goto fail;
212159ac0c16Sdavemq 
212259ac0c16Sdavemq 	NXGE_DELAY(200);
212359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
212459ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
212559ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
212659ac0c16Sdavemq 		goto fail;
212759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
212859ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
212959ac0c16Sdavemq 		goto fail;
213059ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
213159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2132d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2133d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
2134d81011f0Ssbehera 		    portn, val16l, val16h));
213559ac0c16Sdavemq 	}
213659ac0c16Sdavemq 
213759ac0c16Sdavemq 	if (portn == 0) {
2138321febdeSsbehera 		/* Wait for serdes to be ready */
2139321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2140321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2141321febdeSsbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
2142321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
2143321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P0 |
2144321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH3 |
2145321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH2 |
2146321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH1 |
2147321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
2148321febdeSsbehera 
2149321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2150321febdeSsbehera 			else
2151321febdeSsbehera 				break;
2152321febdeSsbehera 		}
2153321febdeSsbehera 
2154321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
2155ab6abb7aSjoycey 			/*
2156ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2157ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2158ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2159ab6abb7aSjoycey 			 * stays down
2160ab6abb7aSjoycey 			 */
2161321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2162321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
2163321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
216400161856Syc 				goto done;
216559ac0c16Sdavemq 		}
216659ac0c16Sdavemq 	} else if (portn == 1) {
2167321febdeSsbehera 		/* Wait for serdes to be ready */
2168321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2169321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2170321febdeSsbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
2171321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
2172321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P1 |
2173321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH3 |
2174321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH2 |
2175321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH1 |
2176321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
2177321febdeSsbehera 
2178321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2179321febdeSsbehera 			else
2180321febdeSsbehera 				break;
2181321febdeSsbehera 		}
2182321febdeSsbehera 
2183321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
2184ab6abb7aSjoycey 			/*
2185ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2186ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2187ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2188ab6abb7aSjoycey 			 * stays down
2189ab6abb7aSjoycey 			 */
2190321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2191321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
2192321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
219300161856Syc 				goto done;
219444961713Sgirish 		}
219544961713Sgirish 	}
219644961713Sgirish 
219744961713Sgirish done:
219859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
219959ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
220059ac0c16Sdavemq 
220144961713Sgirish 	return (NXGE_OK);
220244961713Sgirish fail:
22032d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
220459ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
220559ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
220644961713Sgirish 
220744961713Sgirish 	return (status);
220844961713Sgirish }
220944961713Sgirish 
221059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
221144961713Sgirish 
221259ac0c16Sdavemq static nxge_status_t
221359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
221444961713Sgirish {
221559ac0c16Sdavemq 	npi_handle_t		handle;
221659ac0c16Sdavemq 	uint8_t			portn;
2217d81011f0Ssbehera 	int			chan;
2218d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
2219d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
2220d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
2221d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
222259ac0c16Sdavemq 	uint64_t		val;
2223d81011f0Ssbehera 	uint16_t		val16l;
2224d81011f0Ssbehera 	uint16_t		val16h;
2225d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
222644961713Sgirish 
222744961713Sgirish 	portn = nxgep->mac.portnum;
222844961713Sgirish 
222959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
223059ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
223144961713Sgirish 
223259ac0c16Sdavemq 	handle = nxgep->npi_handle;
223344961713Sgirish 
223459ac0c16Sdavemq 	switch (portn) {
223559ac0c16Sdavemq 	case 0:
2236d81011f0Ssbehera 		/* Assert the reset register */
2237d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2238d81011f0Ssbehera 		val |= ESR_RESET_0;
2239d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2240d81011f0Ssbehera 
2241d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
2242d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2243d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
2244d81011f0Ssbehera 
2245d81011f0Ssbehera 		/* Set the control register to 0x249249f */
2246d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
2247d81011f0Ssbehera 
2248d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
2249d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2250d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
2251d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
2252d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
2253d81011f0Ssbehera 		} else {
2254d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2255d81011f0Ssbehera 		}
2256d81011f0Ssbehera 
2257d81011f0Ssbehera 		/* Deassert the reset register */
2258d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2259d81011f0Ssbehera 		val &= ~ESR_RESET_0;
2260d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
226159ac0c16Sdavemq 		break;
2262d81011f0Ssbehera 
226359ac0c16Sdavemq 	case 1:
2264d81011f0Ssbehera 		/* Assert the reset register */
2265d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2266d81011f0Ssbehera 		val |= ESR_RESET_1;
2267d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2268d81011f0Ssbehera 
2269d81011f0Ssbehera 		/* Set PLL register to 0x79 */
2270d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2271d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
2272d81011f0Ssbehera 
2273d81011f0Ssbehera 		/* Set the control register to 0x249249f */
2274d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
2275d81011f0Ssbehera 
2276d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
2277d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2278d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
2279d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2280d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
2281d81011f0Ssbehera 		} else {
2282d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2283d81011f0Ssbehera 		}
2284d81011f0Ssbehera 
2285d81011f0Ssbehera 		/* Deassert the reset register */
2286d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2287d81011f0Ssbehera 		val &= ~ESR_RESET_1;
2288d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
228959ac0c16Sdavemq 		break;
2290d81011f0Ssbehera 
229159ac0c16Sdavemq 	default:
2292d81011f0Ssbehera 		/* Nothing to do here */
2293d81011f0Ssbehera 		goto done;
2294d81011f0Ssbehera 	}
2295d81011f0Ssbehera 
2296d81011f0Ssbehera 	/* init TX RX channels */
2297d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
2298d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2299d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2300d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
2301d81011f0Ssbehera 			goto fail;
2302d81011f0Ssbehera 		}
2303d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2304d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2305d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
2306d81011f0Ssbehera 			goto fail;
2307d81011f0Ssbehera 		}
2308d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2309d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2310d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
2311d81011f0Ssbehera 			goto fail;
2312d81011f0Ssbehera 		}
2313d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2314d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2315d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
2316d81011f0Ssbehera 			goto fail;
2317d81011f0Ssbehera 		}
2318d81011f0Ssbehera 
2319d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
2320d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2321d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
2322d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
2323d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
2324d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2325d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2326d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2327d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2328d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
2329d81011f0Ssbehera 			goto fail;
2330d81011f0Ssbehera 		}
2331d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2332d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2333d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
2334d81011f0Ssbehera 			goto fail;
2335d81011f0Ssbehera 		}
2336d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2337d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2338d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
2339d81011f0Ssbehera 			goto fail;
2340d81011f0Ssbehera 		}
2341d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2342d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2343d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
2344d81011f0Ssbehera 			goto fail;
2345d81011f0Ssbehera 		}
2346d81011f0Ssbehera 	}
2347d81011f0Ssbehera 
2348d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2349d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2350d81011f0Ssbehera 		goto fail;
2351d81011f0Ssbehera 	}
2352d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2353d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2354d81011f0Ssbehera 		goto fail;
2355d81011f0Ssbehera 	}
2356d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2357d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2358d81011f0Ssbehera 		goto fail;
2359d81011f0Ssbehera 	}
2360d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2361d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
236259ac0c16Sdavemq 		goto fail;
236344961713Sgirish 	}
236444961713Sgirish 
2365d81011f0Ssbehera 	/* Apply Tx core reset */
2366d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2367d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2368d81011f0Ssbehera 		goto fail;
2369d81011f0Ssbehera 	}
2370d81011f0Ssbehera 
2371d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2372d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2373d81011f0Ssbehera 	    NXGE_OK) {
2374d81011f0Ssbehera 		goto fail;
2375d81011f0Ssbehera 	}
2376d81011f0Ssbehera 
2377d81011f0Ssbehera 	NXGE_DELAY(200);
2378d81011f0Ssbehera 
2379d81011f0Ssbehera 	/* Apply Rx core reset */
2380d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2381d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2382d81011f0Ssbehera 	    NXGE_OK) {
2383d81011f0Ssbehera 		goto fail;
2384d81011f0Ssbehera 	}
2385d81011f0Ssbehera 
2386d81011f0Ssbehera 	NXGE_DELAY(200);
2387d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2388d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2389d81011f0Ssbehera 		goto fail;
2390d81011f0Ssbehera 	}
2391d81011f0Ssbehera 
2392d81011f0Ssbehera 	NXGE_DELAY(200);
2393d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2394d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2395d81011f0Ssbehera 		goto fail;
2396d81011f0Ssbehera 	}
2397d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2398d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2399d81011f0Ssbehera 		goto fail;
2400d81011f0Ssbehera 	}
2401d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
2402d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2403d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2404d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2405d81011f0Ssbehera 		status = NXGE_ERROR;
2406d81011f0Ssbehera 		goto fail;
2407d81011f0Ssbehera 	}
2408d81011f0Ssbehera 
2409d81011f0Ssbehera 	NXGE_DELAY(200);
2410d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2411d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2412d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2413d81011f0Ssbehera 	    "val 0x%x", portn, val));
2414d81011f0Ssbehera 	if (portn == 0) {
2415d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2416d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2417ab6abb7aSjoycey 			/*
2418ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2419ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2420ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2421ab6abb7aSjoycey 			 * stays down
2422ab6abb7aSjoycey 			 */
2423d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2424ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2425ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
242600161856Syc 				goto done;
2427d81011f0Ssbehera 		}
2428d81011f0Ssbehera 	} else if (portn == 1) {
2429d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2430d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2431ab6abb7aSjoycey 			/*
2432ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2433ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2434ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2435ab6abb7aSjoycey 			 * stays down
2436ab6abb7aSjoycey 			 */
2437d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2438ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2439ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
244000161856Syc 				goto done;
244100161856Syc 
2442d81011f0Ssbehera 		}
2443d81011f0Ssbehera 	}
2444d81011f0Ssbehera done:
244559ac0c16Sdavemq 
244659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
244759ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
244844961713Sgirish 	return (NXGE_OK);
244959ac0c16Sdavemq fail:
2450d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
245159ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
245259ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
245359ac0c16Sdavemq 	    portn));
245459ac0c16Sdavemq 
2455d81011f0Ssbehera 	return (status);
245644961713Sgirish }
245744961713Sgirish 
24582d17280bSsbehera /* Initialize the BCM 8704 xcvr */
245944961713Sgirish 
246059ac0c16Sdavemq static nxge_status_t
24612d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
246244961713Sgirish {
246344961713Sgirish 	uint16_t		val;
246444961713Sgirish #ifdef	NXGE_DEBUG
246514ea4bb7Ssd 	uint8_t			portn;
246644961713Sgirish 	uint16_t		val1;
246744961713Sgirish #endif
246844961713Sgirish 	uint8_t			phy_port_addr;
246944961713Sgirish 	pmd_tx_control_t	tx_ctl;
247044961713Sgirish 	control_t		ctl;
247144961713Sgirish 	phyxs_control_t		phyxs_ctl;
247244961713Sgirish 	pcs_control_t		pcs_ctl;
247344961713Sgirish 	uint32_t		delay = 0;
247444961713Sgirish 	optics_dcntr_t		op_ctr;
247544961713Sgirish 	nxge_status_t		status = NXGE_OK;
247614ea4bb7Ssd #ifdef	NXGE_DEBUG
247744961713Sgirish 	portn = nxgep->mac.portnum;
247814ea4bb7Ssd #endif
24792d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
248059ac0c16Sdavemq 	    portn));
248144961713Sgirish 
248259ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
248359ac0c16Sdavemq 
248459ac0c16Sdavemq 	/* Reset the transceiver */
248559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
248659ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
248759ac0c16Sdavemq 		goto fail;
248859ac0c16Sdavemq 
248959ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
249059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
249159ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
249259ac0c16Sdavemq 		goto fail;
249359ac0c16Sdavemq 
249459ac0c16Sdavemq 	do {
249559ac0c16Sdavemq 		drv_usecwait(500);
249659ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
249759ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
249859ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
249959ac0c16Sdavemq 			goto fail;
250059ac0c16Sdavemq 		delay++;
250159ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
250259ac0c16Sdavemq 	if (delay == 100) {
250359ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
250459ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
250559ac0c16Sdavemq 		status = NXGE_ERROR;
250659ac0c16Sdavemq 		goto fail;
250759ac0c16Sdavemq 	}
250844961713Sgirish 
250959ac0c16Sdavemq 	/* Set to 0x7FBF */
251059ac0c16Sdavemq 	ctl.value = 0;
251159ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
251259ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
251359ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
251459ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
251559ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
251659ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
251759ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
251859ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
251959ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
252059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
252159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
252259ac0c16Sdavemq 	    != NXGE_OK)
252359ac0c16Sdavemq 		goto fail;
252459ac0c16Sdavemq 
252559ac0c16Sdavemq 	/* Set to 0x164 */
252659ac0c16Sdavemq 	tx_ctl.value = 0;
252759ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
252859ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
252959ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
253059ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
253159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
253259ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
253359ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
253459ac0c16Sdavemq 		goto fail;
253544961713Sgirish 	/*
253659ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
253759ac0c16Sdavemq 	 * back these registers twice after written.
253844961713Sgirish 	 */
253959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
254059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
254159ac0c16Sdavemq 	    != NXGE_OK)
254259ac0c16Sdavemq 		goto fail;
254344961713Sgirish 
254459ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
254559ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
254659ac0c16Sdavemq 	    != NXGE_OK)
254759ac0c16Sdavemq 		goto fail;
254844961713Sgirish 
254959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
255059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
255159ac0c16Sdavemq 	    != NXGE_OK)
255259ac0c16Sdavemq 		goto fail;
255344961713Sgirish 
255459ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
255559ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
255659ac0c16Sdavemq 	    != NXGE_OK)
255759ac0c16Sdavemq 		goto fail;
255844961713Sgirish 
255959ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
256059ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
256159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
256259ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
256359ac0c16Sdavemq 		goto fail;
2564cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2565cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
2566cb9d3ae6Smisaki 	} else {
2567cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x3;
2568cb9d3ae6Smisaki 	}
256959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
257059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
257159ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
257259ac0c16Sdavemq 		goto fail;
257344961713Sgirish 
257459ac0c16Sdavemq 	NXGE_DELAY(1000000);
257544961713Sgirish 
257659ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
257759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
257859ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
257959ac0c16Sdavemq 	    != NXGE_OK)
258059ac0c16Sdavemq 		goto fail;
258159ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
258259ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
258359ac0c16Sdavemq 	else
258459ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
258559ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
258659ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
258759ac0c16Sdavemq 	    != NXGE_OK)
258859ac0c16Sdavemq 		goto fail;
258944961713Sgirish 
259059ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
259159ac0c16Sdavemq 	if (status != NXGE_OK)
259259ac0c16Sdavemq 		goto fail;
259359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
259459ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
259559ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
259659ac0c16Sdavemq 	if (status != NXGE_OK)
259759ac0c16Sdavemq 		goto fail;
259859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
259959ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
260059ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
260159ac0c16Sdavemq 	if (status != NXGE_OK)
260259ac0c16Sdavemq 		goto fail;
260359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
260459ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
260544961713Sgirish 
260659ac0c16Sdavemq #ifdef	NXGE_DEBUG
260759ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
260859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
260959ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
261059ac0c16Sdavemq 	    &val);
261159ac0c16Sdavemq 	if (status != NXGE_OK)
261259ac0c16Sdavemq 		goto fail;
261344961713Sgirish 
261459ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
261552ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
261659ac0c16Sdavemq 	if (status != NXGE_OK)
261759ac0c16Sdavemq 		goto fail;
261844961713Sgirish 
261959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
262052ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
262159ac0c16Sdavemq 	if (status != NXGE_OK)
262259ac0c16Sdavemq 		goto fail;
262344961713Sgirish 
262459ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
262552ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
262659ac0c16Sdavemq 	if (status != NXGE_OK)
262759ac0c16Sdavemq 		goto fail;
262844961713Sgirish 
262959ac0c16Sdavemq 	if (val != 0x3FC) {
263059ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
263159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
263259ac0c16Sdavemq 			    "Cable not connected to peer or bad"
263359ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
263459ac0c16Sdavemq 		} else if (val == 0x639C) {
263559ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
263659ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
263759ac0c16Sdavemq 			    " on port<%d>\n", portn));
263859ac0c16Sdavemq 		}
263959ac0c16Sdavemq 	}
264059ac0c16Sdavemq #endif
264144961713Sgirish 
26422d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
26432d17280bSsbehera 	    portn));
26442d17280bSsbehera 	return (NXGE_OK);
26452d17280bSsbehera 
26462d17280bSsbehera fail:
26472d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26482d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
26492d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
26502d17280bSsbehera 	return (NXGE_ERROR);
26512d17280bSsbehera }
26522d17280bSsbehera 
26532d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
26542d17280bSsbehera 
26552d17280bSsbehera static nxge_status_t
26562d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
26572d17280bSsbehera {
26582d17280bSsbehera 	uint8_t			phy_port_addr;
26592d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
26602d17280bSsbehera 	pcs_control_t		pcs_ctl;
26612d17280bSsbehera 	uint32_t		delay = 0;
26622d17280bSsbehera 	optics_dcntr_t		op_ctr;
26632d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
26642d17280bSsbehera #ifdef	NXGE_DEBUG
26652d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
26662d17280bSsbehera #endif
26672d17280bSsbehera 
26682d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
26692d17280bSsbehera 	    portn));
26702d17280bSsbehera 
26712d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
26722d17280bSsbehera 
26732d17280bSsbehera 	/* Reset the transceiver */
26742d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
26752d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
26762d17280bSsbehera 		goto fail;
26772d17280bSsbehera 
26782d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
26792d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
26802d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
26812d17280bSsbehera 		goto fail;
26822d17280bSsbehera 	do {
26832d17280bSsbehera 		drv_usecwait(500);
26842d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
26852d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
26862d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
26872d17280bSsbehera 			goto fail;
26882d17280bSsbehera 		delay++;
26892d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
26902d17280bSsbehera 
26912d17280bSsbehera 	if (delay == 100) {
26922d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
26932d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
26942d17280bSsbehera 		status = NXGE_ERROR;
26952d17280bSsbehera 		goto fail;
26962d17280bSsbehera 	}
26972d17280bSsbehera 
26982d17280bSsbehera 	NXGE_DELAY(1000000);
26992d17280bSsbehera 
27002d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
27012d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
27022d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
27032d17280bSsbehera 	    != NXGE_OK)
27042d17280bSsbehera 		goto fail;
27052d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
27062d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
27072d17280bSsbehera 	else
27082d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
27092d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
27102d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
27112d17280bSsbehera 	    != NXGE_OK)
27122d17280bSsbehera 		goto fail;
27132d17280bSsbehera 
27142d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
27152d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
27162d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
27172d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
27182d17280bSsbehera 		goto fail;
27192d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
27202d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
27212d17280bSsbehera 
27222d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
27232d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
27242d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
27252d17280bSsbehera 		goto fail;
27262d17280bSsbehera 
27272d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
27282d17280bSsbehera 	    portn));
27292d17280bSsbehera 	return (NXGE_OK);
27302d17280bSsbehera 
27312d17280bSsbehera fail:
27322d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27332d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
27342d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
27352d17280bSsbehera 	return (status);
27362d17280bSsbehera }
27372d17280bSsbehera 
273852cdd236Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
273952cdd236Ssbehera 
274052cdd236Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
274152cdd236Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
274252cdd236Ssbehera 
274352cdd236Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
274452cdd236Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
274552cdd236Ssbehera 
274652cdd236Ssbehera 
274752cdd236Ssbehera static void
274852cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
274952cdd236Ssbehera {
275052cdd236Ssbehera 	uint16_t	value;
275152cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
275252cdd236Ssbehera 
275352cdd236Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
275452cdd236Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
275552cdd236Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
275652cdd236Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
275752cdd236Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
275852cdd236Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
275952cdd236Ssbehera 		    value);
276052cdd236Ssbehera 	}
276152cdd236Ssbehera }
276252cdd236Ssbehera 
276352cdd236Ssbehera static nxge_status_t
276452cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
276552cdd236Ssbehera {
276652cdd236Ssbehera 	nxge_status_t	status;
276752cdd236Ssbehera 	pcs_control_t	pcs_ctl;
276852cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
276952cdd236Ssbehera 
277052cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
277152cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
277252cdd236Ssbehera 
277352cdd236Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
277452cdd236Ssbehera 		pcs_ctl.bits.loopback = 1;
277552cdd236Ssbehera 	else
277652cdd236Ssbehera 		pcs_ctl.bits.loopback = 0;
277752cdd236Ssbehera 
277852cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
277952cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
278052cdd236Ssbehera 
278152cdd236Ssbehera fail:
278252cdd236Ssbehera 	return (status);
278352cdd236Ssbehera }
278452cdd236Ssbehera 
278552cdd236Ssbehera 
278652cdd236Ssbehera static void
278752cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
278852cdd236Ssbehera {
278952cdd236Ssbehera 	uint16_t	val2;
279052cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
279152cdd236Ssbehera 
279252cdd236Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
279352cdd236Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
279452cdd236Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
279552cdd236Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
279652cdd236Ssbehera 
279752cdd236Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
279852cdd236Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
279952cdd236Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
280052cdd236Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
280152cdd236Ssbehera 	}
280252cdd236Ssbehera }
280352cdd236Ssbehera 
280452cdd236Ssbehera 
280552cdd236Ssbehera static nxge_status_t
280652cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
280752cdd236Ssbehera {
280852cdd236Ssbehera 	uint8_t		phy;
280952cdd236Ssbehera 	nxge_status_t	status;
281052cdd236Ssbehera 	uint16_t	clk;
281152cdd236Ssbehera 
281252cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
281352cdd236Ssbehera 
281452cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
281552cdd236Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
281652cdd236Ssbehera 	    nxgep->mac.portnum, phy));
281752cdd236Ssbehera 
281852cdd236Ssbehera 	/* Set LED functions	*/
281952cdd236Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
282052cdd236Ssbehera 	/* PCS activity */
282152cdd236Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
282252cdd236Ssbehera 
282352cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
282452cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
282552cdd236Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
282652cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
282752cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
282852cdd236Ssbehera 
282952cdd236Ssbehera 	/* Set internal loopback mode if necessary */
283052cdd236Ssbehera 
283152cdd236Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
283252cdd236Ssbehera 
283352cdd236Ssbehera 	/* Enable PMD */
283452cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
283552cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
283652cdd236Ssbehera 
283752cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
283852cdd236Ssbehera 
283952cdd236Ssbehera fail:
284052cdd236Ssbehera 	return (status);
284152cdd236Ssbehera }
284252cdd236Ssbehera 
284352cdd236Ssbehera 
284452cdd236Ssbehera 
28452d17280bSsbehera /* Initialize the 10G Transceiver */
28462d17280bSsbehera 
28472d17280bSsbehera static nxge_status_t
28482d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
28492d17280bSsbehera {
28502d17280bSsbehera 	p_nxge_stats_t		statsp;
28511bd6825cSml 	p_nxge_param_t		param_arr = nxgep->param_arr;
28522d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
28532d17280bSsbehera #ifdef	NXGE_DEBUG
28542d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
28552d17280bSsbehera #endif
28562d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
28572d17280bSsbehera 	    portn));
28582d17280bSsbehera 
28592d17280bSsbehera 	statsp = nxgep->statsp;
28602d17280bSsbehera 
28611c7408c9Stc 	/* Disable Link LEDs, with or without PHY */
28621c7408c9Stc 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
28632d17280bSsbehera 		goto done;
28642d17280bSsbehera 
28651c7408c9Stc 	/* Skip MDIO, if PHY absent */
28661c7408c9Stc 	if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
28671c7408c9Stc 		goto done;
28681c7408c9Stc 	}
28692d17280bSsbehera 
28702d17280bSsbehera 	/* Set Clause 45 */
28712d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
28722d17280bSsbehera 
28732d17280bSsbehera 	switch (nxgep->chip_id) {
28742d17280bSsbehera 	case BCM8704_CHIP_ID:
287500161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
28762d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
28772d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
28782d17280bSsbehera 		break;
28792d17280bSsbehera 	case BCM8706_CHIP_ID:
288000161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
28812d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
28822d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
28832d17280bSsbehera 		break;
288452cdd236Ssbehera 	case MRVL88X201X_CHIP_ID:
288500161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
288652cdd236Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
288752cdd236Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
288852cdd236Ssbehera 		break;
28892d17280bSsbehera 	default:
28902d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
28912d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
28922d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
28932d17280bSsbehera 		goto fail;
28942d17280bSsbehera 	}
28952d17280bSsbehera 
28962d17280bSsbehera 	if (status != NXGE_OK) {
28972d17280bSsbehera 		goto fail;
28982d17280bSsbehera 	}
28992e59129aSraghus done:
290059ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
290159ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
29021bd6825cSml 	statsp->mac_stats.adv_cap_asmpause =
29031bd6825cSml 	    param_arr[param_anar_asmpause].value;
29041bd6825cSml 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
290544961713Sgirish 
290659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
290759ac0c16Sdavemq 	    portn));
290859ac0c16Sdavemq 	return (NXGE_OK);
290944961713Sgirish 
291059ac0c16Sdavemq fail:
29112d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
291259ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
29132d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
29142d17280bSsbehera 	return (NXGE_ERROR);
291559ac0c16Sdavemq }
291644961713Sgirish 
291759ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
291844961713Sgirish 
291959ac0c16Sdavemq static nxge_status_t
292059ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
292159ac0c16Sdavemq {
292259ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
292359ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
292459ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
292544961713Sgirish 
29262e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
29272e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
29282e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
29292e59129aSraghus 		goto done;
29302e59129aSraghus 	}
29312e59129aSraghus 
293259ac0c16Sdavemq 	/* Set Clause 22 */
293359ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
293444961713Sgirish 
293559ac0c16Sdavemq 	/* Set capability flags */
293659ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
29372e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
29382e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
29392e59129aSraghus 		statsp->mac_stats.cap_100fdx =
29402e59129aSraghus 		    param_arr[param_anar_100fdx].value;
29412e59129aSraghus 		statsp->mac_stats.cap_10fdx =
29422e59129aSraghus 		    param_arr[param_anar_10fdx].value;
29432e59129aSraghus 	}
294444961713Sgirish 
294559ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
29462e59129aSraghus done:
294759ac0c16Sdavemq 	return (status);
294859ac0c16Sdavemq }
294959ac0c16Sdavemq 
295000161856Syc /*
295100161856Syc  * Although the Teranetics copper transceiver (TN1010) does not need
295200161856Syc  * to be initialized by the driver for passing packets, this funtion
295300161856Syc  * initializes the members of nxgep->statsp->mac_stats struct for
295400161856Syc  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
295500161856Syc  * It also configures the TN1010 for PHY loopback to support SunVTS.
295600161856Syc  *
295700161856Syc  * TN1010 only has the option to disable advertisement for the 10G
295800161856Syc  * mode. So we can set it to either Dual Mode or 1G Only mode but
295900161856Syc  * can't set it to 10G Only mode.
296000161856Syc  *
296100161856Syc  * ndd -set command can set the following 6 speed/duplex related parameters.
296200161856Syc  *
296300161856Syc  * ----------------------------------------------------------------
296400161856Syc  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
296500161856Syc  * ----------------------------------------------------------------
296600161856Syc  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
296700161856Syc  * adv_10gfdx_cap
296800161856Syc  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
296900161856Syc  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
297000161856Syc  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
297100161856Syc  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
297200161856Syc  * ----------------------------------------------------------------
297300161856Syc  */
297400161856Syc static nxge_status_t
297500161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep)
297600161856Syc {
297700161856Syc 	p_nxge_param_t		param_arr;
297800161856Syc 	p_nxge_stats_t		statsp;
297900161856Syc 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
298000161856Syc 	uint16_t		speed;
298100161856Syc 	uint8_t			phy_port_addr;
298200161856Syc 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
298300161856Syc 	int			status = NXGE_OK;
298400161856Syc 
298500161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
298600161856Syc 
298700161856Syc 	param_arr	= nxgep->param_arr;
298800161856Syc 	statsp		= nxgep->statsp;
298900161856Syc 
299000161856Syc 	/*
299100161856Syc 	 * Initialize the xcvr statistics which are NOT controlled by ndd
299200161856Syc 	 */
299300161856Syc 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
299400161856Syc 	statsp->mac_stats.cap_100T4    = 0;
299500161856Syc 
299600161856Syc 	/*
299700161856Syc 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
299800161856Syc 	 * that function nxge_check_tn1010_link repeatedly invoked by the
299900161856Syc 	 * timer will update link_speed real time.
300000161856Syc 	 */
300100161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
300200161856Syc 		goto fail;
300300161856Syc 	}
300400161856Syc 	if (speed == TN1010_SPEED_1G) {
300500161856Syc 		statsp->mac_stats.cap_10gfdx = 0;
300600161856Syc 	} else {
300700161856Syc 		statsp->mac_stats.cap_10gfdx = 1;
300800161856Syc 	}
300900161856Syc 
301000161856Syc 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
301100161856Syc 	statsp->mac_stats.cap_1000fdx  = 1;
301200161856Syc 
301300161856Syc 	/* TN1010 is not able to operate in the following states */
301400161856Syc 	statsp->mac_stats.cap_1000hdx  = 0;
301500161856Syc 	statsp->mac_stats.cap_100fdx   = 0;
301600161856Syc 	statsp->mac_stats.cap_100hdx   = 0;
301700161856Syc 	statsp->mac_stats.cap_10fdx    = 0;
301800161856Syc 	statsp->mac_stats.cap_10hdx    = 0;
301900161856Syc 
302000161856Syc 	/* param_anar_pause can be modified by ndd -set */
302100161856Syc 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
302200161856Syc 
302300161856Syc 	/*
302400161856Syc 	 * The following 4 lines actually overwrites what ever the ndd command
302500161856Syc 	 * has set. For example, by command
302600161856Syc 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
302700161856Syc 	 * we could set param_arr[param_autoneg].value to n.  However, because
302800161856Syc 	 * here we assign constants to these parameters, whatever we set with
302900161856Syc 	 * the "ndd -set" command will be replaced. So command
303000161856Syc 	 *	kstat nxge:X | grep param
303100161856Syc 	 * will always show those constant values.  In other words, the
303200161856Syc 	 * "ndd -set" command can NOT change the values of these 4 parameters
303300161856Syc 	 * even though the command appears to be successful.
303400161856Syc 	 *
303500161856Syc 	 * Note: TN1010 auto negotiation is always enabled.
303600161856Syc 	 */
303700161856Syc 	statsp->mac_stats.adv_cap_autoneg
303800161856Syc 	    = param_arr[param_autoneg].value = 1;
303900161856Syc 	statsp->mac_stats.adv_cap_1000fdx
304000161856Syc 	    = param_arr[param_anar_1000fdx].value = 1;
304100161856Syc 	statsp->mac_stats.adv_cap_100fdx
304200161856Syc 	    = param_arr[param_anar_100fdx].value = 0;
304300161856Syc 	statsp->mac_stats.adv_cap_10fdx
304400161856Syc 	    = param_arr[param_anar_10fdx].value = 0;
304500161856Syc 
304600161856Syc 	/*
304700161856Syc 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
304800161856Syc 	 * defined in nxge_param_arr[], therefore they are not seen by the
304900161856Syc 	 * "ndd -get" command and can not be changed by ndd.  We just set
305000161856Syc 	 * them (both ndd param and kstat values) to constant 0 because TN1010
305100161856Syc 	 * does not support those speeds.
305200161856Syc 	 */
305300161856Syc 	statsp->mac_stats.adv_cap_100T4
305400161856Syc 	    = param_arr[param_anar_100T4].value = 0;
305500161856Syc 	statsp->mac_stats.adv_cap_1000hdx
305600161856Syc 	    = param_arr[param_anar_1000hdx].value = 0;
305700161856Syc 	statsp->mac_stats.adv_cap_100hdx
305800161856Syc 	    = param_arr[param_anar_100hdx].value = 0;
305900161856Syc 	statsp->mac_stats.adv_cap_10hdx
306000161856Syc 	    = param_arr[param_anar_10hdx].value = 0;
306100161856Syc 
306200161856Syc 	/*
306300161856Syc 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
306400161856Syc 	 * by ndd
306500161856Syc 	 */
306600161856Syc 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
306700161856Syc 
306800161856Syc 	/*
306900161856Syc 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
307000161856Syc 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
307100161856Syc 	 * "ndd -get" command and can not be changed by ndd. Here we do not
307200161856Syc 	 * assign a constant to it so the default value defined in
307300161856Syc 	 * nxge_param_arr[] will be used to set the parameter and
307400161856Syc 	 * will be shown by the kstat.
307500161856Syc 	 */
307600161856Syc 	statsp->mac_stats.adv_cap_asmpause
307700161856Syc 	    = param_arr[param_anar_asmpause].value;
307800161856Syc 
307900161856Syc 	/*
308000161856Syc 	 * Initialize the link statistics.
308100161856Syc 	 */
308200161856Syc 	statsp->mac_stats.link_T4 = 0;
308300161856Syc 	statsp->mac_stats.link_asmpause = 0;
308400161856Syc 	statsp->mac_stats.link_pause = 0;
308500161856Syc 	if (speed == TN1010_SPEED_1G) {
308600161856Syc 		statsp->mac_stats.link_speed = 1000;
308700161856Syc 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
308800161856Syc 		statsp->mac_stats.link_up = 1;
308900161856Syc 	} else {
309000161856Syc 		statsp->mac_stats.link_speed = 10000;
309100161856Syc 		statsp->mac_stats.link_duplex = 2;
309200161856Syc 		statsp->mac_stats.link_up = 1;
309300161856Syc 	}
309400161856Syc 
309500161856Syc 	/*
309600161856Syc 	 * Because TN1010 does not have a link partner register, to
309700161856Syc 	 * figure out the link partner's capabilities is tricky. Here we
309800161856Syc 	 * just set the kstat based on our knowledge about the partner
309900161856Syc 	 * (The partner must support auto-neg because auto-negotiation
310000161856Syc 	 * has completed, it must support 1G or 10G because that is the
310100161856Syc 	 * negotiated speed we are using.)
310200161856Syc 	 *
310300161856Syc 	 * Note: Current kstat does not show lp_cap_10gfdx and
310400161856Syc 	 *	lp_cap_10ghdx.
310500161856Syc 	 */
310600161856Syc 	if (speed == TN1010_SPEED_1G) {
310700161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 1;
310800161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 0;
310900161856Syc 	} else {
311000161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 0;
311100161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 1;
311200161856Syc 	}
311300161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
311400161856Syc 	statsp->mac_stats.lp_cap_1000hdx  = 0;
311500161856Syc 	statsp->mac_stats.lp_cap_100fdx   = 0;
311600161856Syc 	statsp->mac_stats.lp_cap_100hdx   = 0;
311700161856Syc 	statsp->mac_stats.lp_cap_10fdx    = 0;
311800161856Syc 	statsp->mac_stats.lp_cap_10hdx    = 0;
311900161856Syc 	statsp->mac_stats.lp_cap_10gfdx   = 0;
312000161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
312100161856Syc 	statsp->mac_stats.lp_cap_100T4    = 0;
312200161856Syc 	statsp->mac_stats.lp_cap_autoneg  = 1;
312300161856Syc 	statsp->mac_stats.lp_cap_asmpause = 0;
312400161856Syc 	statsp->mac_stats.lp_cap_pause    = 0;
312500161856Syc 
312600161856Syc 	/* Handle PHY loopback for SunVTS loopback test */
312700161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
312800161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
312900161856Syc 
313000161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
313100161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
313200161856Syc 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
313300161856Syc 		goto fail;
313400161856Syc 	}
313500161856Syc 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
313600161856Syc 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
313700161856Syc 		tn1010_pcs_ctrl.bits.loopback = 1;
313800161856Syc 	} else {
313900161856Syc 		tn1010_pcs_ctrl.bits.loopback = 0;
314000161856Syc 	}
314100161856Syc 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
314200161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
314300161856Syc 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
314400161856Syc 		goto fail;
314500161856Syc 	}
314600161856Syc 
314700161856Syc 	statsp->mac_stats.xcvr_inits++;
314800161856Syc 
314900161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
315000161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
315100161856Syc 	return (status);
315200161856Syc fail:
315300161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
315400161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
315500161856Syc 	return (status);
315600161856Syc }
315700161856Syc 
315859ac0c16Sdavemq /* Initialize transceiver */
315959ac0c16Sdavemq 
316059ac0c16Sdavemq nxge_status_t
316159ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
316259ac0c16Sdavemq {
316359ac0c16Sdavemq 	p_nxge_stats_t		statsp;
316459ac0c16Sdavemq #ifdef	NXGE_DEBUG
316559ac0c16Sdavemq 	uint8_t			portn;
316644961713Sgirish #endif
316744961713Sgirish 
316859ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
316959ac0c16Sdavemq #ifdef	NXGE_DEBUG
317059ac0c16Sdavemq 	portn = nxgep->mac.portnum;
317159ac0c16Sdavemq #endif
317259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
317359ac0c16Sdavemq 	statsp = nxgep->statsp;
317444961713Sgirish 
317559ac0c16Sdavemq 	/*
317600161856Syc 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
317700161856Syc 	 * modify mac_stats.
317859ac0c16Sdavemq 	 */
317959ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
318059ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
318159ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
318259ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
318359ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
318459ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
318559ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
318659ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
318759ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
318859ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
318959ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
319059ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
319159ac0c16Sdavemq 
319259ac0c16Sdavemq 	/*
319359ac0c16Sdavemq 	 * Initialize the link statistics.
319459ac0c16Sdavemq 	 */
319559ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
319659ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
319759ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
319844961713Sgirish 
319959ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
320059ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
320159ac0c16Sdavemq 		if (status != NXGE_OK)
320244961713Sgirish 			goto fail;
320359ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
320444961713Sgirish 	}
320544961713Sgirish 
320659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
320759ac0c16Sdavemq 	    portn));
320844961713Sgirish 	return (NXGE_OK);
320944961713Sgirish 
321044961713Sgirish fail:
321144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
321259ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
321359ac0c16Sdavemq 	    portn));
321444961713Sgirish 	return (status);
321544961713Sgirish }
321644961713Sgirish 
32172e59129aSraghus /* Look for transceiver type */
32182e59129aSraghus 
32192e59129aSraghus nxge_status_t
32202e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
32212e59129aSraghus {
3222d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
3223d81011f0Ssbehera 	    nxgep->mac.portnum));
32242e59129aSraghus 
32252e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
32262e59129aSraghus 		return (NXGE_ERROR);
32272e59129aSraghus 
32282e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
32292e59129aSraghus 		return (NXGE_ERROR);
32302e59129aSraghus 
32312e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
32322e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
32332e59129aSraghus 	return (NXGE_OK);
32342e59129aSraghus }
323544961713Sgirish 
323644961713Sgirish /* Initialize the TxMAC sub-block */
323744961713Sgirish 
323844961713Sgirish nxge_status_t
323944961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
324044961713Sgirish {
324144961713Sgirish 	npi_attr_t		ap;
324244961713Sgirish 	uint8_t			portn;
324344961713Sgirish 	nxge_port_mode_t	portmode;
324444961713Sgirish 	nxge_port_t		portt;
324544961713Sgirish 	npi_handle_t		handle;
324644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
324744961713Sgirish 
324844961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
324944961713Sgirish 	portt    = nxgep->mac.porttype;
325044961713Sgirish 	handle   = nxgep->npi_handle;
325144961713Sgirish 	portmode = nxgep->mac.portmode;
325244961713Sgirish 
325344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
325452ccf843Smisaki 	    portn));
325544961713Sgirish 	/* Set Max and Min Frame Size */
32561bd6825cSml 	/*
32571bd6825cSml 	 * Use maxframesize to configure the hardware maxframe size
325800161856Syc 	 * and minframesize to configure the hardware minframe size.
32591bd6825cSml 	 */
32601bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
32611bd6825cSml 	    "==> nxge_tx_mac_init: port<%d> "
32621bd6825cSml 	    "min framesize %d max framesize %d ",
32631bd6825cSml 	    nxgep->mac.minframesize,
32641bd6825cSml 	    nxgep->mac.maxframesize,
32651bd6825cSml 	    portn));
326644961713Sgirish 
32671bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
32681bd6825cSml 	    MAC_PORT_FRAME_SIZE,
32691bd6825cSml 	    nxgep->mac.minframesize,
32701bd6825cSml 	    nxgep->mac.maxframesize,
32711bd6825cSml 	    rs);
327244961713Sgirish 	if (rs != NPI_SUCCESS)
327344961713Sgirish 		goto fail;
327444961713Sgirish 
327544961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
327644961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
327752ccf843Smisaki 		    0)) != NPI_SUCCESS)
327844961713Sgirish 			goto fail;
327944961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
328044961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
32812e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
328200161856Syc 		    (portmode == PORT_10G_TN1010) ||
32831c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
32842e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
328544961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
328652ccf843Smisaki 			    XGMII_IPG_12_15, rs);
328744961713Sgirish 			if (rs != NPI_SUCCESS)
328844961713Sgirish 				goto fail;
328944961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
329044961713Sgirish 		} else {
329144961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
329252ccf843Smisaki 			    MII_GMII_IPG_12, rs);
329344961713Sgirish 			if (rs != NPI_SUCCESS)
329444961713Sgirish 				goto fail;
329544961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
329644961713Sgirish 		}
329744961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
329852ccf843Smisaki 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
329944961713Sgirish 			goto fail;
330044961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
330144961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
330244961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
330344961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
330444961713Sgirish 
330544961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
330652ccf843Smisaki 		    != NPI_SUCCESS)
330744961713Sgirish 			goto fail;
330844961713Sgirish 
330944961713Sgirish 	} else {
331044961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
331152ccf843Smisaki 		    0)) != NPI_SUCCESS)
331244961713Sgirish 			goto fail;
331344961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
331444961713Sgirish 
331544961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
331652ccf843Smisaki 		    rs);
331744961713Sgirish 		if (rs != NPI_SUCCESS)
331844961713Sgirish 			goto fail;
331944961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
332044961713Sgirish 
332144961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
332244961713Sgirish 		if (rs != NPI_SUCCESS)
332344961713Sgirish 			goto fail;
332444961713Sgirish 		nxgep->mac.pa_size = 0x7;
332544961713Sgirish 
332644961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
332752ccf843Smisaki 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
332844961713Sgirish 			goto fail;
332944961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
333044961713Sgirish 	}
333144961713Sgirish 
333244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
333352ccf843Smisaki 	    portn));
333444961713Sgirish 
333544961713Sgirish 	return (NXGE_OK);
333644961713Sgirish fail:
333744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
333852ccf843Smisaki 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
333944961713Sgirish 
334044961713Sgirish 	return (NXGE_ERROR | rs);
334144961713Sgirish }
334244961713Sgirish 
3343678453a8Sspeer 
334444961713Sgirish /* Initialize the RxMAC sub-block */
334544961713Sgirish 
334644961713Sgirish nxge_status_t
334744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
334844961713Sgirish {
334944961713Sgirish 	npi_attr_t		ap;
335044961713Sgirish 	uint32_t		i;
335144961713Sgirish 	uint16_t		hashtab_e;
335244961713Sgirish 	p_hash_filter_t		hash_filter;
335344961713Sgirish 	nxge_port_t		portt;
335444961713Sgirish 	uint8_t			portn;
335544961713Sgirish 	npi_handle_t		handle;
335644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
335744961713Sgirish 	uint16_t 		*addr16p;
335844961713Sgirish 	uint16_t 		addr0, addr1, addr2;
335944961713Sgirish 	xmac_rx_config_t	xconfig;
336044961713Sgirish 	bmac_rx_config_t	bconfig;
336144961713Sgirish 
336244961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
336344961713Sgirish 
336444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
336552ccf843Smisaki 	    portn));
336644961713Sgirish 	handle = nxgep->npi_handle;
336744961713Sgirish 	portt = nxgep->mac.porttype;
336844961713Sgirish 
336944961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
337044961713Sgirish 	addr0 = ntohs(addr16p[2]);
337144961713Sgirish 	addr1 = ntohs(addr16p[1]);
337244961713Sgirish 	addr2 = ntohs(addr16p[0]);
337344961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
337452ccf843Smisaki 	    rs);
337544961713Sgirish 
337644961713Sgirish 	if (rs != NPI_SUCCESS)
337744961713Sgirish 		goto fail;
337844961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
337944961713Sgirish 	if (rs != NPI_SUCCESS)
338044961713Sgirish 		goto fail;
338144961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
338244961713Sgirish 	if (rs != NPI_SUCCESS)
338344961713Sgirish 		goto fail;
338444961713Sgirish 
338544961713Sgirish 	/*
338644961713Sgirish 	 * Load the multicast hash filter bits.
338744961713Sgirish 	 */
338844961713Sgirish 	hash_filter = nxgep->hash_filter;
338944961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
339044961713Sgirish 		if (hash_filter != NULL) {
339144961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
339252ccf843Smisaki 			    (NMCFILTER_REGS - 1) - i];
339344961713Sgirish 		} else {
339444961713Sgirish 			hashtab_e = 0;
339544961713Sgirish 		}
339644961713Sgirish 
339744961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
339852ccf843Smisaki 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
339944961713Sgirish 			goto fail;
340044961713Sgirish 	}
340144961713Sgirish 
340244961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
340344961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
340452ccf843Smisaki 		    0)) != NPI_SUCCESS)
340544961713Sgirish 			goto fail;
340644961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
340744961713Sgirish 
340844961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
340944961713Sgirish 
341044961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
341152ccf843Smisaki 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
341252ccf843Smisaki 		    ~CFG_XMAC_RX_STRIP_CRC;
341344961713Sgirish 
341444961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
341544961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
341644961713Sgirish 
341744961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
341844961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
341944961713Sgirish 
342044961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
342144961713Sgirish 
342244961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
342352ccf843Smisaki 		    xconfig)) != NPI_SUCCESS)
342444961713Sgirish 			goto fail;
342544961713Sgirish 		nxgep->mac.rx_config = xconfig;
342644961713Sgirish 
342744961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
342844961713Sgirish 
342944961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
343052ccf843Smisaki 		    != NPI_SUCCESS)
343144961713Sgirish 			goto fail;
343244961713Sgirish 	} else {
343344961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
343444961713Sgirish 
343544961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
343652ccf843Smisaki 		    0) != NPI_SUCCESS)
343744961713Sgirish 			goto fail;
343844961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
343944961713Sgirish 
3440a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
344152ccf843Smisaki 		    ~CFG_BMAC_RX_STRIP_CRC;
344244961713Sgirish 
344344961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
344444961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
344544961713Sgirish 
344644961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
344744961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
344844961713Sgirish 
344944961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
345044961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
345152ccf843Smisaki 		    bconfig)) != NPI_SUCCESS)
345244961713Sgirish 			goto fail;
345344961713Sgirish 		nxgep->mac.rx_config = bconfig;
345444961713Sgirish 
345544961713Sgirish 		/* Always enable comparison of mac unique address */
345644961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
345752ccf843Smisaki 		    != NPI_SUCCESS)
345844961713Sgirish 			goto fail;
345944961713Sgirish 	}
346044961713Sgirish 
346144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
346252ccf843Smisaki 	    portn));
346344961713Sgirish 
346444961713Sgirish 	return (NXGE_OK);
346544961713Sgirish 
346644961713Sgirish fail:
346744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
346852ccf843Smisaki 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
346944961713Sgirish 
347044961713Sgirish 	return (NXGE_ERROR | rs);
347144961713Sgirish }
347244961713Sgirish 
347344961713Sgirish /* Enable TXMAC */
347444961713Sgirish 
347544961713Sgirish nxge_status_t
347644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
347744961713Sgirish {
347844961713Sgirish 	npi_handle_t	handle;
347944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
348044961713Sgirish 	nxge_status_t	status = NXGE_OK;
348144961713Sgirish 
348244961713Sgirish 	handle = nxgep->npi_handle;
348344961713Sgirish 
348444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
348552ccf843Smisaki 	    nxgep->mac.portnum));
348644961713Sgirish 
348744961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
348844961713Sgirish 		goto fail;
348944961713Sgirish 
349044961713Sgirish 	/* based on speed */
349144961713Sgirish 	nxgep->msg_min = ETHERMIN;
349244961713Sgirish 
349344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
349444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
349552ccf843Smisaki 		    CFG_XMAC_TX)) != NPI_SUCCESS)
349644961713Sgirish 			goto fail;
349744961713Sgirish 	} else {
349844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
349952ccf843Smisaki 		    CFG_BMAC_TX)) != NPI_SUCCESS)
350044961713Sgirish 			goto fail;
350144961713Sgirish 	}
350244961713Sgirish 
350344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
350452ccf843Smisaki 	    nxgep->mac.portnum));
350544961713Sgirish 
350644961713Sgirish 	return (NXGE_OK);
350744961713Sgirish fail:
350844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
350952ccf843Smisaki 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
351052ccf843Smisaki 	    nxgep->mac.portnum));
351144961713Sgirish 	if (rs != NPI_SUCCESS)
351244961713Sgirish 		return (NXGE_ERROR | rs);
351344961713Sgirish 	else
351444961713Sgirish 		return (status);
351544961713Sgirish }
351644961713Sgirish 
351744961713Sgirish /* Disable TXMAC */
351844961713Sgirish 
351944961713Sgirish nxge_status_t
352044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
352144961713Sgirish {
352244961713Sgirish 	npi_handle_t	handle;
352344961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
352444961713Sgirish 
3525678453a8Sspeer 	if (isLDOMguest(nxgep))
3526678453a8Sspeer 		return (NXGE_OK);
3527678453a8Sspeer 
352844961713Sgirish 	handle = nxgep->npi_handle;
352944961713Sgirish 
353044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
353152ccf843Smisaki 	    nxgep->mac.portnum));
353244961713Sgirish 
353344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
353444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
353552ccf843Smisaki 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
353644961713Sgirish 			goto fail;
353744961713Sgirish 	} else {
353844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
353952ccf843Smisaki 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
354044961713Sgirish 			goto fail;
354144961713Sgirish 	}
354244961713Sgirish 
354344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
354452ccf843Smisaki 	    nxgep->mac.portnum));
354544961713Sgirish 	return (NXGE_OK);
354644961713Sgirish fail:
354744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
354852ccf843Smisaki 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
354952ccf843Smisaki 	    nxgep->mac.portnum));
355044961713Sgirish 	return (NXGE_ERROR | rs);
355144961713Sgirish }
355244961713Sgirish 
355344961713Sgirish /* Enable RXMAC */
355444961713Sgirish 
355544961713Sgirish nxge_status_t
355644961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
355744961713Sgirish {
355844961713Sgirish 	npi_handle_t	handle;
355944961713Sgirish 	uint8_t 	portn;
356044961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
356144961713Sgirish 	nxge_status_t	status = NXGE_OK;
356244961713Sgirish 
3563678453a8Sspeer 	/* This is a service-domain-only activity. */
3564678453a8Sspeer 	if (isLDOMguest(nxgep))
3565678453a8Sspeer 		return (status);
3566678453a8Sspeer 
356744961713Sgirish 	handle = nxgep->npi_handle;
356844961713Sgirish 	portn = nxgep->mac.portnum;
356944961713Sgirish 
357044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
357152ccf843Smisaki 	    portn));
357244961713Sgirish 
357344961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
357444961713Sgirish 		goto fail;
357544961713Sgirish 
357644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
357744961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
3578678453a8Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
357944961713Sgirish 			goto fail;
358044961713Sgirish 	} else {
358144961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
3582678453a8Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
358344961713Sgirish 			goto fail;
358444961713Sgirish 	}
358544961713Sgirish 
3586678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3587678453a8Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
358844961713Sgirish 
358944961713Sgirish 	return (NXGE_OK);
359044961713Sgirish fail:
359144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3592678453a8Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
359344961713Sgirish 
359444961713Sgirish 	if (rs != NPI_SUCCESS)
359544961713Sgirish 		return (NXGE_ERROR | rs);
359644961713Sgirish 	else
359744961713Sgirish 		return (status);
359844961713Sgirish }
359944961713Sgirish 
360044961713Sgirish /* Disable RXMAC */
360144961713Sgirish 
360244961713Sgirish nxge_status_t
360344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
360444961713Sgirish {
360544961713Sgirish 	npi_handle_t	handle;
360644961713Sgirish 	uint8_t		portn;
360744961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
360844961713Sgirish 
3609678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
3610678453a8Sspeer 	if (isLDOMguest(nxgep))
3611678453a8Sspeer 		return (NXGE_OK);
3612678453a8Sspeer 
361344961713Sgirish 	handle = nxgep->npi_handle;
361444961713Sgirish 	portn = nxgep->mac.portnum;
361544961713Sgirish 
361644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
361752ccf843Smisaki 	    portn));
361844961713Sgirish 
361944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
362044961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
362152ccf843Smisaki 		    CFG_XMAC_RX)) != NPI_SUCCESS)
362244961713Sgirish 			goto fail;
362344961713Sgirish 	} else {
362444961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
362552ccf843Smisaki 		    CFG_BMAC_RX)) != NPI_SUCCESS)
362644961713Sgirish 			goto fail;
362744961713Sgirish 	}
362844961713Sgirish 
362944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
363052ccf843Smisaki 	    portn));
363144961713Sgirish 	return (NXGE_OK);
363244961713Sgirish fail:
363344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
363452ccf843Smisaki 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
363544961713Sgirish 
363644961713Sgirish 	return (NXGE_ERROR | rs);
363744961713Sgirish }
363844961713Sgirish 
363944961713Sgirish /* Reset TXMAC */
364044961713Sgirish 
364144961713Sgirish nxge_status_t
364244961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
364344961713Sgirish {
364444961713Sgirish 	npi_handle_t	handle;
364544961713Sgirish 	uint8_t		portn;
364644961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
364744961713Sgirish 
364844961713Sgirish 	handle = nxgep->npi_handle;
364944961713Sgirish 	portn = nxgep->mac.portnum;
365044961713Sgirish 
365144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
365252ccf843Smisaki 	    portn));
365344961713Sgirish 
365444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
365544961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
365644961713Sgirish 		    != NPI_SUCCESS)
365744961713Sgirish 			goto fail;
365844961713Sgirish 	} else {
365944961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
366052ccf843Smisaki 		    != NPI_SUCCESS)
366144961713Sgirish 			goto fail;
366244961713Sgirish 	}
366344961713Sgirish 
366444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
366552ccf843Smisaki 	    portn));
366644961713Sgirish 
366744961713Sgirish 	return (NXGE_OK);
366844961713Sgirish fail:
366944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
367052ccf843Smisaki 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
367144961713Sgirish 
367244961713Sgirish 	return (NXGE_ERROR | rs);
367344961713Sgirish }
367444961713Sgirish 
367544961713Sgirish /* Reset RXMAC */
367644961713Sgirish 
367744961713Sgirish nxge_status_t
367844961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
367944961713Sgirish {
368044961713Sgirish 	npi_handle_t	handle;
368144961713Sgirish 	uint8_t		portn;
368244961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
368344961713Sgirish 
368444961713Sgirish 	handle = nxgep->npi_handle;
368544961713Sgirish 	portn = nxgep->mac.portnum;
368644961713Sgirish 
368744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
368852ccf843Smisaki 	    portn));
368944961713Sgirish 
369044961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
369144961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
369244961713Sgirish 		    != NPI_SUCCESS)
369344961713Sgirish 		goto fail;
369444961713Sgirish 	} else {
369544961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
369652ccf843Smisaki 		    != NPI_SUCCESS)
369744961713Sgirish 		goto fail;
369844961713Sgirish 	}
369944961713Sgirish 
370044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
370152ccf843Smisaki 	    portn));
370244961713Sgirish 
370359ac0c16Sdavemq 	return (NXGE_OK);
370459ac0c16Sdavemq fail:
370559ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
370652ccf843Smisaki 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
370759ac0c16Sdavemq 	return (NXGE_ERROR | rs);
370859ac0c16Sdavemq }
370959ac0c16Sdavemq 
371059ac0c16Sdavemq /* 10G fiber link interrupt start routine */
371159ac0c16Sdavemq 
371259ac0c16Sdavemq static nxge_status_t
371359ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
371459ac0c16Sdavemq {
371559ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
371659ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
371759ac0c16Sdavemq 
371859ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
371959ac0c16Sdavemq 
372059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
372159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
372259ac0c16Sdavemq 	else
372359ac0c16Sdavemq 		return (NXGE_OK);
372459ac0c16Sdavemq }
372559ac0c16Sdavemq 
372659ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
372759ac0c16Sdavemq 
372859ac0c16Sdavemq static nxge_status_t
372959ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
373059ac0c16Sdavemq {
373159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
373259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
373359ac0c16Sdavemq 
373459ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
373559ac0c16Sdavemq 
373659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
373759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
373859ac0c16Sdavemq 	else
373959ac0c16Sdavemq 		return (NXGE_OK);
374059ac0c16Sdavemq }
374159ac0c16Sdavemq 
374259ac0c16Sdavemq /* 1G fiber link interrupt start routine */
374359ac0c16Sdavemq 
374459ac0c16Sdavemq static nxge_status_t
374559ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
374659ac0c16Sdavemq {
374759ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
374859ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
374959ac0c16Sdavemq 
375059ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
375159ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
375259ac0c16Sdavemq 		return (NXGE_ERROR | rs);
375359ac0c16Sdavemq 	else
375459ac0c16Sdavemq 		return (NXGE_OK);
375559ac0c16Sdavemq }
375659ac0c16Sdavemq 
375759ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
375859ac0c16Sdavemq 
375959ac0c16Sdavemq static nxge_status_t
376059ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
376159ac0c16Sdavemq {
376259ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
376359ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
376459ac0c16Sdavemq 
376559ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
376659ac0c16Sdavemq 
376759ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
376859ac0c16Sdavemq 		return (NXGE_ERROR | rs);
376959ac0c16Sdavemq 	else
377059ac0c16Sdavemq 		return (NXGE_OK);
377159ac0c16Sdavemq }
377259ac0c16Sdavemq 
377359ac0c16Sdavemq /* 1G copper link interrupt start routine */
377459ac0c16Sdavemq 
377559ac0c16Sdavemq static nxge_status_t
377659ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
377759ac0c16Sdavemq {
377859ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
377959ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
378059ac0c16Sdavemq 
378159ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
37826b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
378359ac0c16Sdavemq 
378459ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
378559ac0c16Sdavemq 		return (NXGE_ERROR | rs);
378659ac0c16Sdavemq 	else
378759ac0c16Sdavemq 		return (NXGE_OK);
378844961713Sgirish }
378944961713Sgirish 
379059ac0c16Sdavemq /* 1G copper link interrupt stop routine */
379159ac0c16Sdavemq 
379259ac0c16Sdavemq static nxge_status_t
379359ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
379459ac0c16Sdavemq {
379559ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
379659ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
379759ac0c16Sdavemq 
379859ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
379959ac0c16Sdavemq 
380059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
380159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
380259ac0c16Sdavemq 	else
380359ac0c16Sdavemq 		return (NXGE_OK);
380459ac0c16Sdavemq }
380544961713Sgirish 
380659ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
380744961713Sgirish 
380844961713Sgirish nxge_status_t
380944961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
381044961713Sgirish {
381159ac0c16Sdavemq 	uint8_t		portn;
381259ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
381344961713Sgirish 
381444961713Sgirish 	portn = nxgep->mac.portnum;
381544961713Sgirish 
381644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
381759ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
381859ac0c16Sdavemq 		return (NXGE_OK);
381944961713Sgirish 
382059ac0c16Sdavemq 	if (enable == LINK_INTR_START)
382159ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
382259ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
382359ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
382459ac0c16Sdavemq 	if (status != NXGE_OK)
382559ac0c16Sdavemq 		goto fail;
382644961713Sgirish 
382744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
382844961713Sgirish 
382944961713Sgirish 	return (NXGE_OK);
383044961713Sgirish fail:
383144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
383252ccf843Smisaki 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
383344961713Sgirish 
383459ac0c16Sdavemq 	return (status);
383544961713Sgirish }
383644961713Sgirish 
383744961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
383844961713Sgirish 
383944961713Sgirish nxge_status_t
384044961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
384144961713Sgirish {
384244961713Sgirish 	p_nxge_param_t	param_arr;
384344961713Sgirish 	p_nxge_stats_t	statsp;
384444961713Sgirish 	uint8_t		xcvr_portn;
384544961713Sgirish 	p_mii_regs_t	mii_regs;
384644961713Sgirish 	mii_bmcr_t	bmcr;
384744961713Sgirish 	mii_bmsr_t	bmsr;
384844961713Sgirish 	mii_anar_t	anar;
384944961713Sgirish 	mii_gcr_t	gcr;
385044961713Sgirish 	mii_esr_t	esr;
385144961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
385244961713Sgirish 	int		status = NXGE_OK;
385344961713Sgirish 
385444961713Sgirish 	uint_t delay;
385544961713Sgirish 
385644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
385744961713Sgirish 
385844961713Sgirish 	param_arr = nxgep->param_arr;
385944961713Sgirish 	statsp = nxgep->statsp;
386044961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
386144961713Sgirish 
386244961713Sgirish 	mii_regs = NULL;
386344961713Sgirish 
386444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
386552ccf843Smisaki 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
386644961713Sgirish 
3867d81011f0Ssbehera 	/*
3868d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
3869d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
3870d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
3871d81011f0Ssbehera 	 */
3872d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
3873d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3874d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
3875d81011f0Ssbehera 	}
3876d81011f0Ssbehera 
387744961713Sgirish 	/*
387844961713Sgirish 	 * Reset the transceiver.
387944961713Sgirish 	 */
388044961713Sgirish 	delay = 0;
388144961713Sgirish 	bmcr.value = 0;
388244961713Sgirish 	bmcr.bits.reset = 1;
388344961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3884adfcba55Sjoycey #if defined(__i386)
388552ccf843Smisaki 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
3886adfcba55Sjoycey #else
388752ccf843Smisaki 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
3888adfcba55Sjoycey #endif
388952ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
389044961713Sgirish 		goto fail;
389144961713Sgirish 	do {
389244961713Sgirish 		drv_usecwait(500);
389344961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3894adfcba55Sjoycey #if defined(__i386)
389552ccf843Smisaki 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
3896adfcba55Sjoycey #else
389752ccf843Smisaki 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
3898adfcba55Sjoycey #endif
389952ccf843Smisaki 		    &bmcr.value)) != NXGE_OK)
390044961713Sgirish 			goto fail;
390144961713Sgirish 		delay++;
390244961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
390344961713Sgirish 	if (delay == 1000) {
390444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
390544961713Sgirish 		goto fail;
390644961713Sgirish 	}
390744961713Sgirish 
390844961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3909adfcba55Sjoycey #if defined(__i386)
391052ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3911adfcba55Sjoycey #else
391252ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3913adfcba55Sjoycey #endif
391452ccf843Smisaki 	    &bmsr.value)) != NXGE_OK)
391544961713Sgirish 		goto fail;
391644961713Sgirish 
391744961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
391844961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
391944961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
392044961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
392144961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
392244961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
392344961713Sgirish 
392444961713Sgirish 	/*
392558324dfcSspeer 	 * Initialize the xcvr statistics.
392644961713Sgirish 	 */
392744961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
392844961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
392944961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
393044961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
393144961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
393244961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
393344961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
393444961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
393544961713Sgirish 
393644961713Sgirish 	/*
393700161856Syc 	 * Initialize the xcvr advertised capability statistics.
393844961713Sgirish 	 */
393944961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
394044961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
394144961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
394244961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
394344961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
394444961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
394544961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
394644961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
394744961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
394852ccf843Smisaki 	    param_arr[param_anar_asmpause].value;
394944961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
395044961713Sgirish 
395144961713Sgirish 
395244961713Sgirish 	/*
395344961713Sgirish 	 * Check for extended status just in case we're
395444961713Sgirish 	 * running a Gigibit phy.
395544961713Sgirish 	 */
395644961713Sgirish 	if (bmsr.bits.extend_status) {
395744961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3958adfcba55Sjoycey #if defined(__i386)
395952ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->esr),
3960adfcba55Sjoycey #else
396152ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->esr),
3962adfcba55Sjoycey #endif
396352ccf843Smisaki 		    &esr.value)) != NXGE_OK)
396444961713Sgirish 			goto fail;
396552ccf843Smisaki 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
396644961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
396744961713Sgirish 
396844961713Sgirish 		statsp->mac_stats.cap_1000fdx =
396952ccf843Smisaki 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
397044961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
397144961713Sgirish 	} else {
397244961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
397344961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
397444961713Sgirish 	}
397544961713Sgirish 
397644961713Sgirish 	/*
397744961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
397844961713Sgirish 	 */
397944961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
398044961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
398144961713Sgirish 
398244961713Sgirish 	/*
398300161856Syc 	 * Initialize the link statistics.
398444961713Sgirish 	 */
398544961713Sgirish 	statsp->mac_stats.link_T4 = 0;
398644961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
398744961713Sgirish 	statsp->mac_stats.link_pause = 0;
398844961713Sgirish 	statsp->mac_stats.link_speed = 0;
398944961713Sgirish 	statsp->mac_stats.link_duplex = 0;
399044961713Sgirish 	statsp->mac_stats.link_up = 0;
399144961713Sgirish 
399244961713Sgirish 	/*
399344961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
399444961713Sgirish 	 */
399544961713Sgirish 	bmcr.value = 0;
399644961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3997adfcba55Sjoycey #if defined(__i386)
399852ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3999adfcba55Sjoycey #else
400052ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4001adfcba55Sjoycey #endif
400252ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
400344961713Sgirish 		goto fail;
400444961713Sgirish 
400544961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
400652ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
400744961713Sgirish 		bmcr.bits.loopback = 1;
400844961713Sgirish 		bmcr.bits.enable_autoneg = 0;
400944961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
401044961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
401144961713Sgirish 		bmcr.bits.duplex_mode = 1;
401244961713Sgirish 		param_arr[param_autoneg].value = 0;
401344961713Sgirish 	} else {
401444961713Sgirish 		bmcr.bits.loopback = 0;
401544961713Sgirish 	}
401644961713Sgirish 
401744961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
401852ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
401952ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
402044961713Sgirish 		param_arr[param_autoneg].value = 0;
402144961713Sgirish 		bcm5464r_aux.value = 0;
402244961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
402344961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
402444961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
402552ccf843Smisaki 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
402644961713Sgirish 			goto fail;
402744961713Sgirish 	}
402844961713Sgirish 
402900161856Syc 	/* If auto-negotiation is desired */
403044961713Sgirish 	if (param_arr[param_autoneg].value) {
403144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
403252ccf843Smisaki 		    "Restarting Auto-negotiation."));
403344961713Sgirish 		/*
403444961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
403544961713Sgirish 		 */
403644961713Sgirish 		anar.value = 0;
403744961713Sgirish 		anar.bits.selector = 1;
403844961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
403944961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
404044961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
404144961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
404244961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
404344961713Sgirish 		anar.bits.cap_asmpause = 0;
404444961713Sgirish 		anar.bits.cap_pause = 0;
404544961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
404652ccf843Smisaki 		    param_arr[param_anar_100fdx].value ||
404752ccf843Smisaki 		    param_arr[param_anar_10fdx].value) {
404844961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
404944961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
405044961713Sgirish 		}
405144961713Sgirish 
405200161856Syc 		/* Write to the auto-negotiation advertisement register */
405344961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4054adfcba55Sjoycey #if defined(__i386)
405552ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->anar),
4056adfcba55Sjoycey #else
405752ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->anar),
4058adfcba55Sjoycey #endif
405952ccf843Smisaki 		    anar.value)) != NXGE_OK)
406044961713Sgirish 			goto fail;
406144961713Sgirish 		if (bmsr.bits.extend_status) {
406244961713Sgirish 			gcr.value = 0;
406344961713Sgirish 			gcr.bits.ms_mode_en =
406452ccf843Smisaki 			    param_arr[param_master_cfg_enable].value;
406544961713Sgirish 			gcr.bits.master =
406652ccf843Smisaki 			    param_arr[param_master_cfg_value].value;
406744961713Sgirish 			gcr.bits.link_1000fdx =
406852ccf843Smisaki 			    param_arr[param_anar_1000fdx].value;
406944961713Sgirish 			gcr.bits.link_1000hdx =
407052ccf843Smisaki 			    param_arr[param_anar_1000hdx].value;
407144961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4072adfcba55Sjoycey #if defined(__i386)
407352ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
4074adfcba55Sjoycey #else
407552ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
4076adfcba55Sjoycey #endif
407752ccf843Smisaki 			    gcr.value)) != NXGE_OK)
407844961713Sgirish 				goto fail;
407944961713Sgirish 		}
408044961713Sgirish 
408144961713Sgirish 		bmcr.bits.enable_autoneg = 1;
408244961713Sgirish 		bmcr.bits.restart_autoneg = 1;
408344961713Sgirish 
408444961713Sgirish 	} else {
408544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
408644961713Sgirish 		bmcr.bits.speed_1000_sel =
408752ccf843Smisaki 		    param_arr[param_anar_1000fdx].value |
408852ccf843Smisaki 		    param_arr[param_anar_1000hdx].value;
408944961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
409052ccf843Smisaki 		    (param_arr[param_anar_100fdx].value |
409152ccf843Smisaki 		    param_arr[param_anar_100hdx].value);
409200161856Syc 
409300161856Syc 		/* Force to 1G */
409444961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
409544961713Sgirish 			statsp->mac_stats.link_speed = 1000;
409644961713Sgirish 			gcr.value = 0;
409744961713Sgirish 			gcr.bits.ms_mode_en =
409852ccf843Smisaki 			    param_arr[param_master_cfg_enable].value;
409944961713Sgirish 			gcr.bits.master =
410052ccf843Smisaki 			    param_arr[param_master_cfg_value].value;
410144961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4102adfcba55Sjoycey #if defined(__i386)
410352ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
4104adfcba55Sjoycey #else
410552ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
4106adfcba55Sjoycey #endif
410752ccf843Smisaki 			    gcr.value)) != NXGE_OK)
410844961713Sgirish 				goto fail;
410944961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
411044961713Sgirish 				bmcr.bits.duplex_mode = 1;
411144961713Sgirish 				statsp->mac_stats.link_duplex = 2;
411244961713Sgirish 			} else
411344961713Sgirish 				statsp->mac_stats.link_duplex = 1;
411400161856Syc 
411500161856Syc 		/* Force to 100M */
411644961713Sgirish 		} else if (bmcr.bits.speed_sel) {
411744961713Sgirish 			statsp->mac_stats.link_speed = 100;
411844961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
411944961713Sgirish 				bmcr.bits.duplex_mode = 1;
412044961713Sgirish 				statsp->mac_stats.link_duplex = 2;
412144961713Sgirish 			} else
412244961713Sgirish 				statsp->mac_stats.link_duplex = 1;
412300161856Syc 
412400161856Syc 		/* Force to 10M */
412544961713Sgirish 		} else {
412644961713Sgirish 			statsp->mac_stats.link_speed = 10;
412744961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
412844961713Sgirish 				bmcr.bits.duplex_mode = 1;
412944961713Sgirish 				statsp->mac_stats.link_duplex = 2;
413044961713Sgirish 			} else
413144961713Sgirish 				statsp->mac_stats.link_duplex = 1;
413244961713Sgirish 		}
413344961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
413444961713Sgirish 			statsp->mac_stats.link_asmpause =
413552ccf843Smisaki 			    statsp->mac_stats.cap_asmpause;
413644961713Sgirish 			statsp->mac_stats.link_pause =
413752ccf843Smisaki 			    statsp->mac_stats.cap_pause;
413844961713Sgirish 		}
413944961713Sgirish 
414044961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
414152ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
414252ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
414344961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
414444961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
414544961713Sgirish 				gcr.value = 0;
414644961713Sgirish 				gcr.bits.ms_mode_en = 1;
414744961713Sgirish 				gcr.bits.master = 1;
414844961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
4149adfcba55Sjoycey #if defined(__i386)
415052ccf843Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
4151adfcba55Sjoycey #else
415252ccf843Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
4153adfcba55Sjoycey #endif
415452ccf843Smisaki 				    gcr.value)) != NXGE_OK)
415544961713Sgirish 					goto fail;
415644961713Sgirish 				bmcr.value = 0;
415744961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
415844961713Sgirish 				statsp->mac_stats.link_speed = 1000;
415944961713Sgirish 			} else if (statsp->port_stats.lb_mode
416044961713Sgirish 			    == nxge_lb_ext100) {
416144961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
416244961713Sgirish 				bmcr.value = 0;
416344961713Sgirish 				bmcr.bits.speed_sel = 1;
416444961713Sgirish 				bmcr.bits.duplex_mode = 1;
416544961713Sgirish 				statsp->mac_stats.link_speed = 100;
416644961713Sgirish 			} else if (statsp->port_stats.lb_mode
416744961713Sgirish 			    == nxge_lb_ext10) {
416844961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
416944961713Sgirish 				bmcr.value = 0;
417044961713Sgirish 				bmcr.bits.duplex_mode = 1;
417144961713Sgirish 				statsp->mac_stats.link_speed = 10;
417244961713Sgirish 			}
417344961713Sgirish 		}
417444961713Sgirish 	}
417544961713Sgirish 
417644961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4177adfcba55Sjoycey #if defined(__i386)
417852ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4179adfcba55Sjoycey #else
418052ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4181adfcba55Sjoycey #endif
418252ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
418344961713Sgirish 		goto fail;
418444961713Sgirish 
418544961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4186adfcba55Sjoycey #if defined(__i386)
418752ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4188adfcba55Sjoycey #else
418952ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4190adfcba55Sjoycey #endif
419152ccf843Smisaki 	    &bmcr.value)) != NXGE_OK)
419244961713Sgirish 		goto fail;
419344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
419444961713Sgirish 
419544961713Sgirish 	/*
419644961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
419744961713Sgirish 	 */
419844961713Sgirish 	nxgep->soft_bmsr.value = 0;
419944961713Sgirish 
420044961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4201adfcba55Sjoycey #if defined(__i386)
420252ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4203adfcba55Sjoycey #else
420452ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4205adfcba55Sjoycey #endif
420652ccf843Smisaki 	    &nxgep->bmsr.value)) != NXGE_OK)
420744961713Sgirish 		goto fail;
420844961713Sgirish 
420944961713Sgirish 	statsp->mac_stats.xcvr_inits++;
421044961713Sgirish 	nxgep->bmsr.value = 0;
421144961713Sgirish 
421244961713Sgirish fail:
421344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
421452ccf843Smisaki 	    "<== nxge_mii_xcvr_init status 0x%x", status));
421544961713Sgirish 	return (status);
421644961713Sgirish }
421744961713Sgirish 
4218d81011f0Ssbehera nxge_status_t
4219d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
4220d81011f0Ssbehera {
4221d81011f0Ssbehera 	p_nxge_param_t	param_arr;
4222d81011f0Ssbehera 	p_nxge_stats_t	statsp;
4223d81011f0Ssbehera 	uint8_t		xcvr_portn;
4224d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
4225d81011f0Ssbehera 	mii_bmcr_t	bmcr;
4226d81011f0Ssbehera 	mii_bmsr_t	bmsr;
4227d81011f0Ssbehera 	mii_gcr_t	gcr;
4228d81011f0Ssbehera 	mii_esr_t	esr;
4229d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
4230d81011f0Ssbehera 	int		status = NXGE_OK;
4231d81011f0Ssbehera 
4232d81011f0Ssbehera 	uint_t delay;
4233d81011f0Ssbehera 
4234d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
4235d81011f0Ssbehera 
4236d81011f0Ssbehera 	param_arr = nxgep->param_arr;
4237d81011f0Ssbehera 	statsp = nxgep->statsp;
4238d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
4239d81011f0Ssbehera 
4240d81011f0Ssbehera 	mii_regs = NULL;
4241d81011f0Ssbehera 
4242d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4243d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
4244d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
4245d81011f0Ssbehera 
4246d81011f0Ssbehera 	/*
4247d81011f0Ssbehera 	 * Reset the transceiver.
4248d81011f0Ssbehera 	 */
4249d81011f0Ssbehera 	delay = 0;
4250d81011f0Ssbehera 	bmcr.value = 0;
4251d81011f0Ssbehera 	bmcr.bits.reset = 1;
4252d81011f0Ssbehera 
4253d81011f0Ssbehera #if defined(__i386)
4254d81011f0Ssbehera 
4255d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4256d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4257d81011f0Ssbehera 		goto fail;
4258d81011f0Ssbehera #else
4259d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4260d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4261d81011f0Ssbehera 		goto fail;
4262d81011f0Ssbehera #endif
4263d81011f0Ssbehera 	do {
4264d81011f0Ssbehera 		drv_usecwait(500);
4265d81011f0Ssbehera #if defined(__i386)
4266d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4267d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
4268d81011f0Ssbehera 		    != NXGE_OK)
4269d81011f0Ssbehera 			goto fail;
4270d81011f0Ssbehera #else
4271d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4272d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
4273d81011f0Ssbehera 		    != NXGE_OK)
4274d81011f0Ssbehera 			goto fail;
4275d81011f0Ssbehera #endif
4276d81011f0Ssbehera 		delay++;
4277d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
4278d81011f0Ssbehera 	if (delay == 1000) {
4279d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4280d81011f0Ssbehera 		goto fail;
4281d81011f0Ssbehera 	}
4282d81011f0Ssbehera 
4283d81011f0Ssbehera #if defined(__i386)
4284d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4285d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4286d81011f0Ssbehera 		goto fail;
4287d81011f0Ssbehera #else
4288d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4289d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4290d81011f0Ssbehera 		goto fail;
4291d81011f0Ssbehera #endif
4292d81011f0Ssbehera 
4293d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4294d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
4295d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
4296d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
4297d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
4298d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
4299d81011f0Ssbehera 
4300d81011f0Ssbehera 	/*
4301d81011f0Ssbehera 	 * Initialize the xcvr statistics.
4302d81011f0Ssbehera 	 */
4303d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4304d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
4305d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
4306d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
4307d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
4308d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
4309d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4310d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4311d81011f0Ssbehera 
4312d81011f0Ssbehera 	/*
4313d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
4314d81011f0Ssbehera 	 */
4315d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4316d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4317d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4318d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4319d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4320d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4321d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4322d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4323d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
4324d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
4325d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4326d81011f0Ssbehera 
4327d81011f0Ssbehera 	/*
4328d81011f0Ssbehera 	 * Check for extended status just in case we're
4329d81011f0Ssbehera 	 * running a Gigibit phy.
4330d81011f0Ssbehera 	 */
4331d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
4332d81011f0Ssbehera #if defined(__i386)
4333d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4334d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
4335d81011f0Ssbehera 		    NXGE_OK)
4336d81011f0Ssbehera 			goto fail;
4337d81011f0Ssbehera #else
4338d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4339d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
4340d81011f0Ssbehera 		    NXGE_OK)
4341d81011f0Ssbehera 			goto fail;
4342d81011f0Ssbehera #endif
4343d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
4344d81011f0Ssbehera 		    esr.bits.link_1000fdx;
4345d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4346d81011f0Ssbehera 
4347d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
4348d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4349d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
4350d81011f0Ssbehera 	} else {
4351d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
4352d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4353d81011f0Ssbehera 	}
4354d81011f0Ssbehera 
4355d81011f0Ssbehera 	/*
4356d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
4357d81011f0Ssbehera 	 */
4358d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4359d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4360d81011f0Ssbehera 
4361d81011f0Ssbehera 	/*
4362d81011f0Ssbehera 	 * Initialize the link statistics.
4363d81011f0Ssbehera 	 */
4364d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
4365d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
4366d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
4367d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
4368d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
4369d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
4370d81011f0Ssbehera 
4371d81011f0Ssbehera 	/*
4372d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
4373d81011f0Ssbehera 	 */
4374d81011f0Ssbehera 	bmcr.value = 0;
4375d81011f0Ssbehera #if defined(__i386)
4376d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4377d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4378d81011f0Ssbehera 		goto fail;
4379d81011f0Ssbehera #else
4380d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4381d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4382d81011f0Ssbehera 		goto fail;
4383d81011f0Ssbehera #endif
4384d81011f0Ssbehera 
4385d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4386d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4387d81011f0Ssbehera 		bmcr.bits.loopback = 1;
4388d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
4389d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4390d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
4391d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
4392d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4393d81011f0Ssbehera 	} else {
4394d81011f0Ssbehera 		bmcr.bits.loopback = 0;
4395d81011f0Ssbehera 	}
4396d81011f0Ssbehera 
4397d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
4398d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4399d81011f0Ssbehera 		bcm5464r_aux.value = 0;
4400d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
4401d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
4402d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4403d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4404d81011f0Ssbehera 			goto fail;
4405d81011f0Ssbehera 	}
4406d81011f0Ssbehera 
4407d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
4408d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
4409d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
4410d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
4411d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
4412d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
4413d81011f0Ssbehera 
4414d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
4415d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
4416d81011f0Ssbehera 		gcr.value = 0;
4417d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
4418d81011f0Ssbehera 		gcr.bits.master = 1;
4419d81011f0Ssbehera #if defined(__i386)
4420d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4421d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
4422d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4423d81011f0Ssbehera 			goto fail;
4424d81011f0Ssbehera #else
4425d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4426d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
4427d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4428d81011f0Ssbehera 			goto fail;
4429d81011f0Ssbehera #endif
4430d81011f0Ssbehera 		bmcr.value = 0;
4431d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
4432d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
4433d81011f0Ssbehera 	}
4434d81011f0Ssbehera 
4435d81011f0Ssbehera #if defined(__i386)
4436d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4437d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4438d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4439d81011f0Ssbehera 		goto fail;
4440d81011f0Ssbehera #else
4441d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4442d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4443d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4444d81011f0Ssbehera 		goto fail;
4445d81011f0Ssbehera #endif
4446d81011f0Ssbehera 
4447d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4448d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
4449d81011f0Ssbehera 	    bmcr.value));
4450d81011f0Ssbehera 
4451d81011f0Ssbehera #if defined(__i386)
4452d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4453d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4454d81011f0Ssbehera 		goto fail;
4455d81011f0Ssbehera #else
4456d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4457d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4458d81011f0Ssbehera 		goto fail;
4459d81011f0Ssbehera #endif
4460d81011f0Ssbehera 
4461d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4462d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
4463d81011f0Ssbehera 
4464d81011f0Ssbehera 	/*
4465d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
4466d81011f0Ssbehera 	 */
4467d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
4468d81011f0Ssbehera #if defined(__i386)
4469d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4470d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4471d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4472d81011f0Ssbehera 		goto fail;
4473d81011f0Ssbehera #else
4474d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4475d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4476d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4477d81011f0Ssbehera 		goto fail;
4478d81011f0Ssbehera #endif
4479d81011f0Ssbehera 
4480d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
4481d81011f0Ssbehera 	nxgep->bmsr.value = 0;
4482d81011f0Ssbehera 
4483d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4484d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4485d81011f0Ssbehera 	return (status);
4486d81011f0Ssbehera 
4487d81011f0Ssbehera fail:
4488d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4489d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4490d81011f0Ssbehera 	return (status);
4491d81011f0Ssbehera }
4492d81011f0Ssbehera 
449344961713Sgirish /* Read from a MII compliant register */
449444961713Sgirish 
449544961713Sgirish nxge_status_t
449644961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
449744961713Sgirish 		uint16_t *value)
449844961713Sgirish {
449944961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
450044961713Sgirish 
450144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
450252ccf843Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
450344961713Sgirish 
4504321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
450544961713Sgirish 
4506d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4507d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
450844961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
450952ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
451044961713Sgirish 			goto fail;
45112e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
45122e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
451344961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
451452ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
451544961713Sgirish 			goto fail;
451644961713Sgirish 	} else
451744961713Sgirish 		goto fail;
451844961713Sgirish 
4519321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
452044961713Sgirish 
452144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
452252ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
452344961713Sgirish 	return (NXGE_OK);
452444961713Sgirish fail:
4525321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
452644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
452752ccf843Smisaki 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
452844961713Sgirish 
452944961713Sgirish 	return (NXGE_ERROR | rs);
453044961713Sgirish }
453144961713Sgirish 
453244961713Sgirish /* Write to a MII compliant Register */
453344961713Sgirish 
453444961713Sgirish nxge_status_t
453544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
453644961713Sgirish 		uint16_t value)
453744961713Sgirish {
453844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
453944961713Sgirish 
454044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
454152ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
454244961713Sgirish 
4543321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
454444961713Sgirish 
4545d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4546d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
454744961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
454852ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
454944961713Sgirish 			goto fail;
45502e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
45512e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
455244961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
455352ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
455444961713Sgirish 			goto fail;
455544961713Sgirish 	} else
455644961713Sgirish 		goto fail;
455744961713Sgirish 
4558321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
455944961713Sgirish 
456044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
456152ccf843Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
456244961713Sgirish 	return (NXGE_OK);
456344961713Sgirish fail:
4564321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
456544961713Sgirish 
456644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
456752ccf843Smisaki 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
456844961713Sgirish 
456944961713Sgirish 	return (NXGE_ERROR | rs);
457044961713Sgirish }
457144961713Sgirish 
457200161856Syc /*
457300161856Syc  * Perform write to Clause45 serdes / transceiver device
457400161856Syc  * Arguments:
457500161856Syc  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
457600161856Syc  *			number if nxge_mdio_write is used for accessing the
457700161856Syc  *			internal LSIL serdes. Otherwise PHYAD is different
457800161856Syc  * 			for different platforms.
457900161856Syc  *	device:		With each PHYAD, the driver can use MDIO to control
458000161856Syc  *			multiple devices inside the PHY, here "device" is an
458100161856Syc  *			MMD (MDIO managable device).
458200161856Syc  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
458300161856Syc  *			the register which the driver will write value to.
458400161856Syc  *	value:		The register value will be filled in.
458500161856Syc  */
458644961713Sgirish nxge_status_t
458744961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
458844961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
458944961713Sgirish {
459044961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
459144961713Sgirish 
459244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
459352ccf843Smisaki 	    xcvr_portn));
459444961713Sgirish 
459553560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
459644961713Sgirish 
459744961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
459852ccf843Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
459944961713Sgirish 		goto fail;
460044961713Sgirish 
460153560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
460244961713Sgirish 
460344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
460452ccf843Smisaki 	    xcvr_portn));
460544961713Sgirish 	return (NXGE_OK);
460644961713Sgirish fail:
460753560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
460844961713Sgirish 
460944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
461052ccf843Smisaki 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
461144961713Sgirish 
461244961713Sgirish 	return (NXGE_ERROR | rs);
461344961713Sgirish }
461444961713Sgirish 
461544961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
461644961713Sgirish 
461744961713Sgirish nxge_status_t
461844961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
461944961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
462044961713Sgirish {
462144961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
462244961713Sgirish 
462344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
462452ccf843Smisaki 	    xcvr_portn));
462544961713Sgirish 
462653560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
462744961713Sgirish 
462844961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
462952ccf843Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
463044961713Sgirish 		goto fail;
463144961713Sgirish 
463253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
463344961713Sgirish 
463444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
463552ccf843Smisaki 	    xcvr_portn));
463644961713Sgirish 	return (NXGE_OK);
463744961713Sgirish fail:
463853560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
463944961713Sgirish 
464044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
464152ccf843Smisaki 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
464244961713Sgirish 
464344961713Sgirish 	return (NXGE_ERROR | rs);
464444961713Sgirish }
464544961713Sgirish 
464644961713Sgirish 
464744961713Sgirish /* Check MII to see if there is any link status change */
464844961713Sgirish 
464944961713Sgirish nxge_status_t
4650a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
4651a3c5bd6dSspeer 		nxge_link_state_t *link_up)
465244961713Sgirish {
465344961713Sgirish 	p_nxge_param_t	param_arr;
465444961713Sgirish 	p_nxge_stats_t	statsp;
465544961713Sgirish 	p_mii_regs_t	mii_regs;
465644961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
465744961713Sgirish 	mii_anar_t	anar;
465844961713Sgirish 	mii_anlpar_t	anlpar;
465944961713Sgirish 	mii_anar_t	an_common;
466044961713Sgirish 	mii_aner_t	aner;
466144961713Sgirish 	mii_gsr_t	gsr;
466244961713Sgirish 	nxge_status_t	status = NXGE_OK;
466344961713Sgirish 
466444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
466544961713Sgirish 
466644961713Sgirish 	mii_regs = NULL;
466744961713Sgirish 	param_arr = nxgep->param_arr;
466844961713Sgirish 	statsp = nxgep->statsp;
466944961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
4670a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
467144961713Sgirish 
4672d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4673d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
4674d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
4675d81011f0Ssbehera 
467644961713Sgirish 	if (bmsr_ints.bits.link_status) {
4677d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4678d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
4679d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
468044961713Sgirish 		if (bmsr.bits.link_status) {
468144961713Sgirish 			soft_bmsr->bits.link_status = 1;
4682d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4683d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
4684d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
468544961713Sgirish 		} else {
468644961713Sgirish 			statsp->mac_stats.link_up = 0;
468744961713Sgirish 			soft_bmsr->bits.link_status = 0;
468844961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
468952ccf843Smisaki 			    "Link down cable problem"));
4690a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
469144961713Sgirish 		}
469244961713Sgirish 	}
469344961713Sgirish 
4694d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
4695d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
469644961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
469744961713Sgirish 			if (bmsr.bits.auto_neg_complete)
469844961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
469944961713Sgirish 			else
470044961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
470144961713Sgirish 		}
470244961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
470344961713Sgirish 			statsp->mac_stats.link_T4 = 0;
470444961713Sgirish 			statsp->mac_stats.link_speed = 0;
470544961713Sgirish 			statsp->mac_stats.link_duplex = 0;
470644961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
470744961713Sgirish 			statsp->mac_stats.link_pause = 0;
470844961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
470944961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
471044961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
471144961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
471244961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
471344961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
471444961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
471544961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
471644961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
471744961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
471844961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
471944961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
472044961713Sgirish 		}
472144961713Sgirish 	} else
472244961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
472344961713Sgirish 
472444961713Sgirish 	if ((bmsr_ints.bits.link_status ||
472552ccf843Smisaki 	    bmsr_ints.bits.auto_neg_complete) &&
472652ccf843Smisaki 	    soft_bmsr->bits.link_status &&
472752ccf843Smisaki 	    soft_bmsr->bits.auto_neg_complete) {
472844961713Sgirish 		statsp->mac_stats.link_up = 1;
4729d81011f0Ssbehera 
4730d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4731d81011f0Ssbehera 		    "==> nxge_mii_check "
4732d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
4733d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
4734d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
4735d81011f0Ssbehera 
4736d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4737d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
473844961713Sgirish 			if ((status = nxge_mii_read(nxgep,
473952ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4740adfcba55Sjoycey #if defined(__i386)
474152ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anar),
4742adfcba55Sjoycey #else
474352ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anar),
4744adfcba55Sjoycey #endif
474552ccf843Smisaki 			    &anar.value)) != NXGE_OK)
474644961713Sgirish 				goto fail;
474744961713Sgirish 			if ((status = nxge_mii_read(nxgep,
474852ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4749adfcba55Sjoycey #if defined(__i386)
475052ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
4751adfcba55Sjoycey #else
475252ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
4753adfcba55Sjoycey #endif
475452ccf843Smisaki 			    &anlpar.value)) != NXGE_OK)
475544961713Sgirish 				goto fail;
475644961713Sgirish 			if ((status = nxge_mii_read(nxgep,
475752ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4758adfcba55Sjoycey #if defined(__i386)
475952ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->aner),
4760adfcba55Sjoycey #else
476152ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->aner),
4762adfcba55Sjoycey #endif
476352ccf843Smisaki 			    &aner.value)) != NXGE_OK)
476444961713Sgirish 				goto fail;
476544961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
476644961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
476744961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
476852ccf843Smisaki 			    anlpar.bits.cap_100fdx;
476944961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
477052ccf843Smisaki 			    anlpar.bits.cap_100hdx;
477144961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
477244961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
477344961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
477452ccf843Smisaki 			    anlpar.bits.cap_asmpause;
477544961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
477644961713Sgirish 			an_common.value = anar.value & anlpar.value;
477744961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
477852ccf843Smisaki 			    param_arr[param_anar_1000hdx].value) {
477944961713Sgirish 				if ((status = nxge_mii_read(nxgep,
478052ccf843Smisaki 				    statsp->mac_stats.xcvr_portn,
4781adfcba55Sjoycey #if defined(__i386)
478252ccf843Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
4783adfcba55Sjoycey #else
478452ccf843Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
4785adfcba55Sjoycey #endif
478652ccf843Smisaki 				    &gsr.value)) != NXGE_OK)
478744961713Sgirish 					goto fail;
478844961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
478952ccf843Smisaki 				    gsr.bits.link_1000fdx;
479044961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
479152ccf843Smisaki 				    gsr.bits.link_1000hdx;
479244961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
479352ccf843Smisaki 				    gsr.bits.link_1000fdx) {
479444961713Sgirish 					statsp->mac_stats.link_speed = 1000;
479544961713Sgirish 					statsp->mac_stats.link_duplex = 2;
479644961713Sgirish 				} else if (
479752ccf843Smisaki 				    param_arr[param_anar_1000hdx].value &&
479852ccf843Smisaki 				    gsr.bits.link_1000hdx) {
479944961713Sgirish 					statsp->mac_stats.link_speed = 1000;
480044961713Sgirish 					statsp->mac_stats.link_duplex = 1;
480144961713Sgirish 				}
480244961713Sgirish 			}
480344961713Sgirish 			if ((an_common.value != 0) &&
480452ccf843Smisaki 			    !(statsp->mac_stats.link_speed)) {
480544961713Sgirish 				if (an_common.bits.cap_100T4) {
480644961713Sgirish 					statsp->mac_stats.link_T4 = 1;
480744961713Sgirish 					statsp->mac_stats.link_speed = 100;
480844961713Sgirish 					statsp->mac_stats.link_duplex = 1;
480944961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
481044961713Sgirish 					statsp->mac_stats.link_speed = 100;
481144961713Sgirish 					statsp->mac_stats.link_duplex = 2;
481244961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
481344961713Sgirish 					statsp->mac_stats.link_speed = 100;
481444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
481544961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
481644961713Sgirish 					statsp->mac_stats.link_speed = 10;
481744961713Sgirish 					statsp->mac_stats.link_duplex = 2;
481844961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
481944961713Sgirish 					statsp->mac_stats.link_speed = 10;
482044961713Sgirish 					statsp->mac_stats.link_duplex = 1;
482144961713Sgirish 				} else {
482244961713Sgirish 					goto fail;
482344961713Sgirish 				}
482444961713Sgirish 			}
482544961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
482652ccf843Smisaki 				int	link_pause;
482752ccf843Smisaki 				int	cp, lcp;
482852ccf843Smisaki 
482944961713Sgirish 				statsp->mac_stats.link_asmpause =
483052ccf843Smisaki 				    an_common.bits.cap_asmpause;
483152ccf843Smisaki 				cp = statsp->mac_stats.cap_pause;
483252ccf843Smisaki 				lcp = statsp->mac_stats.lp_cap_pause;
483352ccf843Smisaki 				if (statsp->mac_stats.link_asmpause) {
483452ccf843Smisaki 					if ((cp == 0) && (lcp == 1)) {
483552ccf843Smisaki 						link_pause = 0;
483652ccf843Smisaki 					} else {
483752ccf843Smisaki 						link_pause = 1;
483852ccf843Smisaki 					}
483952ccf843Smisaki 				} else {
484052ccf843Smisaki 					link_pause = an_common.bits.cap_pause;
484152ccf843Smisaki 				}
484252ccf843Smisaki 				statsp->mac_stats.link_pause = link_pause;
484344961713Sgirish 			}
4844d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4845d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
4846d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
484744961713Sgirish 		}
4848a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
4849a3c5bd6dSspeer 	}
4850a3c5bd6dSspeer 
4851a3c5bd6dSspeer 	if (nxgep->link_notify) {
4852a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
485352ccf843Smisaki 		    LINK_IS_DOWN);
4854a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
485544961713Sgirish 	}
485644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
485744961713Sgirish 	return (NXGE_OK);
485844961713Sgirish fail:
485944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
486052ccf843Smisaki 	    "nxge_mii_check: Unable to check MII"));
486144961713Sgirish 	return (status);
486244961713Sgirish }
486344961713Sgirish 
486400161856Syc /*
486500161856Syc  * Check PCS to see if there is any link status change.
486600161856Syc  * This function is called by PORT_1G_SERDES only.
486700161856Syc  */
486800161856Syc void
48692e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
48702e59129aSraghus {
48712e59129aSraghus 	p_nxge_stats_t	statsp;
48722e59129aSraghus 	boolean_t	linkup;
48732e59129aSraghus 
48742e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
48752e59129aSraghus 
48762e59129aSraghus 	statsp = nxgep->statsp;
48772e59129aSraghus 	*link_up = LINK_NO_CHANGE;
48782e59129aSraghus 
48792e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
48802e59129aSraghus 	if (linkup) {
48812e59129aSraghus 		if (nxgep->link_notify ||
48822e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
48832e59129aSraghus 			statsp->mac_stats.link_up = 1;
48842e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
48852e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
48862e59129aSraghus 			*link_up = LINK_IS_UP;
48872e59129aSraghus 			nxgep->link_notify = B_FALSE;
48882e59129aSraghus 		}
48892e59129aSraghus 	} else {
48902e59129aSraghus 		if (nxgep->link_notify ||
48912e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
48922e59129aSraghus 			statsp->mac_stats.link_up = 0;
48932e59129aSraghus 			statsp->mac_stats.link_speed = 0;
48942e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
48952e59129aSraghus 			*link_up = LINK_IS_DOWN;
48962e59129aSraghus 			nxgep->link_notify = B_FALSE;
48972e59129aSraghus 		}
48982e59129aSraghus 	}
48992e59129aSraghus 
49002e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
49012e59129aSraghus }
49022e59129aSraghus 
490344961713Sgirish /* Add a multicast address entry into the HW hash table */
490444961713Sgirish 
490544961713Sgirish nxge_status_t
490644961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
490744961713Sgirish {
490844961713Sgirish 	uint32_t mchash;
490944961713Sgirish 	p_hash_filter_t hash_filter;
491044961713Sgirish 	uint16_t hash_bit;
491144961713Sgirish 	boolean_t rx_init = B_FALSE;
491244961713Sgirish 	uint_t j;
491344961713Sgirish 	nxge_status_t status = NXGE_OK;
491444961713Sgirish 
491544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
491644961713Sgirish 
491744961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
491844961713Sgirish 	mchash = crc32_mchash(addrp);
491944961713Sgirish 	if (nxgep->hash_filter == NULL) {
492044961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
492152ccf843Smisaki 		    "Allocating hash filter storage."));
492244961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
492352ccf843Smisaki 		    KM_SLEEP);
492444961713Sgirish 	}
492544961713Sgirish 	hash_filter = nxgep->hash_filter;
492644961713Sgirish 	j = mchash / HASH_REG_WIDTH;
492744961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
492844961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
492944961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
493044961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
493144961713Sgirish 		hash_filter->hash_ref_cnt++;
493244961713Sgirish 		rx_init = B_TRUE;
493344961713Sgirish 	}
493444961713Sgirish 	if (rx_init) {
493544961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
493644961713Sgirish 			goto fail;
493744961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
493844961713Sgirish 			goto fail;
493944961713Sgirish 	}
494044961713Sgirish 
494144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
494244961713Sgirish 
494344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
494444961713Sgirish 
494544961713Sgirish 	return (NXGE_OK);
494644961713Sgirish fail:
494744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
494844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
494952ccf843Smisaki 	    "Unable to add multicast address"));
495044961713Sgirish 	return (status);
495144961713Sgirish }
495244961713Sgirish 
495344961713Sgirish /* Remove a multicast address entry from the HW hash table */
495444961713Sgirish 
495544961713Sgirish nxge_status_t
495644961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
495744961713Sgirish {
495844961713Sgirish 	uint32_t mchash;
495944961713Sgirish 	p_hash_filter_t hash_filter;
496044961713Sgirish 	uint16_t hash_bit;
496144961713Sgirish 	boolean_t rx_init = B_FALSE;
496244961713Sgirish 	uint_t j;
496344961713Sgirish 	nxge_status_t status = NXGE_OK;
496444961713Sgirish 
496544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
496644961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
496744961713Sgirish 	mchash = crc32_mchash(addrp);
496844961713Sgirish 	if (nxgep->hash_filter == NULL) {
496944961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
497052ccf843Smisaki 		    "Hash filter already de_allocated."));
497144961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
497244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
497344961713Sgirish 		return (NXGE_OK);
497444961713Sgirish 	}
497544961713Sgirish 	hash_filter = nxgep->hash_filter;
497644961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
497744961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
497844961713Sgirish 		j = mchash / HASH_REG_WIDTH;
497944961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
498044961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
498144961713Sgirish 		hash_filter->hash_ref_cnt--;
498244961713Sgirish 		rx_init = B_TRUE;
498344961713Sgirish 	}
498444961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
498544961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
498652ccf843Smisaki 		    "De-allocating hash filter storage."));
498744961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
498844961713Sgirish 		nxgep->hash_filter = NULL;
498944961713Sgirish 	}
499044961713Sgirish 
499144961713Sgirish 	if (rx_init) {
499244961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
499344961713Sgirish 			goto fail;
499444961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
499544961713Sgirish 			goto fail;
499644961713Sgirish 	}
499744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
499844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
499944961713Sgirish 
500044961713Sgirish 	return (NXGE_OK);
500144961713Sgirish fail:
500244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
500344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
500452ccf843Smisaki 	    "Unable to remove multicast address"));
500544961713Sgirish 
500644961713Sgirish 	return (status);
500744961713Sgirish }
500844961713Sgirish 
500944961713Sgirish /* Set MAC address into MAC address HW registers */
501044961713Sgirish 
501144961713Sgirish nxge_status_t
501244961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
501344961713Sgirish {
501444961713Sgirish 	nxge_status_t status = NXGE_OK;
501544961713Sgirish 
501644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
501744961713Sgirish 
501844961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
501944961713Sgirish 	/*
502044961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
502144961713Sgirish 	 */
502244961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
502352ccf843Smisaki 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
502452ccf843Smisaki 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
502544961713Sgirish 		goto nxge_set_mac_addr_exit;
502644961713Sgirish 	}
502744961713Sgirish 	nxgep->ouraddr = *addrp;
502844961713Sgirish 	/*
502944961713Sgirish 	 * Set new interface local address and re-init device.
503044961713Sgirish 	 * This is destructive to any other streams attached
503144961713Sgirish 	 * to this device.
503244961713Sgirish 	 */
503344961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
503444961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
503544961713Sgirish 		goto fail;
503644961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
503744961713Sgirish 		goto fail;
503844961713Sgirish 
503944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
504044961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
504144961713Sgirish 	goto nxge_set_mac_addr_end;
504244961713Sgirish nxge_set_mac_addr_exit:
504344961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
504444961713Sgirish nxge_set_mac_addr_end:
504544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
504644961713Sgirish 
504744961713Sgirish 	return (NXGE_OK);
504844961713Sgirish fail:
504944961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
505044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
505152ccf843Smisaki 	    "Unable to set mac address"));
505244961713Sgirish 	return (status);
505344961713Sgirish }
505444961713Sgirish 
505598ecde52Stm static
505698ecde52Stm check_link_state_t
505700161856Syc nxge_check_link_stop(nxge_t *nxge)
505898ecde52Stm {
505998ecde52Stm 	/* If the poll has been cancelled, return STOP. */
506098ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
506198ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
506298ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
506398ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
506498ecde52Stm 		cv_broadcast(&nxge->poll_cv);
506598ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
506698ecde52Stm 
506798ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
506898ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
506998ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
507098ecde52Stm 		    nxge->mac.portnum));
507198ecde52Stm 		return (CHECK_LINK_STOP);
507298ecde52Stm 	}
507398ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
507498ecde52Stm 
507598ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
507698ecde52Stm }
507798ecde52Stm 
507800161856Syc /*
507900161856Syc  * Check status of MII (MIF or PCS) link.
508000161856Syc  * This function is called once per second, that is because this function
508100161856Syc  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
508200161856Syc  * call this function recursively.
508300161856Syc  */
508459ac0c16Sdavemq static nxge_status_t
508544961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
508644961713Sgirish {
508744961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
508844961713Sgirish 	mii_anlpar_t anlpar;
508944961713Sgirish 	mii_gsr_t gsr;
509044961713Sgirish 	p_mii_regs_t mii_regs;
509144961713Sgirish 	nxge_status_t status = NXGE_OK;
509244961713Sgirish 	uint8_t portn;
5093a3c5bd6dSspeer 	nxge_link_state_t link_up;
509444961713Sgirish 
509598ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
509698ecde52Stm 		return (NXGE_ERROR);
509798ecde52Stm 
509898ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
509998ecde52Stm 		return (NXGE_OK);
510098ecde52Stm 
510144961713Sgirish 	portn = nxgep->mac.portnum;
510244961713Sgirish 
510344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
510498ecde52Stm 	    portn));
510544961713Sgirish 
510644961713Sgirish 	mii_regs = NULL;
510744961713Sgirish 
510844961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
510944961713Sgirish 
511044961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
511144961713Sgirish 		goto nxge_check_mii_link_exit;
511244961713Sgirish 
51132e59129aSraghus 	switch (nxgep->mac.portmode) {
51142e59129aSraghus 	default:
5115d81011f0Ssbehera 		bmsr_data.value = 0;
511644961713Sgirish 		if ((status = nxge_mii_read(nxgep,
51172e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
5118adfcba55Sjoycey #if defined(__i386)
5119adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5120adfcba55Sjoycey #else
51212e59129aSraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5122adfcba55Sjoycey #endif
51232e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
512444961713Sgirish 			goto fail;
512544961713Sgirish 		}
512644961713Sgirish 
5127d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5128d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
5129d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
51302d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
5131d81011f0Ssbehera 
51322e59129aSraghus 		if (nxgep->param_arr[param_autoneg].value) {
51332e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
513452ccf843Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
5135adfcba55Sjoycey #if defined(__i386)
513652ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
5137adfcba55Sjoycey #else
513852ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
5139adfcba55Sjoycey #endif
514052ccf843Smisaki 			    &gsr.value)) != NXGE_OK)
51412e59129aSraghus 				goto fail;
51422e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
514352ccf843Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
5144adfcba55Sjoycey #if defined(__i386)
514552ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
5146adfcba55Sjoycey #else
514752ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
5148adfcba55Sjoycey #endif
514952ccf843Smisaki 			    &anlpar.value)) != NXGE_OK)
51502e59129aSraghus 				goto fail;
5151d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
5152d81011f0Ssbehera 
5153d81011f0Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
5154d81011f0Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
5155d81011f0Ssbehera 				    gsr.bits.link_1000fdx) ||
5156d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
5157d81011f0Ssbehera 				    gsr.bits.link_1000hdx) ||
5158d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
5159d81011f0Ssbehera 				    anlpar.bits.cap_100T4) ||
5160d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
5161d81011f0Ssbehera 				    anlpar.bits.cap_100fdx) ||
5162d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
5163d81011f0Ssbehera 				    anlpar.bits.cap_100hdx) ||
5164d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
5165d81011f0Ssbehera 				    anlpar.bits.cap_10fdx) ||
5166d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
5167d81011f0Ssbehera 				    anlpar.bits.cap_10hdx))) {
5168d81011f0Ssbehera 					bmsr_data.bits.link_status = 0;
5169d81011f0Ssbehera 				}
51702e59129aSraghus 			}
51712e59129aSraghus 		}
517244961713Sgirish 
51732e59129aSraghus 		/* Workaround for link down issue */
51742e59129aSraghus 		if (bmsr_data.value == 0) {
51752e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
51762e59129aSraghus 			goto nxge_check_mii_link_exit;
51772e59129aSraghus 		}
51782e59129aSraghus 
5179d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5180d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
5181d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
51822d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
5183d81011f0Ssbehera 
51842e59129aSraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
51852e59129aSraghus 		nxgep->bmsr.value = bmsr_data.value;
5186d81011f0Ssbehera 
5187d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5188d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
5189d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
51902d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
5191d81011f0Ssbehera 
51922e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
51932e59129aSraghus 		    &link_up)) != NXGE_OK) {
51942e59129aSraghus 			goto fail;
51952e59129aSraghus 		}
51962e59129aSraghus 		break;
51972e59129aSraghus 
51982e59129aSraghus 	case PORT_1G_SERDES:
519900161856Syc 		/*
520000161856Syc 		 * Above default is for all cases except PORT_1G_SERDES.
520100161856Syc 		 * The default case gets information from the PHY, but a
520200161856Syc 		 * nxge whose portmode equals PORT_1G_SERDES does not
520300161856Syc 		 * have a PHY.
520400161856Syc 		 */
52052e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
52062e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
520700161856Syc 		nxge_pcs_check(nxgep, portn, &link_up);
52082e59129aSraghus 		break;
52092e59129aSraghus 	}
521044961713Sgirish 
521144961713Sgirish nxge_check_mii_link_exit:
521244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
5213a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
5214a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
5215a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
5216a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
5217a3c5bd6dSspeer 	}
521844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
521944961713Sgirish 
522044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
522152ccf843Smisaki 	    portn));
522244961713Sgirish 	return (NXGE_OK);
522344961713Sgirish 
522444961713Sgirish fail:
522544961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
522644961713Sgirish 
522744961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
522844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
522952ccf843Smisaki 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
523044961713Sgirish 	return (status);
523144961713Sgirish }
523244961713Sgirish 
523344961713Sgirish /*ARGSUSED*/
523459ac0c16Sdavemq static nxge_status_t
523544961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
523644961713Sgirish {
523744961713Sgirish 	uint8_t		portn;
523844961713Sgirish 	nxge_status_t	status = NXGE_OK;
5239763fcc44Ssbehera 	boolean_t	link_up;
52402e59129aSraghus 	uint32_t	val;
52412e59129aSraghus 	npi_status_t	rs;
524244961713Sgirish 
524398ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
524498ecde52Stm 		return (NXGE_ERROR);
524598ecde52Stm 
524698ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
524798ecde52Stm 		return (NXGE_OK);
524898ecde52Stm 
524944961713Sgirish 	portn = nxgep->mac.portnum;
5250d81011f0Ssbehera 	val = 0;
5251d81011f0Ssbehera 	rs = NPI_SUCCESS;
525244961713Sgirish 
525344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
525498ecde52Stm 	    portn));
525544961713Sgirish 
52562e59129aSraghus 	switch (nxgep->mac.portmode) {
52572e59129aSraghus 	default:
52582d17280bSsbehera 		/*
52592d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
52602d17280bSsbehera 		 */
52612d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
52622d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
52632d17280bSsbehera 
52642d17280bSsbehera 			/*
52652d17280bSsbehera 			 * If this is the 2nd Goa port, then check 2 addresses
52662d17280bSsbehera 			 * to take care of the Goa NEM card requirements.
52672d17280bSsbehera 			 */
52682d17280bSsbehera 			if (portn == 1) {
52692d17280bSsbehera 				if (nxge_is_phy_present(nxgep,
527000161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
52712d17280bSsbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
52722d17280bSsbehera 					phy_present_now = B_TRUE;
52732d17280bSsbehera 					nxgep->xcvr_addr =
527400161856Syc 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
52752d17280bSsbehera 					goto phy_check_done;
52762d17280bSsbehera 				}
52772d17280bSsbehera 			}
52782d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
527900161856Syc 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
52802d17280bSsbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
52812d17280bSsbehera 				nxgep->xcvr_addr =
528200161856Syc 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
52832d17280bSsbehera 				phy_present_now = B_TRUE;
52842d17280bSsbehera 			}
52852d17280bSsbehera 
52862d17280bSsbehera phy_check_done:
52871c7408c9Stc 			/* Check back-to-back XAUI connect to detect Opus NEM */
52881c7408c9Stc 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
52891c7408c9Stc 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
52901c7408c9Stc 			if (rs != 0)
52911c7408c9Stc 				goto fail;
52921c7408c9Stc 
52931c7408c9Stc 			link_up = B_FALSE;
52941c7408c9Stc 			if (val & XPCS_STATUS_LANE_ALIGN) {
52951c7408c9Stc 				link_up = B_TRUE;
52961c7408c9Stc 			}
52971c7408c9Stc 
52982d17280bSsbehera 			if (nxgep->phy_absent) {
52992d17280bSsbehera 				if (phy_present_now) {
53002d17280bSsbehera 				/*
53012d17280bSsbehera 				 * Detect, Initialize phy and do link up
53022d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
53032d17280bSsbehera 				 */
53042d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53052d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
53062d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
53072d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
53082d17280bSsbehera 					(void) nxge_link_init(nxgep);
53092d17280bSsbehera 					if (!(nxgep->drv_state &
53102d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
53112d17280bSsbehera 						status = nxge_init(nxgep);
53122d17280bSsbehera 						if (status != NXGE_OK) {
53132d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
53142d17280bSsbehera 							    NXGE_ERR_CTL,
53152d17280bSsbehera 							    "Hot swappable "
53162d17280bSsbehera 							    "phy present, but"
53172d17280bSsbehera 							    " driver init"
53182d17280bSsbehera 							    "  failed..."));
53192d17280bSsbehera 							goto fail;
53202d17280bSsbehera 						}
53212d17280bSsbehera 					}
53221c7408c9Stc 				} else if (link_up) { /* XAUI linkup, no PHY */
532348056c53SMichael Speer 					/*
53241c7408c9Stc 					 * This is the back-to-back XAUI
53251c7408c9Stc 					 * connect case for Opus NEM.
53261c7408c9Stc 					 */
53271c7408c9Stc 					nxgep->statsp->mac_stats.xcvr_inuse =
53281c7408c9Stc 					    XPCS_XCVR;
53291c7408c9Stc 					nxgep->mac.portmode = PORT_10G_SERDES;
53301c7408c9Stc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53311c7408c9Stc 					    "HSP 10G Serdes DETECTED!!"));
53321c7408c9Stc 					break;
53332d17280bSsbehera 				}
53342d17280bSsbehera 
53352d17280bSsbehera 				goto start_link_check;
53362d17280bSsbehera 
53372d17280bSsbehera 			} else if (!phy_present_now) {
53382d17280bSsbehera 				/*
53392d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
53402d17280bSsbehera 				 */
53412d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53422d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
53432d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
53442d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
53452d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
53462d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
53472d17280bSsbehera 				nxge_link_is_down(nxgep);
53482d17280bSsbehera 				nxgep->link_notify = B_FALSE;
53492d17280bSsbehera 
53502d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
53512d17280bSsbehera 
53522d17280bSsbehera 				goto start_link_check;
53532d17280bSsbehera 
53542d17280bSsbehera 			}
53552d17280bSsbehera 		}
535652cdd236Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
535700161856Syc 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
535852cdd236Ssbehera 		} else {
535952cdd236Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
536052cdd236Ssbehera 		}
53612e59129aSraghus 		if (status != NXGE_OK)
53622e59129aSraghus 			goto fail;
53632e59129aSraghus 		break;
53642e59129aSraghus 	case PORT_10G_SERDES:
53652e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5366763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
53672e59129aSraghus 		if (rs != 0)
53682e59129aSraghus 			goto fail;
53692e59129aSraghus 
53702e59129aSraghus 		link_up = B_FALSE;
5371763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
5372763fcc44Ssbehera 			link_up = B_TRUE;
53732e59129aSraghus 		}
53742e59129aSraghus 
53752e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53762e59129aSraghus 		    "==> nxge_check_10g_link port<%d> "
5377763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
5378763fcc44Ssbehera 		    portn, val, link_up));
53792e59129aSraghus 
53802e59129aSraghus 		break;
53812e59129aSraghus 	}
538244961713Sgirish 
538344961713Sgirish 	if (link_up) {
5384a3c5bd6dSspeer 		if (nxgep->link_notify ||
538552ccf843Smisaki 		    nxgep->statsp->mac_stats.link_up == 0) {
538644961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
538744961713Sgirish 				goto fail;
538844961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
538944961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
539044961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
539144961713Sgirish 
539244961713Sgirish 			nxge_link_is_up(nxgep);
5393a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
539444961713Sgirish 		}
539544961713Sgirish 	} else {
5396a3c5bd6dSspeer 		if (nxgep->link_notify ||
539752ccf843Smisaki 		    nxgep->statsp->mac_stats.link_up == 1) {
539844961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
539944961713Sgirish 				goto fail;
540044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
540152ccf843Smisaki 			    "Link down cable problem"));
540244961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
540344961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
540444961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
540544961713Sgirish 
540644961713Sgirish 			nxge_link_is_down(nxgep);
5407a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
54081c7408c9Stc 
54091c7408c9Stc 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
54101c7408c9Stc 				/*
54111c7408c9Stc 				 * NEM was unplugged, set up xcvr table
54121c7408c9Stc 				 * to find another xcvr in the future.
54131c7408c9Stc 				 */
54141c7408c9Stc 				(void) nxge_xcvr_find(nxgep);
54151c7408c9Stc 			}
541644961713Sgirish 		}
541744961713Sgirish 	}
541844961713Sgirish 
54192d17280bSsbehera start_link_check:
542044961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
542144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
542298ecde52Stm 	    portn));
542344961713Sgirish 	return (NXGE_OK);
542444961713Sgirish 
542544961713Sgirish fail:
542698ecde52Stm 	(void) nxge_check_link_stop(nxgep);
542798ecde52Stm 
542844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
542998ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
543098ecde52Stm 	    portn));
543144961713Sgirish 	return (status);
543244961713Sgirish }
543344961713Sgirish 
543444961713Sgirish 
543544961713Sgirish /* Declare link down */
543644961713Sgirish 
543744961713Sgirish void
543844961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
543944961713Sgirish {
544059ac0c16Sdavemq 	p_nxge_stats_t statsp;
544159ac0c16Sdavemq 	char link_stat_msg[64];
544259ac0c16Sdavemq 
544344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
544444961713Sgirish 
544559ac0c16Sdavemq 	statsp = nxgep->statsp;
544659ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
544759ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
544859ac0c16Sdavemq 
544959ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
545059ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
545159ac0c16Sdavemq 	}
545259ac0c16Sdavemq 
545344961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
545444961713Sgirish 
545544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
545644961713Sgirish }
545744961713Sgirish 
545844961713Sgirish /* Declare link up */
545944961713Sgirish 
546044961713Sgirish void
546144961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
546244961713Sgirish {
546359ac0c16Sdavemq 	p_nxge_stats_t statsp;
546459ac0c16Sdavemq 	char link_stat_msg[64];
546544961713Sgirish 	uint32_t val;
546644961713Sgirish 
546744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
546844961713Sgirish 
546959ac0c16Sdavemq 	statsp = nxgep->statsp;
547059ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
547159ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
547259ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
547359ac0c16Sdavemq 
547459ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
547559ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
547659ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
547759ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
547859ac0c16Sdavemq 	else
547959ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
548059ac0c16Sdavemq 
548144961713Sgirish 
548244961713Sgirish 	/* Clean up symbol errors incurred during link transition */
54832e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
54842e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
548544961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
548652ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
548744961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
548852ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
548944961713Sgirish 	}
549044961713Sgirish 
549100161856Syc 	/*
549200161856Syc 	 * If the driver was plumbed without a link (therefore auto-negotiation
549300161856Syc 	 * could not complete), the driver will detect a link up when a cable
549400161856Syc 	 * conneting to a link partner is plugged into the port. By the time
549500161856Syc 	 * link-up is detected, auto-negotiation should have completed (The
549600161856Syc 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
549700161856Syc 	 * configure the Neptune/NIU according to the newly negotiated speed.
549800161856Syc 	 * This is necessary only for the TN1010 basad device because only the
549900161856Syc 	 * TN1010 supports dual speeds.
550000161856Syc 	 */
550100161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
550200161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
550300161856Syc 
550400161856Syc 		(void) nxge_set_tn1010_param(nxgep);
550500161856Syc 
550600161856Syc 		/*
550700161856Syc 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
550800161856Syc 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
550900161856Syc 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
551000161856Syc 		 */
551100161856Syc 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
551200161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
551300161856Syc 			    "nxge_link_is_up: nxge_xcvr_find failed"));
551400161856Syc 		}
551500161856Syc 
551600161856Syc 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
551700161856Syc 		if (nxge_link_init(nxgep) != NXGE_OK) {
551800161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
551900161856Syc 			    "nxge_link_is_up: nxge_link_init failed"));
552000161856Syc 		}
552100161856Syc 
552200161856Syc 		/*
552300161856Syc 		 * nxge_mac_init calls many subroutines including
552400161856Syc 		 * nxge_xif_init which sets XGMII or GMII mode
552500161856Syc 		 */
552600161856Syc 		if (nxge_mac_init(nxgep) != NXGE_OK) {
552700161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
552800161856Syc 			    "nxge_link_is_up: nxge_mac_init failed"));
552900161856Syc 		}
553000161856Syc 	} else {
553100161856Syc 		(void) nxge_xif_init(nxgep);
553200161856Syc 	}
553300161856Syc 
553459ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
553559ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
553659ac0c16Sdavemq 	}
553759ac0c16Sdavemq 
553844961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
553944961713Sgirish 
554044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
554144961713Sgirish }
554244961713Sgirish 
554300161856Syc #ifdef NXGE_DEBUG
554400161856Syc /* Dump all TN1010 Status registers */
554500161856Syc static void
554600161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
554700161856Syc {
554800161856Syc 	uint16_t val;
554900161856Syc 
555000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
555100161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
555200161856Syc 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
555300161856Syc 
555400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
555500161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
555600161856Syc 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
555700161856Syc 
555800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
555900161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
556000161856Syc 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
556100161856Syc 
556200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
556300161856Syc 	    TN1010_PCS_DEV_ADDR, 1, &val);
556400161856Syc 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
556500161856Syc 
556600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
556700161856Syc 	    TN1010_PCS_DEV_ADDR, 8, &val);
556800161856Syc 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
556900161856Syc 
557000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
557100161856Syc 	    TN1010_PCS_DEV_ADDR, 32, &val);
557200161856Syc 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
557300161856Syc 
557400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
557500161856Syc 	    TN1010_PCS_DEV_ADDR, 33, &val);
557600161856Syc 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
557700161856Syc 
557800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
557900161856Syc 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
558000161856Syc 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
558100161856Syc 
558200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
558300161856Syc 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
558400161856Syc 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
558500161856Syc 
558600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
558700161856Syc 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
558800161856Syc 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
558900161856Syc 
559000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
559100161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
559200161856Syc 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
559300161856Syc 
559400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
559500161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
559600161856Syc 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
559700161856Syc 
559800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
559900161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
560000161856Syc 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
560100161856Syc 
560200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
560300161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
560400161856Syc 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
560500161856Syc 
560600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
560700161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
560800161856Syc 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
560900161856Syc 
561000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
561100161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
561200161856Syc 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
561300161856Syc 
561400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
561500161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
561600161856Syc 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
561700161856Syc 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
561800161856Syc }
561900161856Syc #endif
562000161856Syc 
562144961713Sgirish /*
562244961713Sgirish  * Calculate the bit in the multicast address filter
562344961713Sgirish  * that selects the given * address.
562444961713Sgirish  * Note: For GEM, the last 8-bits are used.
562544961713Sgirish  */
562644961713Sgirish uint32_t
562744961713Sgirish crc32_mchash(p_ether_addr_t addr)
562844961713Sgirish {
562944961713Sgirish 	uint8_t *cp;
563044961713Sgirish 	uint32_t crc;
563144961713Sgirish 	uint32_t c;
563244961713Sgirish 	int byte;
563344961713Sgirish 	int bit;
563444961713Sgirish 
563544961713Sgirish 	cp = (uint8_t *)addr;
563644961713Sgirish 	crc = (uint32_t)0xffffffff;
563744961713Sgirish 	for (byte = 0; byte < 6; byte++) {
563844961713Sgirish 		c = (uint32_t)cp[byte];
563944961713Sgirish 		for (bit = 0; bit < 8; bit++) {
564044961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
564144961713Sgirish 				crc = (crc >> 1)^0xedb88320;
564244961713Sgirish 			else
564344961713Sgirish 				crc = (crc >> 1);
564444961713Sgirish 			c >>= 1;
564544961713Sgirish 		}
564644961713Sgirish 	}
564744961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
564844961713Sgirish }
564944961713Sgirish 
565044961713Sgirish /* Reset serdes */
565144961713Sgirish 
565244961713Sgirish nxge_status_t
565344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
565444961713Sgirish {
565544961713Sgirish 	npi_handle_t		handle;
565644961713Sgirish 
565744961713Sgirish 	handle = nxgep->npi_handle;
565844961713Sgirish 
565944961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
566044961713Sgirish 	drv_usecwait(500);
566144961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
566244961713Sgirish 
566344961713Sgirish 	return (NXGE_OK);
566444961713Sgirish }
566544961713Sgirish 
566600161856Syc /*
566700161856Syc  * This function monitors link status using interrupt or polling.
566800161856Syc  * It calls nxgep->xcvr.check_link, a member function of
566900161856Syc  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
567000161856Syc  * function back, that is why the check_link routine is
567100161856Syc  * executed periodically.
567200161856Syc  */
567344961713Sgirish nxge_status_t
567444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
567544961713Sgirish {
567644961713Sgirish 	nxge_status_t status = NXGE_OK;
567744961713Sgirish 
5678678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
5679678453a8Sspeer 	if (isLDOMguest(nxgep))
5680678453a8Sspeer 		return (status);
5681678453a8Sspeer 
568244961713Sgirish 	/*
568398ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
568498ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
568544961713Sgirish 	 */
56862e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
56872e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
56882e59129aSraghus 	    (nxgep->mac.portnum > 1))
568944961713Sgirish 		return (NXGE_OK);
569044961713Sgirish 
569144961713Sgirish 	if (nxgep->statsp == NULL) {
569244961713Sgirish 		/* stats has not been allocated. */
569344961713Sgirish 		return (NXGE_OK);
569444961713Sgirish 	}
5695321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
5696321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
569744961713Sgirish 		return (NXGE_OK);
569844961713Sgirish 
569944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
570098ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
570198ecde52Stm 	    nxgep->mac.portnum, enable));
570244961713Sgirish 	if (enable == LINK_MONITOR_START) {
570344961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
570444961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
570598ecde52Stm 			    != NXGE_OK)
570644961713Sgirish 				goto fail;
570744961713Sgirish 		} else {
570898ecde52Stm 			timeout_id_t timerid;
570900161856Syc 			/*
571000161856Syc 			 * check_link_stop means "Stop the link check", so
571100161856Syc 			 * we return without starting the timer.
571200161856Syc 			 */
571398ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
571498ecde52Stm 				return (NXGE_OK);
571598ecde52Stm 
571600161856Syc 			/*
571700161856Syc 			 * Otherwise fire the timer for the nxge to check
571800161856Syc 			 * the link using the check_link function
571900161856Syc 			 * of the nxge_xcvr_table and pass "nxgep" as the
572000161856Syc 			 * argument to the check_link function.
572100161856Syc 			 */
572259ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
572359ac0c16Sdavemq 				timerid = timeout(
572459ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
572598ecde52Stm 				    nxgep,
572698ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
572759ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
572859ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
572959ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
573059ac0c16Sdavemq 			} else {
573198ecde52Stm 				return (NXGE_ERROR);
573244961713Sgirish 			}
573344961713Sgirish 		}
573444961713Sgirish 	} else {
573544961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
573644961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
573798ecde52Stm 			    != NXGE_OK)
573844961713Sgirish 				goto fail;
573944961713Sgirish 		} else {
574098ecde52Stm 			clock_t rv;
574198ecde52Stm 
574298ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
574398ecde52Stm 
574498ecde52Stm 			/* If <timerid> == 0, the link monitor has */
574598ecde52Stm 			/* never been started, or just now stopped. */
574698ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
574798ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
574898ecde52Stm 				return (NXGE_OK);
574998ecde52Stm 			}
575098ecde52Stm 
575198ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
5752d3d50737SRafael Vanoni 			rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
575398ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
5754d3d50737SRafael Vanoni 			    LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
575598ecde52Stm 			if (rv == -1) {
575698ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
575798ecde52Stm 				    "==> stopping port %d: "
575898ecde52Stm 				    "cv_timedwait(%d) timed out",
575998ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
576098ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
576144961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
576244961713Sgirish 			}
576398ecde52Stm 
576498ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
576544961713Sgirish 		}
576644961713Sgirish 	}
576744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
576898ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
576998ecde52Stm 	    nxgep->mac.portnum, enable));
5770678453a8Sspeer 
577144961713Sgirish 	return (NXGE_OK);
577244961713Sgirish fail:
577344961713Sgirish 	return (status);
577400161856Syc 
577500161856Syc }
577600161856Syc 
577700161856Syc nxge_status_t
577800161856Syc nxge_check_tn1010_link(p_nxge_t nxgep)
577900161856Syc {
578000161856Syc 	nxge_status_t	status = NXGE_OK;
578100161856Syc 	nxge_link_state_t link_up;
578200161856Syc 
578300161856Syc 	if (nxgep->nxge_magic != NXGE_MAGIC) {
578400161856Syc 		/* magic is 0 if driver is not attached */
578500161856Syc 		return (NXGE_ERROR);
578600161856Syc 	}
578700161856Syc 
578800161856Syc 	/* Link has been stopped, no need to continue */
578900161856Syc 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
579000161856Syc 		return (NXGE_OK);
579100161856Syc 	}
579200161856Syc 
579300161856Syc 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
579400161856Syc 		goto nxge_check_tn1010_link_exit;
579500161856Syc 
579600161856Syc 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
579700161856Syc 		goto fail;
579800161856Syc 
579900161856Syc nxge_check_tn1010_link_exit:
580000161856Syc 	if (link_up == LINK_IS_UP)
580100161856Syc 		nxge_link_is_up(nxgep);
580200161856Syc 	else if (link_up == LINK_IS_DOWN)
580300161856Syc 		nxge_link_is_down(nxgep);
580400161856Syc 
580500161856Syc 	/*
580600161856Syc 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
580700161856Syc 	 * which could be THIS function.
580800161856Syc 	 */
580900161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
581000161856Syc 
581100161856Syc 	return (NXGE_OK);
581200161856Syc 
581300161856Syc fail:
581400161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
581500161856Syc 
581600161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
581700161856Syc 	    "nxge_check_tn1010_link: Failed to check link"));
581800161856Syc 	return (status);
581900161856Syc }
582000161856Syc 
582100161856Syc 
582200161856Syc /*
582300161856Syc  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
582400161856Syc  */
582500161856Syc static nxge_status_t
582600161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
582700161856Syc {
582800161856Syc 	nxge_status_t	status = NXGE_OK;
582900161856Syc 	p_nxge_stats_t	statsp;
583000161856Syc 	uint8_t		phy_port_addr, portn;
583100161856Syc 	uint16_t	val;
583200161856Syc 
583300161856Syc 	*link_up = LINK_NO_CHANGE;
583400161856Syc 
583500161856Syc 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
583600161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
583700161856Syc 	statsp = nxgep->statsp;
583800161856Syc 
583900161856Syc 	/* Check if link is up */
584000161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
584100161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
584200161856Syc 	    != NXGE_OK) {
584300161856Syc 		goto fail;
584400161856Syc 	}
584500161856Syc 	/*
584600161856Syc 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
584700161856Syc 	 * portmode and link_speed
584800161856Syc 	 */
584900161856Syc 	if (val & TN1010_AN_LINK_STAT_BIT) {
585000161856Syc 		if (nxgep->link_notify ||
585100161856Syc 		    nxgep->statsp->mac_stats.link_up == 0) {
585200161856Syc 			statsp->mac_stats.link_up = 1;
585300161856Syc 			statsp->mac_stats.link_duplex = 2;
585400161856Syc 			*link_up = LINK_IS_UP;
585500161856Syc 			nxgep->link_notify = B_FALSE;
585600161856Syc 		}
585700161856Syc 	} else {
585800161856Syc 		if (nxgep->link_notify ||
585900161856Syc 		    nxgep->statsp->mac_stats.link_up == 1) {
586000161856Syc 			statsp->mac_stats.link_up = 0;
586100161856Syc 			statsp->mac_stats.link_speed = 0;
586200161856Syc 			statsp->mac_stats.link_duplex = 0;
586300161856Syc 			*link_up = LINK_IS_DOWN;
586400161856Syc 			nxgep->link_notify = B_FALSE;
586500161856Syc 		}
586600161856Syc 	}
586700161856Syc 	return (NXGE_OK);
586800161856Syc 
586900161856Syc fail:
587000161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
587100161856Syc 	    "nxge_tn1010_check: Unable to check TN1010"));
587200161856Syc 	return (status);
587344961713Sgirish }
587444961713Sgirish 
587500161856Syc 
587644961713Sgirish /* Set promiscous mode */
587744961713Sgirish 
587844961713Sgirish nxge_status_t
587944961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
588044961713Sgirish {
588144961713Sgirish 	nxge_status_t status = NXGE_OK;
588244961713Sgirish 
588359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
588444961713Sgirish 
588544961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
588644961713Sgirish 
588744961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
588844961713Sgirish 
588944961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
589044961713Sgirish 		goto fail;
589144961713Sgirish 	}
589244961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
589344961713Sgirish 		goto fail;
589444961713Sgirish 	}
589544961713Sgirish 
589644961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
589744961713Sgirish 
589844961713Sgirish 	if (on)
589944961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
590044961713Sgirish 	else
590144961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
590244961713Sgirish 
590344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
590444961713Sgirish 
590544961713Sgirish 	return (NXGE_OK);
590644961713Sgirish fail:
590744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
590844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
590959ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
591044961713Sgirish 
591144961713Sgirish 	return (status);
591244961713Sgirish }
591344961713Sgirish 
591444961713Sgirish /*ARGSUSED*/
591544961713Sgirish uint_t
591644961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
591744961713Sgirish {
591844961713Sgirish #ifdef	NXGE_DEBUG
591944961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
592044961713Sgirish #endif
592144961713Sgirish #if NXGE_MIF
592244961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
592344961713Sgirish 	uint32_t		status;
592444961713Sgirish 	npi_handle_t		handle;
592544961713Sgirish 	uint8_t			portn;
592644961713Sgirish 	p_nxge_stats_t		statsp;
592744961713Sgirish #endif
592844961713Sgirish 
592944961713Sgirish #ifdef	NXGE_MIF
593044961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
593144961713Sgirish 		nxgep = ldvp->nxgep;
593244961713Sgirish 	}
593344961713Sgirish 	nxgep = ldvp->nxgep;
593444961713Sgirish #endif
593544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
593644961713Sgirish 
593744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
593844961713Sgirish 	return (DDI_INTR_CLAIMED);
593944961713Sgirish 
594044961713Sgirish mif_intr_fail:
594144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
594244961713Sgirish 	return (DDI_INTR_UNCLAIMED);
594344961713Sgirish }
594444961713Sgirish 
594544961713Sgirish /*ARGSUSED*/
594644961713Sgirish uint_t
594744961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
594844961713Sgirish {
594944961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
595044961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
595144961713Sgirish 	p_nxge_ldg_t		ldgp;
595244961713Sgirish 	uint32_t		status;
595344961713Sgirish 	npi_handle_t		handle;
595444961713Sgirish 	uint8_t			portn;
595544961713Sgirish 	p_nxge_stats_t		statsp;
595644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
595744961713Sgirish 
595844961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
595944961713Sgirish 		nxgep = ldvp->nxgep;
596044961713Sgirish 	}
596144961713Sgirish 
596244961713Sgirish 	ldgp = ldvp->ldgp;
596344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
596459ac0c16Sdavemq 	    "group %d", ldgp->ldg));
596544961713Sgirish 
596644961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
596744961713Sgirish 	/*
596844961713Sgirish 	 * This interrupt handler is for a specific
596944961713Sgirish 	 * mac port.
597044961713Sgirish 	 */
597144961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
597244961713Sgirish 	portn = nxgep->mac.portnum;
597344961713Sgirish 
597444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
597559ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
597644961713Sgirish 
597744961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
597844961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
597952ccf843Smisaki 		    (xmac_tx_iconfig_t *)&status);
598044961713Sgirish 		if (rs != NPI_SUCCESS)
598144961713Sgirish 			goto npi_fail;
598244961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
598344961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
598444961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
598544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
598652ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
598744961713Sgirish 			}
598844961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
598944961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
5990f6485eecSyc 				/*
5991f6485eecSyc 				 * Do not send FMA ereport because this
5992f6485eecSyc 				 * error does not indicate HW failure.
5993f6485eecSyc 				 */
599444961713Sgirish 			}
599544961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
599644961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
599744961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
599852ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
599944961713Sgirish 			}
600044961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
600144961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
600244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
600352ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
600444961713Sgirish 			}
600544961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
600644961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
600752ccf843Smisaki 				    XTXMAC_BYTE_CNT_MASK;
600844961713Sgirish 			}
600944961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
601044961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
601152ccf843Smisaki 				    XTXMAC_FRM_CNT_MASK;
601244961713Sgirish 			}
601344961713Sgirish 		}
601444961713Sgirish 
601544961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
601652ccf843Smisaki 		    (xmac_rx_iconfig_t *)&status);
601744961713Sgirish 		if (rs != NPI_SUCCESS)
601844961713Sgirish 			goto npi_fail;
601944961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
602044961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
602144961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
602244961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
602344961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
602444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
602552ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
602644961713Sgirish 			}
6027f6485eecSyc 			/*
6028f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
6029f6485eecSyc 			 * because they do not indicate HW failures.
6030f6485eecSyc 			 */
603144961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
603244961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
603352ccf843Smisaki 				    XRXMAC_CRC_ER_CNT_MASK;
603444961713Sgirish 			}
603544961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
603644961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
603752ccf843Smisaki 				    MAC_LEN_ER_CNT_MASK;
603844961713Sgirish 			}
603944961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
604044961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
604152ccf843Smisaki 				    XRXMAC_CD_VIO_CNT_MASK;
604244961713Sgirish 			}
604344961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
604444961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
604552ccf843Smisaki 				    XRXMAC_BT_CNT_MASK;
604644961713Sgirish 			}
604744961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
604844961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
604952ccf843Smisaki 				    XRXMAC_HIST_CNT1_MASK;
605044961713Sgirish 			}
605144961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
605244961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
605352ccf843Smisaki 				    XRXMAC_HIST_CNT2_MASK;
605444961713Sgirish 			}
605544961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
605644961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
605752ccf843Smisaki 				    XRXMAC_HIST_CNT3_MASK;
605844961713Sgirish 			}
605944961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
606044961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
606152ccf843Smisaki 				    XRXMAC_HIST_CNT4_MASK;
606244961713Sgirish 			}
606344961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
606444961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
606552ccf843Smisaki 				    XRXMAC_HIST_CNT5_MASK;
606644961713Sgirish 			}
606744961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
606844961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
606952ccf843Smisaki 				    XRXMAC_HIST_CNT6_MASK;
607044961713Sgirish 			}
607144961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
607244961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
607352ccf843Smisaki 				    XRXMAC_BC_FRM_CNT_MASK;
607444961713Sgirish 			}
607544961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
607644961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
607752ccf843Smisaki 				    XRXMAC_MC_FRM_CNT_MASK;
607844961713Sgirish 			}
6079f6485eecSyc 			/*
6080f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
6081f6485eecSyc 			 * because they do not indicate HW failures.
6082f6485eecSyc 			 */
608344961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
608444961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
608552ccf843Smisaki 				    XRXMAC_FRAG_CNT_MASK;
608644961713Sgirish 			}
608744961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
608844961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
608952ccf843Smisaki 				    XRXMAC_AL_ER_CNT_MASK;
609044961713Sgirish 			}
609144961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
609244961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
609352ccf843Smisaki 				    XMAC_LINK_FLT_CNT_MASK;
609444961713Sgirish 			}
609544961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
609644961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
609744961713Sgirish 			}
609844961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
609944961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
610044961713Sgirish 			}
610144961713Sgirish 		}
610244961713Sgirish 
610344961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
610452ccf843Smisaki 		    (xmac_ctl_iconfig_t *)&status);
610544961713Sgirish 		if (rs != NPI_SUCCESS)
610644961713Sgirish 			goto npi_fail;
610744961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
610844961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
610944961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
611044961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
611144961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
611244961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
611344961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
611444961713Sgirish 		}
611544961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
611644961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
611752ccf843Smisaki 		    (bmac_tx_iconfig_t *)&status);
611844961713Sgirish 		if (rs != NPI_SUCCESS)
611944961713Sgirish 			goto npi_fail;
612044961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
612144961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
612244961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
612344961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
612452ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
612544961713Sgirish 			}
612644961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
612744961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
612844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
612952ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
613044961713Sgirish 			}
613144961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
613244961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
613352ccf843Smisaki 				    BTXMAC_BYTE_CNT_MASK;
613444961713Sgirish 			}
613544961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
613644961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
613752ccf843Smisaki 				    BTXMAC_FRM_CNT_MASK;
613844961713Sgirish 			}
613944961713Sgirish 		}
614044961713Sgirish 
614144961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
614252ccf843Smisaki 		    (bmac_rx_iconfig_t *)&status);
614344961713Sgirish 		if (rs != NPI_SUCCESS)
614444961713Sgirish 			goto npi_fail;
614544961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
614644961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
614744961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
614844961713Sgirish 			}
614944961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
615044961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
615152ccf843Smisaki 				    RXMAC_FRM_CNT_MASK;
615244961713Sgirish 			}
615344961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
615444961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
615552ccf843Smisaki 				    BMAC_CRC_ER_CNT_MASK;
615644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
615752ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
615844961713Sgirish 			}
615944961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
616044961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
616152ccf843Smisaki 				    MAC_LEN_ER_CNT_MASK;
616244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
616352ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
616444961713Sgirish 			}
616544961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
616644961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
616752ccf843Smisaki 				    BMAC_CD_VIO_CNT_MASK;
616844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
616952ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
617044961713Sgirish 			}
617144961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
617244961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
617352ccf843Smisaki 				    BRXMAC_BYTE_CNT_MASK;
617444961713Sgirish 			}
617544961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
617644961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
617752ccf843Smisaki 				    BMAC_AL_ER_CNT_MASK;
617844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
617952ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
618044961713Sgirish 			}
618144961713Sgirish 
618244961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
618352ccf843Smisaki 			    (bmac_ctl_iconfig_t *)&status);
618444961713Sgirish 			if (rs != NPI_SUCCESS)
618544961713Sgirish 				goto npi_fail;
618644961713Sgirish 
618744961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
618844961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
618944961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
619044961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
619144961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
619244961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
619344961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
619444961713Sgirish 			}
619544961713Sgirish 		}
619644961713Sgirish 
619744961713Sgirish 	if (ldgp->nldvs == 1) {
619844961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
619952ccf843Smisaki 		    B_TRUE, ldgp->ldg_timer);
620044961713Sgirish 	}
620144961713Sgirish 
620244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
620344961713Sgirish 	return (DDI_INTR_CLAIMED);
620444961713Sgirish 
620544961713Sgirish npi_fail:
620644961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
620744961713Sgirish 	return (DDI_INTR_UNCLAIMED);
620844961713Sgirish }
620944961713Sgirish 
621044961713Sgirish nxge_status_t
621144961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
621244961713Sgirish {
621344961713Sgirish 	uint8_t		phy_port_addr;
621444961713Sgirish 	nxge_status_t	status = NXGE_OK;
621544961713Sgirish 	boolean_t	rx_sig_ok;
621644961713Sgirish 	boolean_t	pcs_blk_lock;
621744961713Sgirish 	boolean_t	link_align;
621844961713Sgirish 	uint16_t	val1, val2, val3;
621944961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
622044961713Sgirish 	uint16_t	val_debug;
6221*4df55fdeSJanie Lu 	uint32_t	val;
622244961713Sgirish #endif
622344961713Sgirish 
622444961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
622544961713Sgirish 
622644961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
622744961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
622844961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
622944961713Sgirish 	if ((val_debug & ~0x200) != 0) {
623044961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
623152ccf843Smisaki 		    nxgep->mac.portnum, val_debug);
623244961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
623352ccf843Smisaki 		    &val_debug);
623444961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
623552ccf843Smisaki 		    nxgep->mac.portnum, val_debug);
623644961713Sgirish 	}
623744961713Sgirish 
623844961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
623952ccf843Smisaki 	    XPCS_REG_DESCWERR_COUNTER, &val);
624044961713Sgirish 	if (val != 0)
624144961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
624244961713Sgirish 
624344961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
624452ccf843Smisaki 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
624544961713Sgirish 	if (val != 0)
624644961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
624744961713Sgirish 
624844961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
624952ccf843Smisaki 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
625044961713Sgirish 	if (val != 0)
625144961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
625244961713Sgirish #endif
625344961713Sgirish 
625444961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
625544961713Sgirish 
625644961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
625752ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
625852ccf843Smisaki 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
625944961713Sgirish 	if (status != NXGE_OK)
626044961713Sgirish 		goto fail;
626144961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
626244961713Sgirish 
626344961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
626452ccf843Smisaki 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
626552ccf843Smisaki 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
626644961713Sgirish 		goto fail;
626744961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
626844961713Sgirish 
626944961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
627052ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
627152ccf843Smisaki 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
627244961713Sgirish 	if (status != NXGE_OK)
627344961713Sgirish 		goto fail;
62742d17280bSsbehera 
62752d17280bSsbehera 	switch (nxgep->chip_id) {
62762d17280bSsbehera 	case BCM8704_CHIP_ID:
62772d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
62782d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
62792d17280bSsbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
62802d17280bSsbehera 		break;
62812d17280bSsbehera 	case BCM8706_CHIP_ID:
62822d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
62832d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
62842d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
62852d17280bSsbehera 		    B_TRUE : B_FALSE;
62862d17280bSsbehera 		break;
62872d17280bSsbehera 	default:
62882d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
62892d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
62902d17280bSsbehera 		goto fail;
62912d17280bSsbehera 	}
62922d17280bSsbehera 
629344961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
629444961713Sgirish 	/* Temp workaround for link down issue */
629544961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
629644961713Sgirish 		if (val2 != 0x4) {
629744961713Sgirish 			pcs_blk_lock = B_TRUE;
629852ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
629952ccf843Smisaki 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
630044961713Sgirish 		}
630144961713Sgirish 	}
630244961713Sgirish 
630344961713Sgirish 	if (link_align == B_FALSE) {
630444961713Sgirish 		if (val3 != 0x140f) {
630544961713Sgirish 			link_align = B_TRUE;
630652ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
630752ccf843Smisaki 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
630844961713Sgirish 		}
630944961713Sgirish 	}
631044961713Sgirish 
631144961713Sgirish 	if (rx_sig_ok == B_FALSE) {
631244961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
631344961713Sgirish 			rx_sig_ok = B_TRUE;
631444961713Sgirish 			cmn_err(CE_NOTE,
631552ccf843Smisaki 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
631652ccf843Smisaki 			    nxgep->mac.portnum);
631744961713Sgirish 		}
631844961713Sgirish 	}
631944961713Sgirish #endif
632044961713Sgirish 
632144961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
632252ccf843Smisaki 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
632344961713Sgirish 
632444961713Sgirish 	return (NXGE_OK);
632544961713Sgirish fail:
632644961713Sgirish 	return (status);
632744961713Sgirish }
632844961713Sgirish 
632952cdd236Ssbehera static nxge_status_t
633000161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
633152cdd236Ssbehera {
633252cdd236Ssbehera 	uint8_t		phy;
633352cdd236Ssbehera 	nxge_status_t   status = NXGE_OK;
633452cdd236Ssbehera 	boolean_t	pma_status;
633552cdd236Ssbehera 	boolean_t	pcs_status;
633652cdd236Ssbehera 	boolean_t	xgxs_status;
633752cdd236Ssbehera 	uint16_t	val;
633852cdd236Ssbehera 
633952cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
634052cdd236Ssbehera 
634152cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
634252cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
634352cdd236Ssbehera 
634452cdd236Ssbehera 	*link_up = B_FALSE;
634552cdd236Ssbehera 
634652cdd236Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
634752cdd236Ssbehera 
634852cdd236Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
634952cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
635052cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
635152cdd236Ssbehera 
635252cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
635352cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
635452cdd236Ssbehera 
635552cdd236Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
635652cdd236Ssbehera 
635752cdd236Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
635852cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
635952cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
636052cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
636152cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
636252cdd236Ssbehera 
636352cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
636452cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
636552cdd236Ssbehera 
636652cdd236Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
636752cdd236Ssbehera 
636852cdd236Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
636952cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
637052cdd236Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
637152cdd236Ssbehera 
637252cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
637352cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
637452cdd236Ssbehera 
637552cdd236Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
637652cdd236Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
637752cdd236Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
637852cdd236Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
637952cdd236Ssbehera 
638052cdd236Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
638152cdd236Ssbehera 	    B_TRUE : B_FALSE;
638252cdd236Ssbehera 
638352cdd236Ssbehera fail:
638452cdd236Ssbehera 
638552cdd236Ssbehera 	if (*link_up == B_FALSE) {
638652cdd236Ssbehera 		/* PCS OFF */
638752cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
638852cdd236Ssbehera 	} else {
638952cdd236Ssbehera 		/* PCS Activity */
639052cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
639152cdd236Ssbehera 	}
639252cdd236Ssbehera 
639352cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
639452cdd236Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
639552cdd236Ssbehera 
639652cdd236Ssbehera 	return (status);
639752cdd236Ssbehera }
639852cdd236Ssbehera 
639959ac0c16Sdavemq nxge_status_t
640059ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
640159ac0c16Sdavemq {
640259ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
640359ac0c16Sdavemq 	    != NPI_SUCCESS)
640459ac0c16Sdavemq 		return (NXGE_ERROR);
640559ac0c16Sdavemq 	else
640659ac0c16Sdavemq 		return (NXGE_OK);
640759ac0c16Sdavemq }
640844961713Sgirish 
640944961713Sgirish nxge_status_t
641059ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
641144961713Sgirish {
641259ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
641359ac0c16Sdavemq 	    != NPI_SUCCESS)
641459ac0c16Sdavemq 		return (NXGE_ERROR);
641559ac0c16Sdavemq 	else
641659ac0c16Sdavemq 		return (NXGE_OK);
641759ac0c16Sdavemq }
641844961713Sgirish 
64192d17280bSsbehera static boolean_t
64202d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
64212d17280bSsbehera {
64222d17280bSsbehera 	uint32_t pma_pmd_id = 0;
64232d17280bSsbehera 	uint32_t pcs_id = 0;
64242d17280bSsbehera 	uint32_t phy_id = 0;
64252d17280bSsbehera 
64262d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
64272d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64282d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
64292d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
64302d17280bSsbehera 		goto found_phy;
64312d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
64322d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64332d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
64342d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
64352d17280bSsbehera 		goto found_phy;
64362d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
64372d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64382d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
64392d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
64402d17280bSsbehera 		goto found_phy;
64412d17280bSsbehera 
64422d17280bSsbehera 	return (B_FALSE);
64432d17280bSsbehera 
64442d17280bSsbehera found_phy:
64452d17280bSsbehera 	return (B_TRUE);
64462d17280bSsbehera }
64472d17280bSsbehera 
644859ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
644959ac0c16Sdavemq 
645059ac0c16Sdavemq static boolean_t
645159ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
645259ac0c16Sdavemq {
645359ac0c16Sdavemq 	int		i;
645459ac0c16Sdavemq 	boolean_t	found = B_FALSE;
645559ac0c16Sdavemq 
645659ac0c16Sdavemq 	switch (type) {
645759ac0c16Sdavemq 	case CLAUSE_45_TYPE:
645800161856Syc 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
645900161856Syc 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
646000161856Syc 			    (id & BCM_PHY_ID_MASK)) ||
646100161856Syc 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
646259ac0c16Sdavemq 				found = B_TRUE;
646359ac0c16Sdavemq 				break;
646459ac0c16Sdavemq 			}
646559ac0c16Sdavemq 		}
646659ac0c16Sdavemq 		break;
646759ac0c16Sdavemq 	case CLAUSE_22_TYPE:
646800161856Syc 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
646930505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
647030505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
647159ac0c16Sdavemq 				found = B_TRUE;
647259ac0c16Sdavemq 				break;
647356d930aeSspeer 			}
647444961713Sgirish 		}
647559ac0c16Sdavemq 		break;
647659ac0c16Sdavemq 	default:
647759ac0c16Sdavemq 		break;
647856d930aeSspeer 	}
647956d930aeSspeer 
648059ac0c16Sdavemq 	return (found);
648159ac0c16Sdavemq }
648259ac0c16Sdavemq 
64832e59129aSraghus static uint32_t
64842e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
64852e59129aSraghus {
64862e59129aSraghus 	uint16_t	val1 = 0;
64872e59129aSraghus 	uint16_t	val2 = 0;
64882e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
64892e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
64902e59129aSraghus 
649153560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
64922e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
64932e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
64942e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
64952e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
649653560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
64972e59129aSraghus 
649800161856Syc 	/* Concatenate the Device ID stored in two registers. */
64992e59129aSraghus 	pma_pmd_dev_id = val1;
65002e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
65012e59129aSraghus 	pma_pmd_dev_id |= val2;
65022e59129aSraghus 
65032e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
65042e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
65052e59129aSraghus 
65062e59129aSraghus 	return (pma_pmd_dev_id);
65072e59129aSraghus }
65082e59129aSraghus 
65092e59129aSraghus static uint32_t
65102e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
65112e59129aSraghus {
65122e59129aSraghus 	uint16_t	val1 = 0;
65132e59129aSraghus 	uint16_t	val2 = 0;
65142e59129aSraghus 	uint32_t	pcs_dev_id = 0;
65152e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
65162e59129aSraghus 
651753560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
65182e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
65192e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
65202e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
65212e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
652253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
65232e59129aSraghus 
65242e59129aSraghus 	pcs_dev_id = val1;
65252e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
65262e59129aSraghus 	pcs_dev_id |= val2;
65272e59129aSraghus 
65282e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
65292e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
65302e59129aSraghus 
65312e59129aSraghus 	return (pcs_dev_id);
65322e59129aSraghus }
65332e59129aSraghus 
65342e59129aSraghus static uint32_t
65352e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
65362e59129aSraghus {
65372e59129aSraghus 	uint16_t	val1 = 0;
65382e59129aSraghus 	uint16_t	val2 = 0;
65392e59129aSraghus 	uint32_t	phy_id = 0;
65402e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
65412e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
65422e59129aSraghus 
6543321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
65442e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
65452e59129aSraghus 	    &val1);
65462e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
65472e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
65482e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
65492e59129aSraghus 		goto exit;
65502e59129aSraghus 	}
65512e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
65522e59129aSraghus 	    &val2);
65532e59129aSraghus 	if (npi_status != 0) {
65542e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
65552e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
65562e59129aSraghus 		goto exit;
65572e59129aSraghus 	}
65582e59129aSraghus 	phy_id = val1;
65592e59129aSraghus 	phy_id = (phy_id << 16);
65602e59129aSraghus 	phy_id |= val2;
65612e59129aSraghus 
65622e59129aSraghus exit:
6563321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
65642e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
65652e59129aSraghus 	    phy_port, phy_id));
65662e59129aSraghus 
65672e59129aSraghus 	return (phy_id);
65682e59129aSraghus }
65692e59129aSraghus 
657059ac0c16Sdavemq /*
657159ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
657259ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
657359ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
657459ac0c16Sdavemq  * and the Neptune type.
657500161856Syc  *
657600161856Syc  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
657700161856Syc  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
657800161856Syc  * in case the portmode information is not available via OBP, nxge.conf,
657900161856Syc  * VPD or SEEPROM.
658059ac0c16Sdavemq  */
658159ac0c16Sdavemq nxge_status_t
658259ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
658359ac0c16Sdavemq {
658459a835ddSjoycey 	int		i, j, l;
658559ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
658659ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
658759ac0c16Sdavemq 	uint32_t	phy_id = 0;
658830505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
658930505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
659030505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
659159ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
659259ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
65932d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
65942d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
659559ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
659600161856Syc 	uint8_t		num_xaui;
659759ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
659856d930aeSspeer 
659959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
660056d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
660159ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
660259ac0c16Sdavemq 	    nxgep->niu_type));
660359ac0c16Sdavemq 
6604678453a8Sspeer 	if (isLDOMguest(nxgep)) {
6605678453a8Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
6606678453a8Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
6607678453a8Sspeer 		return (NXGE_OK);
6608678453a8Sspeer 	}
6609678453a8Sspeer 
661059a835ddSjoycey 	j = l = 0;
661159ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
661256d930aeSspeer 	/*
661323b952a3SSantwona Behera 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
661423b952a3SSantwona Behera 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
661556d930aeSspeer 	 */
661659ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
66172e59129aSraghus 
66182e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
661959ac0c16Sdavemq 
662059ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
662159ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
662259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
662352cdd236Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
662430505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
662500161856Syc 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
662600161856Syc 				    == TN1010_DEV_ID) {
662700161856Syc 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
662800161856Syc 				} else {
662900161856Syc 					port_pma_pmd_dev_id[j] =
663052ccf843Smisaki 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
663100161856Syc 				}
66322d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
663359ac0c16Sdavemq 				j++;
663459ac0c16Sdavemq 			}
663559ac0c16Sdavemq 		} else {
663659ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
663759ac0c16Sdavemq 		}
663859ac0c16Sdavemq 
66392e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
664059ac0c16Sdavemq 
664159ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
664259ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
664359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
664452cdd236Ssbehera 			    "dev %x found", i, pcs_dev_id));
664559a835ddSjoycey 			if (pma_pmd_dev_fd[i] == 1) {
664600161856Syc 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
664700161856Syc 				    == TN1010_DEV_ID) {
664800161856Syc 					port_pcs_dev_id[j - 1] =
664900161856Syc 					    TN1010_DEV_ID;
665000161856Syc 				} else {
665100161856Syc 					port_pcs_dev_id[j - 1] =
665200161856Syc 					    pcs_dev_id &
665300161856Syc 					    BCM_PHY_ID_MASK;
665400161856Syc 				}
665559a835ddSjoycey 			} else {
665659a835ddSjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
665700161856Syc 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
665852ccf843Smisaki 					    == TN1010_DEV_ID) {
665900161856Syc 						port_pcs_dev_id[j] =
666000161856Syc 						    TN1010_DEV_ID;
666100161856Syc 					} else {
666200161856Syc 						port_pcs_dev_id[j] =
666300161856Syc 						    pcs_dev_id &
666400161856Syc 						    BCM_PHY_ID_MASK;
666500161856Syc 					}
666659a835ddSjoycey 					port_fd_arr[j] = (uint8_t)i;
666759a835ddSjoycey 					j++;
666859a835ddSjoycey 				}
666959ac0c16Sdavemq 			}
667059ac0c16Sdavemq 		} else {
667159ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
667259ac0c16Sdavemq 		}
667359ac0c16Sdavemq 
66742d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
66752d17280bSsbehera 			total_port_fd ++;
66762d17280bSsbehera 		}
667759ac0c16Sdavemq 
66782e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
667959ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
66802d17280bSsbehera 			total_phy_fd ++;
668159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
668252cdd236Ssbehera 			    "%x found", i, phy_id));
668330505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
668400161856Syc 				if ((phy_id & TN1010_DEV_ID_MASK)
668500161856Syc 				    == TN1010_DEV_ID) {
668600161856Syc 					port_phy_id[l] = TN1010_DEV_ID;
668700161856Syc 				} else {
668800161856Syc 					port_phy_id[l]
668900161856Syc 					    = phy_id & BCM_PHY_ID_MASK;
669000161856Syc 				}
66912d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
669259ac0c16Sdavemq 				l++;
669359ac0c16Sdavemq 			}
669459ac0c16Sdavemq 		}
669559ac0c16Sdavemq 	}
669659ac0c16Sdavemq 
669759ac0c16Sdavemq 	switch (total_port_fd) {
669859ac0c16Sdavemq 	case 2:
669959ac0c16Sdavemq 		switch (total_phy_fd) {
670059ac0c16Sdavemq 		case 2:
670123b952a3SSantwona Behera 			/* 2 10G, 2 1G RGMII Fiber / copper */
670259a835ddSjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
670359a835ddSjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
670459a835ddSjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
670559a835ddSjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
670659a835ddSjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
670759a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
670859a835ddSjoycey 
670923b952a3SSantwona Behera 				switch (hw_p->platform_type) {
671023b952a3SSantwona Behera 				case P_NEPTUNE_ROCK:
671123b952a3SSantwona Behera 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
671223b952a3SSantwona Behera 					/*
671323b952a3SSantwona Behera 					 * ROCK platform has assigned a lower
671423b952a3SSantwona Behera 					 * addr to port 1. (port 0 = 0x9 and
671523b952a3SSantwona Behera 					 * port 1 = 0x8).
671623b952a3SSantwona Behera 					 */
671723b952a3SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
671823b952a3SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[1];
671923b952a3SSantwona Behera 
672023b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
672123b952a3SSantwona Behera 					    "Rock with 2 10G, 2 1GC"));
672223b952a3SSantwona Behera 					break;
672323b952a3SSantwona Behera 
672423b952a3SSantwona Behera 				case P_NEPTUNE_NONE:
672523b952a3SSantwona Behera 				default:
672623b952a3SSantwona Behera 					hw_p->platform_type =
672723b952a3SSantwona Behera 					    P_NEPTUNE_GENERIC;
672823b952a3SSantwona Behera 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
672959a835ddSjoycey 
673023b952a3SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
673123b952a3SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[1];
673223b952a3SSantwona Behera 
673323b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
673423b952a3SSantwona Behera 					    "ARTM card with 2 10G, 2 1GF"));
673523b952a3SSantwona Behera 					break;
673623b952a3SSantwona Behera 				}
673759a835ddSjoycey 
673859a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
673959a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
674059a835ddSjoycey 
674159a835ddSjoycey 			} else {
674259a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
674359a835ddSjoycey 				    "Unsupported neptune type 1"));
674459a835ddSjoycey 				goto error_exit;
674559a835ddSjoycey 			}
674659a835ddSjoycey 			break;
674759a835ddSjoycey 
674859ac0c16Sdavemq 		case 1:
674959ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
675059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
675159ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
675259ac0c16Sdavemq 			goto error_exit;
675359ac0c16Sdavemq 		case 0:
675400161856Syc 			/*
675500161856Syc 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
675600161856Syc 			 * cards, etc.
675700161856Syc 			 */
675830505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
675930505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
676030505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
676152cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
676252cdd236Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
676352cdd236Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
676452cdd236Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
676552cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
676652cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] ==
676752cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
67682e59129aSraghus 
67692e59129aSraghus 				/*
67702e59129aSraghus 				 * Check the first phy port address against
67712e59129aSraghus 				 * the known phy start addresses to determine
67722e59129aSraghus 				 * the platform type.
67732e59129aSraghus 				 */
67742d17280bSsbehera 
67752d17280bSsbehera 				switch (port_fd_arr[0]) {
677600161856Syc 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
677752cdd236Ssbehera 					/*
677852cdd236Ssbehera 					 * The Marvell case also falls into
677952cdd236Ssbehera 					 * this case as
678052cdd236Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
678100161856Syc 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
678252cdd236Ssbehera 					 * This is OK for the 2 10G case.
678352cdd236Ssbehera 					 */
67842e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
67852e59129aSraghus 					hw_p->platform_type =
67862e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
67872d17280bSsbehera 					break;
678800161856Syc 				case GOA_CLAUSE45_PORT_ADDR_BASE:
67892d17280bSsbehera 					if (hw_p->platform_type !=
67902d17280bSsbehera 					    P_NEPTUNE_NIU) {
67912d17280bSsbehera 						hw_p->platform_type =
67922d17280bSsbehera 						    P_NEPTUNE_GENERIC;
67932d17280bSsbehera 						hw_p->niu_type =
67942d17280bSsbehera 						    NEPTUNE_2_10GF;
67952d17280bSsbehera 					}
67962d17280bSsbehera 					break;
67972d17280bSsbehera 				default:
67982d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67992e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
68002e59129aSraghus 					goto error_exit;
68012e59129aSraghus 				}
68022d17280bSsbehera 
68032d17280bSsbehera 				for (i = 0; i < 2; i++) {
68042d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
68052d17280bSsbehera 				}
680600161856Syc 
680700161856Syc 			/* Both XAUI slots have copper XAUI cards */
680800161856Syc 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
680900161856Syc 			    == TN1010_DEV_ID) &&
681000161856Syc 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
681100161856Syc 			    == TN1010_DEV_ID)) ||
681200161856Syc 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
681300161856Syc 			    == TN1010_DEV_ID) &&
681400161856Syc 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
681500161856Syc 			    == TN1010_DEV_ID))) {
681600161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010;
681700161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
681800161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
681900161856Syc 
682000161856Syc 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
682100161856Syc 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
682200161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
682300161856Syc 			    == TN1010_DEV_ID) ||
682400161856Syc 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
682500161856Syc 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
682600161856Syc 			    TN1010_DEV_ID)) {
682700161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
682800161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
682900161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
683000161856Syc 
683100161856Syc 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
683200161856Syc 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
683300161856Syc 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
683400161856Syc 			    == TN1010_DEV_ID) ||
683500161856Syc 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
683600161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
683700161856Syc 			    == TN1010_DEV_ID)) {
683800161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
683900161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
684000161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
684100161856Syc 
684259ac0c16Sdavemq 			} else {
684359ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
684459ac0c16Sdavemq 				    "Unsupported neptune type 2"));
684559ac0c16Sdavemq 				goto error_exit;
684659ac0c16Sdavemq 			}
684759ac0c16Sdavemq 			break;
684800161856Syc 
684959ac0c16Sdavemq 		case 4:
685000161856Syc 			if (nxge_get_num_of_xaui(
685100161856Syc 			    port_pma_pmd_dev_id, port_pcs_dev_id,
685200161856Syc 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
685300161856Syc 				goto error_exit;
685400161856Syc 			}
685500161856Syc 			if (num_xaui != 2)
685600161856Syc 				goto error_exit;
685759ac0c16Sdavemq 
685800161856Syc 			/*
685900161856Syc 			 *  Maramba with 2 XAUIs (either fiber or copper)
686000161856Syc 			 *
686100161856Syc 			 * Check the first phy port address against
686200161856Syc 			 * the known phy start addresses to determine
686300161856Syc 			 * the platform type.
686400161856Syc 			 */
686500161856Syc 			switch (phy_fd_arr[0]) {
686600161856Syc 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
686700161856Syc 				hw_p->platform_type =
686800161856Syc 				    P_NEPTUNE_MARAMBA_P0;
686900161856Syc 				break;
687000161856Syc 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
687100161856Syc 				hw_p->platform_type =
687200161856Syc 				    P_NEPTUNE_MARAMBA_P1;
687300161856Syc 				break;
687400161856Syc 			default:
687500161856Syc 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
687600161856Syc 				    "Unknown port %d...Cannot "
687700161856Syc 				    "determine platform type", i));
687800161856Syc 				goto error_exit;
687900161856Syc 			}
68802d17280bSsbehera 
688100161856Syc 			hw_p->xcvr_addr[0] = port_fd_arr[0];
688200161856Syc 			hw_p->xcvr_addr[1] = port_fd_arr[1];
688300161856Syc 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
688400161856Syc 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
688500161856Syc 
688600161856Syc 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
688700161856Syc 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
688800161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
688900161856Syc 			    == TN1010_DEV_ID) {
689000161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
689100161856Syc 
689200161856Syc 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
689300161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
689400161856Syc 			    == TN1010_DEV_ID) &&
689500161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
689600161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
689700161856Syc 
689800161856Syc 			/* Both slots have fiber XAUI */
689900161856Syc 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
690000161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
69012e59129aSraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
69022e59129aSraghus 
690300161856Syc 			/* Both slots have copper XAUI */
690400161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
690500161856Syc 			    == TN1010_DEV_ID) &&
690600161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
690700161856Syc 			    == TN1010_DEV_ID) {
690800161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
69092d17280bSsbehera 
691059ac0c16Sdavemq 			} else {
691159ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
691259ac0c16Sdavemq 				    "Unsupported neptune type 3"));
691359ac0c16Sdavemq 				goto error_exit;
691459ac0c16Sdavemq 			}
691559ac0c16Sdavemq 			break;
691659ac0c16Sdavemq 		default:
691759ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
691859ac0c16Sdavemq 			    "Unsupported neptune type 5"));
691959ac0c16Sdavemq 			goto error_exit;
692059ac0c16Sdavemq 		}
692130505775Ssbehera 		break;
692200161856Syc 	case 1: 	/* Only one clause45 port */
692300161856Syc 		switch (total_phy_fd) {	/* Number of clause22 ports */
692459ac0c16Sdavemq 		case 3:
69252e59129aSraghus 			/*
69262e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
69272e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
69282e59129aSraghus 			 * 1_10G_3_1G
69292e59129aSraghus 			 */
69302e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69312e59129aSraghus 			    "Unsupported neptune type 7"));
69322e59129aSraghus 			goto error_exit;
693359ac0c16Sdavemq 		case 2:
693459ac0c16Sdavemq 			/*
693559ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
693659ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
693759ac0c16Sdavemq 			 * 1_10G_2_1G
693859ac0c16Sdavemq 			 */
693959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
694059ac0c16Sdavemq 			    "Unsupported neptune type 8"));
694159ac0c16Sdavemq 			goto error_exit;
694259ac0c16Sdavemq 		case 1:
694359ac0c16Sdavemq 			/*
694459ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
694559ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
694659ac0c16Sdavemq 			 * 1_10G_1_1G
694759ac0c16Sdavemq 			 */
694859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
694959ac0c16Sdavemq 			    "Unsupported neptune type 9"));
695059ac0c16Sdavemq 			goto error_exit;
695100161856Syc 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
695200161856Syc 			/* Fiber XAUI */
69532d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
69542d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
69552d17280bSsbehera 
69562d17280bSsbehera 				/*
69572d17280bSsbehera 				 * Check the first phy port address against
69582d17280bSsbehera 				 * the known phy start addresses to determine
69592d17280bSsbehera 				 * the platform type.
69602d17280bSsbehera 				 */
69612d17280bSsbehera 
69622d17280bSsbehera 				switch (port_fd_arr[0]) {
696300161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
696400161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
696500161856Syc 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
696600161856Syc 					/*
696700161856Syc 					 * If hw_p->platform_type ==
696800161856Syc 					 * P_NEPTUNE_NIU, then portmode
696900161856Syc 					 * is already known, so there is
697000161856Syc 					 * no need to figure out hw_p->
697100161856Syc 					 * platform_type because
697200161856Syc 					 * platform_type is only for
697300161856Syc 					 * figuring out portmode.
697400161856Syc 					 */
69752d17280bSsbehera 					if (hw_p->platform_type !=
69762d17280bSsbehera 					    P_NEPTUNE_NIU) {
69772d17280bSsbehera 						hw_p->platform_type =
69782d17280bSsbehera 						    P_NEPTUNE_GENERIC;
69792d17280bSsbehera 						hw_p->niu_type =
69802d17280bSsbehera 						    NEPTUNE_2_10GF;
69812d17280bSsbehera 					}
69822d17280bSsbehera 					break;
69832d17280bSsbehera 				default:
69842d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69852d17280bSsbehera 					    "Unsupported neptune type 10"));
69862d17280bSsbehera 					goto error_exit;
69872d17280bSsbehera 				}
6988321febdeSsbehera 				/*
6989321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
6990321febdeSsbehera 				 * phy address to function number mapping
6991321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
6992321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
6993321febdeSsbehera 				 * But for Huron XAUI, the assignment should
6994321febdeSsbehera 				 * be by function number, i.e., whichever
6995321febdeSsbehera 				 * function number attaches should be
6996321febdeSsbehera 				 * assigned the available PHY (this is required
6997321febdeSsbehera 				 * primarily to support pre-production Huron
6998321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
6999321febdeSsbehera 				 */
7000321febdeSsbehera 				if (port_fd_arr[0] ==
700100161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
7002321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
7003321febdeSsbehera 				} else {
7004321febdeSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
7005321febdeSsbehera 					    port_fd_arr[0];
7006321febdeSsbehera 				}
700700161856Syc 
700800161856Syc 			/* A 10G copper XAUI in either slot0 or slot1 */
700900161856Syc 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
701000161856Syc 			    == TN1010_DEV_ID ||
701100161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
701200161856Syc 			    == TN1010_DEV_ID) {
701300161856Syc 				switch (port_fd_arr[0]) {
701400161856Syc 				/* The XAUI is in slot0 */
701500161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
701600161856Syc 					hw_p->niu_type = NEPTUNE_1_TN1010;
701700161856Syc 					break;
701800161856Syc 
701900161856Syc 				/* The XAUI is in slot1 */
702000161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
702100161856Syc 					hw_p->niu_type
702200161856Syc 					    = NEPTUNE_1_NONE_1_TN1010;
702300161856Syc 					break;
702400161856Syc 				default:
702500161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
702600161856Syc 					    "Unsupported XAUI port address"));
702700161856Syc 					goto error_exit;
702800161856Syc 				}
702900161856Syc 				hw_p->xcvr_addr[nxgep->function_num]
703000161856Syc 				    = port_fd_arr[0];
703100161856Syc 
70322d17280bSsbehera 			} else {
70332d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
703400161856Syc 				    "Unsupported PHY type"));
70352d17280bSsbehera 				goto error_exit;
70362d17280bSsbehera 			}
70372d17280bSsbehera 			break;
703800161856Syc 		case 4: /* Maramba always have 4 clause 45 ports */
703959ac0c16Sdavemq 
704000161856Syc 			/* Maramba with 1 XAUI */
704152ccf843Smisaki 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
704252ccf843Smisaki 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
704300161856Syc 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
704452ccf843Smisaki 			    != TN1010_DEV_ID) &&
704500161856Syc 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
704652ccf843Smisaki 			    != TN1010_DEV_ID)) {
704752ccf843Smisaki 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
704852ccf843Smisaki 				    "Unsupported neptune type 12"));
704952ccf843Smisaki 				goto error_exit;
705052ccf843Smisaki 			}
70512e59129aSraghus 
705252ccf843Smisaki 			/*
705352ccf843Smisaki 			 * Check the first phy port address against
705452ccf843Smisaki 			 * the known phy start addresses to determine
705552ccf843Smisaki 			 * the platform type.
705652ccf843Smisaki 			 */
705752ccf843Smisaki 			switch (phy_fd_arr[0]) {
705852ccf843Smisaki 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
705952ccf843Smisaki 				hw_p->platform_type =
706052ccf843Smisaki 				    P_NEPTUNE_MARAMBA_P0;
706152ccf843Smisaki 				break;
706252ccf843Smisaki 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
706352ccf843Smisaki 				hw_p->platform_type =
706452ccf843Smisaki 				    P_NEPTUNE_MARAMBA_P1;
706552ccf843Smisaki 				break;
706652ccf843Smisaki 			default:
706752ccf843Smisaki 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
706852ccf843Smisaki 				    "Unknown port %d...Cannot "
706952ccf843Smisaki 				    "determine platform type 10 - 2",
707052ccf843Smisaki 				    i));
707152ccf843Smisaki 				goto error_exit;
707252ccf843Smisaki 			}
707352ccf843Smisaki 
707452ccf843Smisaki 			/*
707552ccf843Smisaki 			 * Check the clause45 address to determine
707652ccf843Smisaki 			 * if XAUI is in port 0 or port 1.
707752ccf843Smisaki 			 */
707852ccf843Smisaki 			switch (port_fd_arr[0]) {
707952ccf843Smisaki 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
708052ccf843Smisaki 				if (port_pcs_dev_id[0]
708152ccf843Smisaki 				    == PHY_BCM8704_FAMILY ||
708252ccf843Smisaki 				    port_pma_pmd_dev_id[0]
708352ccf843Smisaki 				    == PHY_BCM8704_FAMILY) {
708452ccf843Smisaki 					hw_p->niu_type
708552ccf843Smisaki 					    = NEPTUNE_1_10GF_3_1GC;
708652ccf843Smisaki 				} else {
708752ccf843Smisaki 					hw_p->niu_type
708852ccf843Smisaki 					    = NEPTUNE_1_TN1010_3_1GC;
708959ac0c16Sdavemq 				}
709052ccf843Smisaki 				hw_p->xcvr_addr[0] = port_fd_arr[0];
709152ccf843Smisaki 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
709252ccf843Smisaki 					hw_p->xcvr_addr[i] =
709352ccf843Smisaki 					    phy_fd_arr[i];
709452ccf843Smisaki 				}
709552ccf843Smisaki 				break;
709652ccf843Smisaki 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
709752ccf843Smisaki 				if (port_pcs_dev_id[0]
709852ccf843Smisaki 				    == PHY_BCM8704_FAMILY ||
709952ccf843Smisaki 				    port_pma_pmd_dev_id[0]
710052ccf843Smisaki 				    == PHY_BCM8704_FAMILY) {
710152ccf843Smisaki 					hw_p->niu_type =
710252ccf843Smisaki 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
710352ccf843Smisaki 				} else {
710452ccf843Smisaki 					hw_p->niu_type =
710552ccf843Smisaki 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
710652ccf843Smisaki 				}
710752ccf843Smisaki 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
710852ccf843Smisaki 				hw_p->xcvr_addr[1] = port_fd_arr[0];
710952ccf843Smisaki 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
711052ccf843Smisaki 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
711152ccf843Smisaki 				break;
711252ccf843Smisaki 			default:
711359ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
711452ccf843Smisaki 				    "Unsupported neptune type 11"));
711559ac0c16Sdavemq 				goto error_exit;
711659ac0c16Sdavemq 			}
711752ccf843Smisaki 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
711852ccf843Smisaki 			    "Maramba with 1 XAUI (fiber or copper)"));
711959ac0c16Sdavemq 			break;
712059ac0c16Sdavemq 		default:
712159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
712259ac0c16Sdavemq 			    "Unsupported neptune type 13"));
712359ac0c16Sdavemq 			goto error_exit;
712459ac0c16Sdavemq 		}
712559ac0c16Sdavemq 		break;
712600161856Syc 	case 0: /* 4 ports Neptune based NIC */
712759ac0c16Sdavemq 		switch (total_phy_fd) {
712859ac0c16Sdavemq 		case 4:
712930505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
713030505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
713130505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
713230505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
713359ac0c16Sdavemq 
713459ac0c16Sdavemq 				/*
713559ac0c16Sdavemq 				 * Check the first phy port address against
713659ac0c16Sdavemq 				 * the known phy start addresses to determine
713759ac0c16Sdavemq 				 * the platform type.
713859ac0c16Sdavemq 				 */
71392d17280bSsbehera 				switch (phy_fd_arr[0]) {
714000161856Syc 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
714159ac0c16Sdavemq 					hw_p->platform_type =
714259ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
71432d17280bSsbehera 					break;
714400161856Syc 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
71452e59129aSraghus 					hw_p->platform_type =
71462e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
71472d17280bSsbehera 					break;
71482d17280bSsbehera 				default:
71492e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
71502e59129aSraghus 					    "Unknown port %d...Cannot "
71512e59129aSraghus 					    "determine platform type", i));
71522e59129aSraghus 					goto error_exit;
715359ac0c16Sdavemq 				}
71542e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
71552d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
71562d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
71572d17280bSsbehera 				}
715859ac0c16Sdavemq 			} else {
715959ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
716059ac0c16Sdavemq 				    "Unsupported neptune type 14"));
716159ac0c16Sdavemq 				goto error_exit;
716259ac0c16Sdavemq 			}
716359ac0c16Sdavemq 			break;
716459ac0c16Sdavemq 		case 3:
716559ac0c16Sdavemq 			/* TODO 3 1G mode */
716659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
716759ac0c16Sdavemq 			    "Unsupported neptune type 15"));
716859ac0c16Sdavemq 			goto error_exit;
716959ac0c16Sdavemq 		case 2:
717059ac0c16Sdavemq 			/* TODO 2 1G mode */
717159a835ddSjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
717259a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
717359a835ddSjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
717459a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
717559a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
717659a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
717759a835ddSjoycey 			} else {
717859a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
717959a835ddSjoycey 				    "Unsupported neptune type 16"));
718059a835ddSjoycey 				goto error_exit;
718159a835ddSjoycey 			}
718259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
718359a835ddSjoycey 			    "2 RGMII Fiber ports - RTM"));
718459a835ddSjoycey 			break;
718559a835ddSjoycey 
718659ac0c16Sdavemq 		case 1:
718759ac0c16Sdavemq 			/* TODO 1 1G mode */
718859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
718959ac0c16Sdavemq 			    "Unsupported neptune type 17"));
719059ac0c16Sdavemq 			goto error_exit;
719159ac0c16Sdavemq 		default:
719259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
719359ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
719459ac0c16Sdavemq 			    total_phy_fd));
719559ac0c16Sdavemq 			goto error_exit;
719659ac0c16Sdavemq 		}
719759ac0c16Sdavemq 		break;
719859ac0c16Sdavemq 	default:
719956d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
720059ac0c16Sdavemq 		    "Unsupported neptune type 19"));
720159ac0c16Sdavemq 		goto error_exit;
720244961713Sgirish 	}
720344961713Sgirish 
720459ac0c16Sdavemq scan_exit:
720544961713Sgirish 
720659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
720759ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
720859ac0c16Sdavemq 	return (status);
720944961713Sgirish 
721059ac0c16Sdavemq error_exit:
721159ac0c16Sdavemq 	return (NXGE_ERROR);
721244961713Sgirish }
721356d930aeSspeer 
721456d930aeSspeer boolean_t
721556d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
721656d930aeSspeer {
721756d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
721856d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
721956d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
722056d930aeSspeer 		return (B_FALSE);
722156d930aeSspeer 	else
722256d930aeSspeer 		return (B_TRUE);
722356d930aeSspeer }
722459ac0c16Sdavemq 
722559ac0c16Sdavemq static void
722659ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
722759ac0c16Sdavemq 
722859ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
722959ac0c16Sdavemq 	uint8_t xcvr_portn;
723059ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
723159ac0c16Sdavemq 
723259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
723359ac0c16Sdavemq 
723459ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
723500161856Syc 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
723659ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
723700161856Syc 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
723859ac0c16Sdavemq 	}
723959ac0c16Sdavemq 	/*
724059ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
724159ac0c16Sdavemq 	 * swapped with ethernet port number. This is
724259ac0c16Sdavemq 	 * designed for better signal integrity in routing.
724359ac0c16Sdavemq 	 */
724459ac0c16Sdavemq 	switch (portn) {
724559ac0c16Sdavemq 	case 0:
724659ac0c16Sdavemq 		xcvr_portn += 3;
724759ac0c16Sdavemq 		break;
724859ac0c16Sdavemq 	case 1:
724959ac0c16Sdavemq 		xcvr_portn += 2;
725059ac0c16Sdavemq 		break;
725159ac0c16Sdavemq 	case 2:
725259ac0c16Sdavemq 		xcvr_portn += 1;
725359ac0c16Sdavemq 		break;
725459ac0c16Sdavemq 	case 3:
725559ac0c16Sdavemq 	default:
725659ac0c16Sdavemq 		break;
725759ac0c16Sdavemq 	}
725859ac0c16Sdavemq 
7259321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
726059ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
726159ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
726259ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
726359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
726459ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
726559ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
7266321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
726759ac0c16Sdavemq 		return;
726859ac0c16Sdavemq 	}
726959ac0c16Sdavemq 
727059ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
727159ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
727259ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
727359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
727459ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
727559ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
727659ac0c16Sdavemq 	}
727759ac0c16Sdavemq 
7278321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
727959ac0c16Sdavemq }
7280d81011f0Ssbehera 
7281d81011f0Ssbehera static nxge_status_t
7282d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
7283d81011f0Ssbehera {
7284d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7285d81011f0Ssbehera 	uint8_t		xcvr_portn;
7286d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7287d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7288d81011f0Ssbehera 	int		status = NXGE_OK;
7289d81011f0Ssbehera 
7290d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
7291d81011f0Ssbehera 
7292d81011f0Ssbehera 	statsp = nxgep->statsp;
7293d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7294d81011f0Ssbehera 	mii_regs = NULL;
7295d81011f0Ssbehera 	mode.value = 0;
72966b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7297d81011f0Ssbehera #if defined(__i386)
7298d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7299d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7300d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7301d81011f0Ssbehera 		goto fail;
7302d81011f0Ssbehera #else
7303d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7304d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7305d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7306d81011f0Ssbehera 		goto fail;
7307d81011f0Ssbehera #endif
7308d81011f0Ssbehera 	}
7309d81011f0Ssbehera #if defined(__i386)
7310d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7311d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7312d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7313d81011f0Ssbehera 		goto fail;
7314d81011f0Ssbehera 	}
7315d81011f0Ssbehera #else
7316d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7317d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7318d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7319d81011f0Ssbehera 		goto fail;
7320d81011f0Ssbehera 	}
7321d81011f0Ssbehera #endif
7322d81011f0Ssbehera 
7323d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
7324d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
7325d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7326d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
7327d81011f0Ssbehera 	}
7328d81011f0Ssbehera 
7329d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7330d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
7331d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
73326b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
7333d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
7334d81011f0Ssbehera 
7335d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7336d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
7337d81011f0Ssbehera 	return (status);
7338d81011f0Ssbehera fail:
7339d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7340d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
7341d81011f0Ssbehera 	return (NXGE_ERROR);
7342d81011f0Ssbehera }
7343d81011f0Ssbehera 
73441bd6825cSml nxge_status_t
73451bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep)
73461bd6825cSml {
73471bd6825cSml 	npi_attr_t		ap;
73481bd6825cSml 	uint8_t			portn;
73491bd6825cSml 	npi_handle_t		handle;
73501bd6825cSml 	npi_status_t		rs = NPI_SUCCESS;
73511bd6825cSml 
73521bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
73531bd6825cSml 
73541bd6825cSml 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
73551bd6825cSml 	handle = nxgep->npi_handle;
73561bd6825cSml 
73571bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
73581bd6825cSml 	    "==> nxge_mac_sec_framesize: port<%d> "
73591bd6825cSml 	    "min framesize %d max framesize %d ",
73601bd6825cSml 	    portn,
73611bd6825cSml 	    nxgep->mac.minframesize,
73621bd6825cSml 	    nxgep->mac.maxframesize));
73631bd6825cSml 
73641bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
73651bd6825cSml 	    MAC_PORT_FRAME_SIZE,
73661bd6825cSml 	    nxgep->mac.minframesize,
73671bd6825cSml 	    nxgep->mac.maxframesize,
73681bd6825cSml 	    rs);
73691bd6825cSml 	if (rs != NPI_SUCCESS) {
73701bd6825cSml 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
73711bd6825cSml 		    "<== nxge_mac_set_framesize: failed to configure "
73721bd6825cSml 		    "max/min frame size port %d", portn));
73731bd6825cSml 
73741bd6825cSml 		return (NXGE_ERROR | rs);
73751bd6825cSml 	}
73761bd6825cSml 
73771bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
73781bd6825cSml 	    "<== nxge_mac_set_framesize: port<%d>", portn));
73791bd6825cSml 
73801bd6825cSml 	return (NXGE_OK);
73811bd6825cSml }
73821bd6825cSml 
738300161856Syc static nxge_status_t
738400161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
738500161856Syc     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
738600161856Syc {
738700161856Syc 	uint8_t i;
738800161856Syc 
738900161856Syc 	for (i = 0; i < 4; i++) {
739000161856Syc 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
739100161856Syc 			return (NXGE_ERROR);
739200161856Syc 	}
739300161856Syc 
739400161856Syc 	*num_xaui = 0;
739500161856Syc 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
739600161856Syc 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
739700161856Syc 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
739800161856Syc 	    == TN1010_DEV_ID) &&
739900161856Syc 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
740000161856Syc 	    == TN1010_DEV_ID))) {
740100161856Syc 		(*num_xaui) ++;
740200161856Syc 	}
740300161856Syc 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
740400161856Syc 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
740500161856Syc 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
740600161856Syc 	    == TN1010_DEV_ID) &&
740700161856Syc 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
740800161856Syc 	    == TN1010_DEV_ID))) {
740900161856Syc 		(*num_xaui) ++;
741000161856Syc 	}
741100161856Syc 	return (NXGE_OK);
741200161856Syc }
741300161856Syc 
741400161856Syc /*
741500161856Syc  * Instruction from Teranetics:  Once you detect link is up, go
741600161856Syc  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
741700161856Syc  * may want to qualify it by first checking Register 30.1.7:6 and
741800161856Syc  * making sure it reads "01" (Auto-Neg Complete).
741900161856Syc  *
742000161856Syc  * If this function is called when the link is down or before auto-
742100161856Syc  * negotiation has completed, then the speed of the PHY is not certain.
742200161856Syc  * In such cases, this function returns 1G as the default speed with
742300161856Syc  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
742400161856Syc  * driver based on a default speed because this function will be called
742500161856Syc  * again when the link comes up.  Returning NXGE_ERROR, which may
742600161856Syc  * cause brutal chain reaction in caller functions, is not necessary.
742700161856Syc  */
742800161856Syc static nxge_status_t
742900161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
743000161856Syc {
743100161856Syc 	uint8_t		phy_port_addr, autoneg_stat, link_up;
743200161856Syc 	nxge_status_t	status = NXGE_OK;
743300161856Syc 	uint16_t	val;
743400161856Syc 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
743500161856Syc 
743600161856Syc 	/* Set default speed to 10G */
743700161856Syc 	*speed = TN1010_SPEED_10G;
743800161856Syc 
743900161856Syc 	/* Set Clause 45 */
744000161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
744100161856Syc 
744200161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
744300161856Syc 
744400161856Syc 	/* Check Device 1 Register 0xA bit0 for link up status */
744500161856Syc 	status = nxge_mdio_read(nxgep, phy_port_addr,
744600161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
744700161856Syc 	if (status != NXGE_OK)
744800161856Syc 		goto fail;
744900161856Syc 
745000161856Syc 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
745100161856Syc 	    ? B_TRUE : B_FALSE);
745200161856Syc 	if (link_up == B_FALSE) {
745300161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
745400161856Syc 		    "nxge_get_tn1010_speed: link is down"));
745500161856Syc 		goto nxge_get_tn1010_speed_exit;
745600161856Syc 	}
745700161856Syc 
745800161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
745900161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
746000161856Syc 	    &val)) != NXGE_OK) {
746100161856Syc 		goto fail;
746200161856Syc 	}
746300161856Syc 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
746400161856Syc 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
746500161856Syc 
746600161856Syc 	/*
746700161856Syc 	 * Return NXGE_OK even when we can not get a settled speed. In
746800161856Syc 	 * such case, the speed reported should not be trusted but that
746900161856Syc 	 * is OK, we will call this function periodically and will get
747000161856Syc 	 * the correct speed after the link is up.
747100161856Syc 	 */
747200161856Syc 	switch (autoneg_stat) {
747300161856Syc 	case TN1010_AN_IN_PROG:
747400161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
747500161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
747600161856Syc 		break;
747700161856Syc 	case TN1010_AN_COMPLETE:
747800161856Syc 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
747900161856Syc 		    TN1010_VENDOR_MMD1_DEV_ADDR,
748000161856Syc 		    TN1010_VENDOR_MMD1_STATUS_REG,
748100161856Syc 		    &val)) != NXGE_OK) {
748200161856Syc 			goto fail;
748300161856Syc 		}
748400161856Syc 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
748500161856Syc 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
748600161856Syc 		break;
748700161856Syc 	case TN1010_AN_RSVD:
748800161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
748900161856Syc 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
749000161856Syc 		break;
749100161856Syc 	case TN1010_AN_FAILED:
749200161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
749300161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
749400161856Syc 		break;
749500161856Syc 	default:
749600161856Syc 		break;
749700161856Syc 	}
749800161856Syc nxge_get_tn1010_speed_exit:
749900161856Syc 	return (NXGE_OK);
750000161856Syc fail:
750100161856Syc 	return (status);
750200161856Syc }
750300161856Syc 
750400161856Syc 
750500161856Syc /*
750600161856Syc  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
750700161856Syc  * figures out the speed of the PHY determined by the autonegotiation
750800161856Syc  * process and sets the following 3 parameters,
750900161856Syc  * 	nxgep->mac.portmode
751000161856Syc  *     	nxgep->statsp->mac_stats.link_speed
751100161856Syc  *	nxgep->statsp->mac_stats.xcvr_inuse
751200161856Syc  */
751300161856Syc static nxge_status_t
751400161856Syc nxge_set_tn1010_param(p_nxge_t nxgep)
751500161856Syc {
751600161856Syc 	uint16_t speed;
751700161856Syc 
751800161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
751900161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
752000161856Syc 		    "nxge_set_tn1010_param: "
752100161856Syc 		    "Failed to get TN1010 speed"));
752200161856Syc 		return (NXGE_ERROR);
752300161856Syc 	}
752400161856Syc 	if (speed == TN1010_SPEED_1G) {
752500161856Syc 		nxgep->mac.portmode = PORT_1G_TN1010;
752600161856Syc 		nxgep->statsp->mac_stats.link_speed = 1000;
752700161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
752800161856Syc 	} else {
752900161856Syc 		nxgep->mac.portmode = PORT_10G_TN1010;
753000161856Syc 		nxgep->statsp->mac_stats.link_speed = 10000;
753100161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
753200161856Syc 	}
753300161856Syc 	return (NXGE_OK);
753400161856Syc }
753500161856Syc 
7536d81011f0Ssbehera #ifdef NXGE_DEBUG
7537d81011f0Ssbehera static void
7538d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
7539d81011f0Ssbehera {
7540d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7541d81011f0Ssbehera 	uint8_t		xcvr_portn;
7542d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7543d81011f0Ssbehera 	mii_bmcr_t	bmcr;
7544d81011f0Ssbehera 	mii_bmsr_t	bmsr;
7545d81011f0Ssbehera 	mii_idr1_t	idr1;
7546d81011f0Ssbehera 	mii_idr2_t	idr2;
7547d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7548678453a8Sspeer 	p_nxge_param_t	param_arr;
7549d81011f0Ssbehera 
7550d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
7551d81011f0Ssbehera 
7552d81011f0Ssbehera 	statsp = nxgep->statsp;
7553d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7554d81011f0Ssbehera 
7555d81011f0Ssbehera 	mii_regs = NULL;
7556d81011f0Ssbehera 
7557d81011f0Ssbehera #if defined(__i386)
7558d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7559d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
7560d81011f0Ssbehera #else
7561d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7562d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
7563d81011f0Ssbehera #endif
7564d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7565d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
7566d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
7567d81011f0Ssbehera 
7568d81011f0Ssbehera #if defined(__i386)
7569d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7570d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7571d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
7572d81011f0Ssbehera #else
7573d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7574d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7575d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
7576d81011f0Ssbehera #endif
7577d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7578d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
7579d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
7580d81011f0Ssbehera 
7581d81011f0Ssbehera #if defined(__i386)
7582d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7583d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7584d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
7585d81011f0Ssbehera #else
7586d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7587d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7588d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
7589d81011f0Ssbehera #endif
7590d81011f0Ssbehera 
7591d81011f0Ssbehera 
7592d81011f0Ssbehera #if defined(__i386)
7593d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7594d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7595d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
7596d81011f0Ssbehera #else
7597d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7598d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7599d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
7600d81011f0Ssbehera #endif
7601d81011f0Ssbehera 
7602d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7603d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
7604d81011f0Ssbehera 	    xcvr_portn, idr1.value));
7605d81011f0Ssbehera 
7606d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7607d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
7608d81011f0Ssbehera 	    xcvr_portn, idr2.value));
7609d81011f0Ssbehera 
7610d81011f0Ssbehera 	mode.value = 0;
76116b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7612d81011f0Ssbehera 
7613d81011f0Ssbehera #if defined(__i386)
7614d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7615d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
7616d81011f0Ssbehera 
7617d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7618d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
7619d81011f0Ssbehera #else
7620d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7621d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
7622d81011f0Ssbehera 
7623d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7624d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
7625d81011f0Ssbehera #endif
7626d81011f0Ssbehera 
7627d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7628d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
7629d81011f0Ssbehera 	    xcvr_portn, mode.value));
7630d81011f0Ssbehera }
7631d81011f0Ssbehera #endif
7632