xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision ef523517)
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);
9359ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
9459ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
9559ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
9659ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
9759ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
9859ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
9959ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
10059ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
10159ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
10259ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
10359ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1042d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1052d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
10659ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
10759ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
10800161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
10952cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
11000161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
11100161856Syc 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
11200161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
11300161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
11400161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
11500161856Syc 	nxge_link_state_t *link_up);
11600161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
11700161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
11800161856Syc 
11900161856Syc nxge_status_t nxge_mac_init(p_nxge_t);
12000161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
12100161856Syc 
12200161856Syc #ifdef NXGE_DEBUG
12300161856Syc static void nxge_mii_dump(p_nxge_t);
12400161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
12500161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
12600161856Syc #endif
12759ac0c16Sdavemq 
12859ac0c16Sdavemq /*
12959ac0c16Sdavemq  * xcvr tables for supported transceivers
13059ac0c16Sdavemq  */
13159ac0c16Sdavemq 
13200161856Syc /*
13300161856Syc  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
13400161856Syc  * The Teranetics TN1010 based copper XAUI card can also be used
13500161856Syc  * on N2-NIU systems in 10G mode, but it uses its own table
13600161856Syc  * nxge_n2_10G_tn1010_table below.
13700161856Syc  */
1382e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
13959ac0c16Sdavemq 	nxge_n2_serdes_init,
14059ac0c16Sdavemq 	nxge_10G_xcvr_init,
14159ac0c16Sdavemq 	nxge_10G_link_intr_stop,
14259ac0c16Sdavemq 	nxge_10G_link_intr_start,
14359ac0c16Sdavemq 	nxge_check_10g_link,
1442d17280bSsbehera 	PCS_XCVR
14559ac0c16Sdavemq };
14659ac0c16Sdavemq 
14700161856Syc /*
14800161856Syc  * For the Teranetics TN1010 based copper XAUI card
14900161856Syc  */
15000161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
15100161856Syc 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
15200161856Syc 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
15300161856Syc 	nxge_10G_link_intr_stop,
15400161856Syc 	nxge_10G_link_intr_start,
15500161856Syc 	nxge_check_tn1010_link,		/* Will figure out speed */
15600161856Syc 	XPCS_XCVR
15700161856Syc };
15800161856Syc 
1592e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1602e59129aSraghus 	nxge_n2_serdes_init,
1612e59129aSraghus 	nxge_1G_xcvr_init,
1622e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1632e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1642e59129aSraghus 	nxge_check_mii_link,
1652d17280bSsbehera 	PCS_XCVR
1662e59129aSraghus };
1672e59129aSraghus 
16800161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
16900161856Syc 	nxge_n2_serdes_init,
17000161856Syc 	nxge_tn1010_xcvr_init,
17100161856Syc 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
17200161856Syc 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
17300161856Syc 	nxge_check_tn1010_link,
17400161856Syc 	PCS_XCVR
17500161856Syc };
17600161856Syc 
17700161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = {
17800161856Syc 	nxge_neptune_10G_serdes_init,
17900161856Syc 	nxge_tn1010_xcvr_init,
18000161856Syc 	nxge_10G_link_intr_stop,
18100161856Syc 	nxge_10G_link_intr_start,
18200161856Syc 	nxge_check_tn1010_link,
18300161856Syc 	XPCS_XCVR
18400161856Syc };
18500161856Syc 
18600161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = {
18700161856Syc 	nxge_1G_serdes_init,
18800161856Syc 	nxge_tn1010_xcvr_init,
18900161856Syc 	nxge_1G_fiber_link_intr_stop,
19000161856Syc 	nxge_1G_fiber_link_intr_start,
19100161856Syc 	nxge_check_tn1010_link,
19200161856Syc 	PCS_XCVR
19300161856Syc };
19400161856Syc 
19559ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
19659ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
19759ac0c16Sdavemq 	nxge_10G_xcvr_init,
19859ac0c16Sdavemq 	nxge_10G_link_intr_stop,
19959ac0c16Sdavemq 	nxge_10G_link_intr_start,
20059ac0c16Sdavemq 	nxge_check_10g_link,
2012d17280bSsbehera 	PCS_XCVR
20259ac0c16Sdavemq };
20359ac0c16Sdavemq 
20459ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
20559ac0c16Sdavemq 	NULL,
20659ac0c16Sdavemq 	nxge_1G_xcvr_init,
20759ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
20859ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
20959ac0c16Sdavemq 	nxge_check_mii_link,
2102d17280bSsbehera 	INT_MII_XCVR
21159ac0c16Sdavemq };
21259ac0c16Sdavemq 
21300161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */
21459ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
21559ac0c16Sdavemq 	nxge_1G_serdes_init,
21659ac0c16Sdavemq 	nxge_1G_xcvr_init,
21759ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
21859ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
21959ac0c16Sdavemq 	nxge_check_mii_link,
2202d17280bSsbehera 	PCS_XCVR
22159ac0c16Sdavemq };
22259ac0c16Sdavemq 
22359ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
22459ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
22559ac0c16Sdavemq 	NULL,
22659ac0c16Sdavemq 	NULL,
22759ac0c16Sdavemq 	NULL,
2282e59129aSraghus 	NULL,
2292d17280bSsbehera 	PCS_XCVR
23059ac0c16Sdavemq };
23144961713Sgirish 
23200161856Syc /*
23300161856Syc  * NXGE_PORT_TN1010 is defined as,
23400161856Syc  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
23500161856Syc  *	= 0 | 5 << 16 = 0x50000
23600161856Syc  *
23700161856Syc  * So NEPTUNE_2_TN1010 =
23800161856Syc  *      (NXGE_PORT_TN1010 |
23900161856Syc  *      (NXGE_PORT_TN1010 << 4) |
24000161856Syc  *      (NXGE_PORT_NONE << 8) |
24100161856Syc  *      (NXGE_PORT_NONE << 12)),
24200161856Syc  *      = 0x50000 | (0x50000 << 4)
24300161856Syc  *	= 0x550000
24400161856Syc  *
24500161856Syc  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
24600161856Syc  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
24700161856Syc  * = 0x50000
24800161856Syc  */
24900161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
25000161856Syc {
25100161856Syc 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
25200161856Syc 
25300161856Syc 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
25400161856Syc 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
25500161856Syc 		return (B_TRUE);
25600161856Syc 	} else {
25700161856Syc 		return (B_FALSE);
25800161856Syc 	}
25900161856Syc }
26044961713Sgirish 
261d81011f0Ssbehera 
26200161856Syc /*
26300161856Syc  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
26400161856Syc  * serial EEPROM or VPD if possible.  Note that not all systems could get
26500161856Syc  * the portmode information by calling this function.  For example, the
26600161856Syc  * Maramba system figures out the portmode information by calling function
26700161856Syc  * nxge_setup_xcvr_table.
26800161856Syc  */
2692e59129aSraghus nxge_status_t
2702e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
2712e59129aSraghus {
2722e59129aSraghus 	nxge_status_t status = NXGE_OK;
2732e59129aSraghus 	char *phy_type;
2742e59129aSraghus 	char *prop_val;
27500161856Syc 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2761c7408c9Stc 	uint32_t	val;
2771c7408c9Stc 	npi_status_t	rs;
2781c7408c9Stc 
2791c7408c9Stc 	/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
2801c7408c9Stc 	if (nxgep->mac.portmode == PORT_10G_SERDES &&
2811c7408c9Stc 	    nxgep->statsp->mac_stats.link_up) {
2821c7408c9Stc 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2831c7408c9Stc 		return (status);
2841c7408c9Stc 	}
2852e59129aSraghus 
2862e59129aSraghus 	nxgep->mac.portmode = 0;
2872d17280bSsbehera 	nxgep->xcvr_addr = 0;
2882e59129aSraghus 
2892d17280bSsbehera 	/*
2902d17280bSsbehera 	 * First check for hot swappable phy property.
2912d17280bSsbehera 	 */
2922d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
2932d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2942d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2952d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
2962d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
2972d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2982d17280bSsbehera 	    "hot-swappable-phy") == 1) {
2992d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3002d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3012d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
3022d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
3032d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
3042d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3052d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3062d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3072d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3082d17280bSsbehera 	}
3092d17280bSsbehera 
3102d17280bSsbehera 	/*
3112d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3122d17280bSsbehera 	 */
3132d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3142d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
315*ef523517SMichael Speer 		if (portn > 1) {
316*ef523517SMichael Speer 			return (NXGE_ERROR);
317*ef523517SMichael Speer 		}
318*ef523517SMichael Speer 
3192d17280bSsbehera 		/*
3202d17280bSsbehera 		 * If this is the 2nd NIU port, then check 2 addresses
3212d17280bSsbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
3222d17280bSsbehera 		 * (in the eval board) or 20 (in the P0 board).
3232d17280bSsbehera 		 */
3242d17280bSsbehera 		if (portn == 1) {
3252d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
32600161856Syc 			    ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID,
3272d17280bSsbehera 			    BCM_PHY_ID_MASK)) {
3282d17280bSsbehera 				nxgep->xcvr_addr =
32900161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR;
3302d17280bSsbehera 				goto found_phy;
3312d17280bSsbehera 			}
3322d17280bSsbehera 		}
3332d17280bSsbehera 		if (nxge_is_phy_present(nxgep,
33400161856Syc 		    GOA_CLAUSE45_PORT_ADDR_BASE + portn,
3352d17280bSsbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
33600161856Syc 			nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE +
3372d17280bSsbehera 			    portn;
3382d17280bSsbehera 			goto found_phy;
3392d17280bSsbehera 		}
3402d17280bSsbehera 
3412d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
3421c7408c9Stc 
3431c7408c9Stc 		/* Check Serdes link to detect Opus NEM */
3441c7408c9Stc 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3451c7408c9Stc 		    XPCS_REG_STATUS, &val);
3461c7408c9Stc 
3471c7408c9Stc 		if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
3481c7408c9Stc 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3491c7408c9Stc 			nxgep->mac.portmode = PORT_10G_SERDES;
3501c7408c9Stc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3511c7408c9Stc 			    "HSP 10G Serdes FOUND!!"));
3521c7408c9Stc 		}
3532d17280bSsbehera 		goto check_phy_done;
3542d17280bSsbehera found_phy:
3552d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3562d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3572d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
3582d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3592d17280bSsbehera 		    "found for hot swappable phy"));
3602d17280bSsbehera check_phy_done:
3612d17280bSsbehera 		return (status);
3622d17280bSsbehera 	}
3632d17280bSsbehera 
36400161856Syc 	/* Get phy-type property (May have been set by nxge.conf) */
3652e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3662e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3672e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3682e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3692e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
3702e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
3712e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3722e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3732e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3742e59129aSraghus 			    "found: 10G Serdes"));
3752e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3762e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3772e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3782e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3792e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
3802e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3812e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3822e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3832e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3842e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3852e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3862e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
387321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
38800161856Syc 			/*
38900161856Syc 			 * Before OBP supports new phy-type property
39000161856Syc 			 * value "xgc", the 10G copper XAUI may carry
39100161856Syc 			 * "xgf" instead of "xgc". If the OBP is
39200161856Syc 			 * upgraded to a newer version which supports
39300161856Syc 			 * "xgc", then the TN1010 related code in this
39400161856Syc 			 * "xgf" case will not be used anymore.
39500161856Syc 			 */
39600161856Syc 			if (nxge_is_tn1010_phy(nxgep)) {
39700161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
39800161856Syc 				    != NXGE_OK) {
39900161856Syc 					return (status);
40000161856Syc 				}
40100161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
40200161856Syc 			} else {  /* For Fiber XAUI */
40300161856Syc 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
40400161856Syc 				nxgep->mac.portmode = PORT_10G_FIBER;
40500161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
40600161856Syc 				    "10G Fiber Xcvr"));
40700161856Syc 			}
40800161856Syc 		} else if (strcmp("xgc", prop_val) == 0) {
40900161856Syc 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
41000161856Syc 				return (status);
41100161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4122e59129aSraghus 		}
4132e59129aSraghus 
4142e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
4152e59129aSraghus 		    "phy-type", prop_val);
4162e59129aSraghus 		ddi_prop_free(prop_val);
4172e59129aSraghus 
4182e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4192e59129aSraghus 		    "Got phy type [0x%x] from conf file",
4202e59129aSraghus 		    nxgep->mac.portmode));
4212e59129aSraghus 
4222e59129aSraghus 		return (NXGE_OK);
4232e59129aSraghus 	}
4242d17280bSsbehera 
4252d17280bSsbehera 	/* Get phy-type property from OBP */
4262e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
4272e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4282e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4292e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
43000161856Syc 				/*
43100161856Syc 				 * Before OBP supports new phy-type property
43200161856Syc 				 * value "xgc", the 10G copper XAUI may carry
43300161856Syc 				 * "xgf" instead of "xgc". If the OBP is
43400161856Syc 				 * upgraded to a newer version which supports
43500161856Syc 				 * "xgc", then the TN1010 related code in this
43600161856Syc 				 * "xgf" case will not be used anymore.
43700161856Syc 				 */
43800161856Syc 				if (nxge_is_tn1010_phy(nxgep)) {
43900161856Syc 					if ((status =
44000161856Syc 					    nxge_set_tn1010_param(nxgep))
44100161856Syc 					    != NXGE_OK) {
44200161856Syc 						return (status);
44300161856Syc 					}
44400161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44500161856Syc 					    "TN1010 Xcvr"));
44600161856Syc 				} else {  /* For Fiber XAUI */
44700161856Syc 					nxgep->statsp->mac_stats.xcvr_inuse
44800161856Syc 					    = XPCS_XCVR;
44900161856Syc 					nxgep->mac.portmode = PORT_10G_FIBER;
45000161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
45100161856Syc 					    "10G Fiber Xcvr"));
45200161856Syc 				}
4532e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
4542e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4552e59129aSraghus 				    INT_MII_XCVR;
4562e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4572e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4582e59129aSraghus 				    "1G Copper Xcvr"));
4592e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4602e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4612e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4622e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4632e59129aSraghus 				    "1G Fiber Xcvr"));
4642e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
46500161856Syc 				status = nxge_set_tn1010_param(nxgep);
46600161856Syc 				if (status != NXGE_OK)
46700161856Syc 					return (status);
46800161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4692e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4702e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4712e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4722e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4732e59129aSraghus 				    "OBP: 10G Serdes"));
4742e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4752e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4762e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4772e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4782e59129aSraghus 				    "OBP: 1G Serdes"));
4792e59129aSraghus 			} else {
4802e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4812e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
4822e59129aSraghus 				ddi_prop_free(prop_val);
4832e59129aSraghus 				return (NXGE_ERROR);
4842e59129aSraghus 			}
4852e59129aSraghus 			status = NXGE_OK;
4862e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4872e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
4882e59129aSraghus 			ddi_prop_free(prop_val);
4892e59129aSraghus 
4902e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4912e59129aSraghus 			    "Got phy type [0x%x] from OBP",
4922e59129aSraghus 			    nxgep->mac.portmode));
4932e59129aSraghus 
4942e59129aSraghus 			return (status);
4952e59129aSraghus 		} else {
4962e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4972e59129aSraghus 			    "Exiting...phy-type property not found"));
4982e59129aSraghus 			return (NXGE_ERROR);
4992e59129aSraghus 		}
5002e59129aSraghus 	}
5012e59129aSraghus 
5022e59129aSraghus 
5032e59129aSraghus 	if (!nxgep->vpd_info.present) {
5042e59129aSraghus 		return (NXGE_OK);
5052e59129aSraghus 	}
5062e59129aSraghus 
5072e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
5082e59129aSraghus 		goto read_seeprom;
5092e59129aSraghus 	}
5102e59129aSraghus 
5112e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5122e59129aSraghus 	    "Reading phy type from expansion ROM"));
5132e59129aSraghus 	/*
5142e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
5152e59129aSraghus 	 * expansion ROM.
5162e59129aSraghus 	 */
5172e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
5182e59129aSraghus 
519d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
5202e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
5212e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
522d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5232e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5242e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
525d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5262e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5272e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
528d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
52900161856Syc 		status = nxge_set_tn1010_param(nxgep);
53000161856Syc 		if (status != NXGE_OK) {
53100161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
53200161856Syc 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
53300161856Syc 			goto read_seeprom;
53400161856Syc 		}
535d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
536d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
537d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
538d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
539d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
540d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5412e59129aSraghus 	} else {
542d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5432e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5442e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5452e59129aSraghus 		goto read_seeprom;
5462e59129aSraghus 	}
5472e59129aSraghus 
5482e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5492e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5502e59129aSraghus 
5512e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5522e59129aSraghus 	return (status);
5532e59129aSraghus 
5542e59129aSraghus read_seeprom:
5552e59129aSraghus 	/*
5562e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
5572e59129aSraghus 	 */
5582e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
5592e59129aSraghus 	if (status != NXGE_OK) {
5602e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5612e59129aSraghus 		    "Failed to get phy type"));
5622e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5632e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5642e59129aSraghus 	}
5652e59129aSraghus 
5662e59129aSraghus 	return (status);
5672e59129aSraghus 
5682e59129aSraghus }
5692e59129aSraghus 
57059ac0c16Sdavemq /* Set up the PHY specific values. */
57159ac0c16Sdavemq 
57259ac0c16Sdavemq nxge_status_t
57359ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
57459ac0c16Sdavemq {
57559ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
57659ac0c16Sdavemq 	uint32_t	port_type;
57759ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5782e59129aSraghus 	uint32_t	pcs_id = 0;
5792e59129aSraghus 	uint32_t	pma_pmd_id = 0;
5802e59129aSraghus 	uint32_t	phy_id = 0;
5812d17280bSsbehera 	uint16_t	chip_id = 0;
58259ac0c16Sdavemq 
58359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
58459ac0c16Sdavemq 	    portn));
58559ac0c16Sdavemq 
5862e59129aSraghus 	switch (nxgep->niu_type) {
5872e59129aSraghus 	case N2_NIU:
5882e59129aSraghus 		switch (nxgep->mac.portmode) {
5892e59129aSraghus 		case PORT_1G_FIBER:
5902e59129aSraghus 		case PORT_1G_SERDES:
5912e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
5922d17280bSsbehera 			nxgep->xcvr_addr = portn;
5932e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5942e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5952e59129aSraghus 			    "Serdes"));
5962e59129aSraghus 			break;
5972e59129aSraghus 		case PORT_10G_FIBER:
5982e59129aSraghus 		case PORT_10G_SERDES:
5992e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
6002d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
6012d17280bSsbehera 				nxgep->xcvr_addr =
6022d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
6032d17280bSsbehera 			}
6042e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
6052e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
6062e59129aSraghus 			    "Serdes"));
6072e59129aSraghus 			break;
60800161856Syc 		case PORT_1G_TN1010:
60900161856Syc 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
61000161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61100161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61200161856Syc 			    "TN1010 Copper Xcvr in 1G"));
61300161856Syc 			break;
61400161856Syc 		case PORT_10G_TN1010:
61500161856Syc 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
61600161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61700161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61800161856Syc 			    "TN1010 Copper Xcvr in 10G"));
61900161856Syc 			break;
6202d17280bSsbehera 		case PORT_HSP_MODE:
6212d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
6222d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6232d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6242d17280bSsbehera 			    "Swappable Xcvr (not present)"));
6252d17280bSsbehera 			break;
6262e59129aSraghus 		default:
6272e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6282e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
6292e59129aSraghus 			    "Unable to determine NIU portmode"));
6302e59129aSraghus 			return (NXGE_ERROR);
6312e59129aSraghus 		}
6322e59129aSraghus 		break;
6332e59129aSraghus 	default:
6342e59129aSraghus 		if (nxgep->mac.portmode == 0) {
6352e59129aSraghus 			/*
6362e59129aSraghus 			 * Would be the case for platforms like Maramba
6372e59129aSraghus 			 * in which the phy type could not be got from conf
6382e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
6392e59129aSraghus 			 */
6402e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6412e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6422e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
6432e59129aSraghus 				    " Invalid Neptune type [0x%x]",
6442e59129aSraghus 				    nxgep->niu_type));
6452e59129aSraghus 				return (NXGE_ERROR);
6462e59129aSraghus 			}
6472e59129aSraghus 
6482e59129aSraghus 			port_type = nxgep->niu_type >>
6492e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
6502e59129aSraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6512e59129aSraghus 
6522e59129aSraghus 			switch (port_type) {
6532e59129aSraghus 
6542e59129aSraghus 			case NXGE_PORT_1G_COPPER:
6552e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
6562e59129aSraghus 				break;
6572e59129aSraghus 			case NXGE_PORT_10G_COPPER:
6582e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6592e59129aSraghus 				break;
6602e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
6612e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6622e59129aSraghus 				break;
6632e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
6642e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6652e59129aSraghus 				break;
6662e59129aSraghus 			case NXGE_PORT_1G_SERDES:
6672e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6682e59129aSraghus 				break;
6692e59129aSraghus 			case NXGE_PORT_10G_SERDES:
6702e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6712e59129aSraghus 				break;
67200161856Syc 			/* Ports 2 and 3 of Alonso or ARTM */
6732e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6742e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6752e59129aSraghus 				break;
67600161856Syc 			case NXGE_PORT_TN1010:
67700161856Syc 				/*
67800161856Syc 				 * If this port uses the TN1010 copper
67900161856Syc 				 * PHY, then its speed is not known yet
68000161856Syc 				 * because nxge_scan_ports_phy could only
68100161856Syc 				 * figure out the vendor of the PHY but
68200161856Syc 				 * not its speed. nxge_set_tn1010_param
68300161856Syc 				 * will read the PHY speed and set
68400161856Syc 				 * portmode accordingly.
68500161856Syc 				 */
68600161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
68700161856Syc 				    != NXGE_OK) {
68800161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68900161856Syc 					    "nxge_set_tn1010_param failed"));
69000161856Syc 					return (status);
69100161856Syc 				}
69200161856Syc 				break;
6932e59129aSraghus 			default:
6942e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6952e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
6962e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
6972e59129aSraghus 				return (NXGE_ERROR);
6982e59129aSraghus 			}
6992e59129aSraghus 		}
7002e59129aSraghus 
70100161856Syc 		/*
70200161856Syc 		 * Above switch has figured out nxge->mac.portmode, now set
70300161856Syc 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
70400161856Syc 		 * to portmode.
70500161856Syc 		 */
7062e59129aSraghus 		switch (nxgep->mac.portmode) {
7072e59129aSraghus 		case PORT_1G_COPPER:
7082e59129aSraghus 		case PORT_1G_RGMII_FIBER:
70959ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
7102d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
71159ac0c16Sdavemq 			/*
71259ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
71359ac0c16Sdavemq 			 * swapped with ethernet port number. This is
7142e59129aSraghus 			 * designed for better signal integrity in
7152e59129aSraghus 			 * routing. This is also the case for the
7162e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
7172e59129aSraghus 			 * platform.
71859ac0c16Sdavemq 			 */
7192e59129aSraghus 			switch (nxgep->platform_type) {
7202e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
7212e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7222e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
7232e59129aSraghus 				switch (portn) {
7242e59129aSraghus 				case 0:
7252d17280bSsbehera 					nxgep->xcvr_addr += 3;
7262e59129aSraghus 					break;
7272e59129aSraghus 				case 1:
7282d17280bSsbehera 					nxgep->xcvr_addr += 1;
7292e59129aSraghus 					break;
7302e59129aSraghus 				case 2:
7312d17280bSsbehera 					nxgep->xcvr_addr -= 1;
7322e59129aSraghus 					break;
7332e59129aSraghus 				case 3:
7342d17280bSsbehera 					nxgep->xcvr_addr -= 3;
7352e59129aSraghus 					break;
7362e59129aSraghus 				default:
7372e59129aSraghus 					return (NXGE_ERROR);
7382e59129aSraghus 				}
73959ac0c16Sdavemq 				break;
74059ac0c16Sdavemq 			default:
7412e59129aSraghus 				break;
74259ac0c16Sdavemq 			}
743d81011f0Ssbehera 
7442e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7452e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7462e59129aSraghus 			    "Copper" : "RGMII Fiber"));
74759ac0c16Sdavemq 			break;
74800161856Syc 
7492e59129aSraghus 		case PORT_10G_COPPER:
75059ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
75159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
75259ac0c16Sdavemq 			break;
75300161856Syc 
75400161856Syc 		case PORT_1G_TN1010:
75500161856Syc 			nxgep->xcvr = nxge_1G_tn1010_table;
75600161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
75700161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75800161856Syc 			    "1G TN1010 copper Xcvr"));
75900161856Syc 			break;
76000161856Syc 
76100161856Syc 		case PORT_10G_TN1010:
76200161856Syc 			nxgep->xcvr = nxge_10G_tn1010_table;
76300161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
76400161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
76500161856Syc 			    "10G TN1010 copper Xcvr"));
76600161856Syc 			break;
76700161856Syc 
7682e59129aSraghus 		case PORT_1G_FIBER:
7692e59129aSraghus 		case PORT_1G_SERDES:
77059ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7712d17280bSsbehera 			nxgep->xcvr_addr = portn;
7722e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7732e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7742e59129aSraghus 			    "Fiber" : "Serdes"));
77559ac0c16Sdavemq 			break;
7762e59129aSraghus 		case PORT_10G_FIBER:
7772e59129aSraghus 		case PORT_10G_SERDES:
77859ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7792d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7802d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7812d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
7822d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7832d17280bSsbehera 			    nxgep->xcvr_addr));
7842d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7852d17280bSsbehera 				nxgep->xcvr_addr =
7862d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7872d17280bSsbehera 			}
7882e59129aSraghus 			switch (nxgep->platform_type) {
7892e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7902e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
79159ac0c16Sdavemq 				/*
79259ac0c16Sdavemq 				 * Switch off LED for corresponding copper
79359ac0c16Sdavemq 				 * port
79459ac0c16Sdavemq 				 */
79559ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7962e59129aSraghus 				break;
7972e59129aSraghus 			default:
7982e59129aSraghus 				break;
79959ac0c16Sdavemq 			}
8002e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
8012e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
8022e59129aSraghus 			    "Fiber" : "Serdes"));
80359ac0c16Sdavemq 			break;
8042d17280bSsbehera 
8052d17280bSsbehera 		case PORT_HSP_MODE:
8062d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
8072d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
8082d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
8092d17280bSsbehera 			    "Swappable Xcvr (not present)"));
8102d17280bSsbehera 			break;
81159ac0c16Sdavemq 		default:
81259ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
81359ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
81459ac0c16Sdavemq 			return (NXGE_ERROR);
81559ac0c16Sdavemq 		}
81659ac0c16Sdavemq 	}
81759ac0c16Sdavemq 
8182d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
81952cdd236Ssbehera 		uint32_t pma_pmd_id;
82052cdd236Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
82152cdd236Ssbehera 		    nxgep->xcvr_addr);
82252cdd236Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
82352cdd236Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
82452cdd236Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
82552cdd236Ssbehera 			    "nxge_setup_xcvr_table: "
82652cdd236Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
82752cdd236Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8282d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8292d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
8302d17280bSsbehera 
8312d17280bSsbehera 			switch (chip_id) {
8322d17280bSsbehera 			case BCM8704_CHIP_ID:
8332d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8342d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8352d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8362d17280bSsbehera 				    chip_id));
8372d17280bSsbehera 				break;
8382d17280bSsbehera 			case BCM8706_CHIP_ID:
8392d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8402d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8412d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8422d17280bSsbehera 				    chip_id));
8432d17280bSsbehera 				break;
8442d17280bSsbehera 			default:
8452d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8462d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8472d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8482d17280bSsbehera 				    chip_id));
8492d17280bSsbehera 				break;
8502d17280bSsbehera 			}
8512d17280bSsbehera 		}
8522d17280bSsbehera 	}
8532d17280bSsbehera 
85459ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8552d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8562d17280bSsbehera 	nxgep->chip_id = chip_id;
8572e59129aSraghus 
8582e59129aSraghus 	/*
8592e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
8602e59129aSraghus 	 */
8612e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8622e59129aSraghus 
8632d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8642e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8652e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8662e59129aSraghus 	} else {
8672d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8682e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8692e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8702e59129aSraghus 		} else {
8712e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8722d17280bSsbehera 			    nxgep->xcvr_addr);
8732e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8742e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8752e59129aSraghus 			}
8762e59129aSraghus 		}
8772e59129aSraghus 	}
8782e59129aSraghus 
87959ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
88059ac0c16Sdavemq 
8812e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
88223b952a3SSantwona Behera 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
8832d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8842e59129aSraghus 
88559ac0c16Sdavemq 	return (status);
88659ac0c16Sdavemq }
88759ac0c16Sdavemq 
88844961713Sgirish /* Initialize the entire MAC and physical layer */
88944961713Sgirish 
89044961713Sgirish nxge_status_t
89144961713Sgirish nxge_mac_init(p_nxge_t nxgep)
89244961713Sgirish {
89344961713Sgirish 	uint8_t			portn;
89444961713Sgirish 	nxge_status_t		status = NXGE_OK;
89544961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
89644961713Sgirish 
89744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
89844961713Sgirish 
89944961713Sgirish 	nxgep->mac.portnum = portn;
90044961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
90144961713Sgirish 
90244961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
90344961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
90444961713Sgirish 
90500161856Syc 
90644961713Sgirish 	/* Initialize XIF to configure a network mode */
90744961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
90844961713Sgirish 		goto fail;
90944961713Sgirish 	}
91044961713Sgirish 
91144961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
91244961713Sgirish 		goto fail;
91344961713Sgirish 	}
91444961713Sgirish 
91544961713Sgirish 	/* Initialize TX and RX MACs */
91644961713Sgirish 	/*
91744961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
91844961713Sgirish 	 */
91944961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
92044961713Sgirish 		goto fail;
92144961713Sgirish 
92244961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
92344961713Sgirish 		goto fail;
92444961713Sgirish 
92544961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
92644961713Sgirish 		goto fail;
92744961713Sgirish 
92844961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
92944961713Sgirish 		goto fail;
93044961713Sgirish 
93144961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
93244961713Sgirish 		goto fail;
93344961713Sgirish 
934e759c33aSMichael Speer 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
935e759c33aSMichael Speer 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
936e759c33aSMichael Speer 			goto fail;
937e759c33aSMichael Speer 	}
93844961713Sgirish 
939cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
940cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
941cb9d3ae6Smisaki 		goto fail;
942cb9d3ae6Smisaki 	}
943cb9d3ae6Smisaki 
94444961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
94544961713Sgirish 
946d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
947d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
948d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
94900161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
950d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
951d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
952d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
953d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
954d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
955d81011f0Ssbehera 			goto fail;
956d81011f0Ssbehera 		}
957d81011f0Ssbehera 	}
958d81011f0Ssbehera 
9592e59129aSraghus 
96044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
96144961713Sgirish 
96244961713Sgirish 	return (NXGE_OK);
96344961713Sgirish fail:
96444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
96552ccf843Smisaki 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
96644961713Sgirish 	return (status);
96744961713Sgirish }
96844961713Sgirish 
96944961713Sgirish /* Initialize the Ethernet Link */
97044961713Sgirish 
97144961713Sgirish nxge_status_t
97244961713Sgirish nxge_link_init(p_nxge_t nxgep)
97344961713Sgirish {
97444961713Sgirish 	nxge_status_t		status = NXGE_OK;
9752e59129aSraghus 	nxge_port_mode_t	portmode;
97644961713Sgirish #ifdef	NXGE_DEBUG
97744961713Sgirish 	uint8_t			portn;
97844961713Sgirish 
97944961713Sgirish 	portn = nxgep->mac.portnum;
98044961713Sgirish 
98144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
98244961713Sgirish #endif
9831c7408c9Stc 	/* For Opus NEM, Serdes always needs to be initialized */
98444961713Sgirish 
9852e59129aSraghus 	portmode = nxgep->mac.portmode;
9862d17280bSsbehera 
98700161856Syc 	/*
98800161856Syc 	 * Workaround to get link up in both NIU ports. Some portmodes require
98900161856Syc 	 * that the xcvr be initialized twice, the first time before calling
99000161856Syc 	 * nxge_serdes_init.
99100161856Syc 	 */
9922e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
99300161856Syc 	    (portmode != PORT_10G_TN1010) &&
99400161856Syc 	    (portmode != PORT_1G_TN1010) &&
9952e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
9962e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
99744961713Sgirish 			goto fail;
9982e59129aSraghus 		}
99944961713Sgirish 	}
100000161856Syc 
100144961713Sgirish 	NXGE_DELAY(200000);
100244961713Sgirish 	/* Initialize internal serdes */
100344961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
100444961713Sgirish 		goto fail;
100544961713Sgirish 	NXGE_DELAY(200000);
100644961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
100744961713Sgirish 		goto fail;
100844961713Sgirish 
100944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
101044961713Sgirish 
101144961713Sgirish 	return (NXGE_OK);
101244961713Sgirish 
101344961713Sgirish fail:
101452ccf843Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
101552ccf843Smisaki 	    "failed to initialize Ethernet link on port<%d>", portn));
101644961713Sgirish 
101744961713Sgirish 	return (status);
101844961713Sgirish }
101944961713Sgirish 
102044961713Sgirish 
102144961713Sgirish /* Initialize the XIF sub-block within the MAC */
102244961713Sgirish 
102344961713Sgirish nxge_status_t
102444961713Sgirish nxge_xif_init(p_nxge_t nxgep)
102544961713Sgirish {
102644961713Sgirish 	uint32_t		xif_cfg = 0;
102744961713Sgirish 	npi_attr_t		ap;
102844961713Sgirish 	uint8_t			portn;
102944961713Sgirish 	nxge_port_t		portt;
103044961713Sgirish 	nxge_port_mode_t	portmode;
103144961713Sgirish 	p_nxge_stats_t		statsp;
103244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
103344961713Sgirish 	npi_handle_t		handle;
103444961713Sgirish 
103544961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
103644961713Sgirish 
103744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
103844961713Sgirish 
103944961713Sgirish 	handle = nxgep->npi_handle;
104044961713Sgirish 	portmode = nxgep->mac.portmode;
104144961713Sgirish 	portt = nxgep->mac.porttype;
104244961713Sgirish 	statsp = nxgep->statsp;
104344961713Sgirish 
1044d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1045d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
104600161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
1047d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1048d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
1049d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1050d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
1051d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1052d81011f0Ssbehera 	}
1053d81011f0Ssbehera 
105444961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
105544961713Sgirish 
105644961713Sgirish 		/* Setup XIF Configuration for XMAC */
105744961713Sgirish 
105844961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
10592e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
106000161856Syc 		    (portmode == PORT_10G_TN1010) ||
10611c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
10622e59129aSraghus 		    (portmode == PORT_10G_SERDES))
106344961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
106444961713Sgirish 
106500161856Syc 		/* Bypass PCS so that RGMII will be used */
106644961713Sgirish 		if (portmode == PORT_1G_COPPER) {
106744961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
106844961713Sgirish 		}
106944961713Sgirish 
107044961713Sgirish 		/* Set MAC Internal Loopback if necessary */
107144961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
107244961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
107344961713Sgirish 
107444961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
107544961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
107644961713Sgirish 
107744961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
107844961713Sgirish 
10792e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
108000161856Syc 		    (portmode == PORT_10G_TN1010) ||
108100161856Syc 		    (portmode == PORT_1G_TN1010) ||
10821c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
10832e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
108400161856Syc 			/* Assume LED same for 1G and 10G */
108544961713Sgirish 			if (statsp->mac_stats.link_up) {
108644961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
108744961713Sgirish 			} else {
108844961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
108944961713Sgirish 			}
109044961713Sgirish 		}
109144961713Sgirish 
109244961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
109344961713Sgirish 		if (rs != NPI_SUCCESS)
109444961713Sgirish 			goto fail;
109544961713Sgirish 
109644961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
109744961713Sgirish 
109844961713Sgirish 		/* Set Port Mode */
109944961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
11002e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
110100161856Syc 		    (portmode == PORT_10G_TN1010) ||
11021c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
11032e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
110444961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
110552ccf843Smisaki 			    MAC_XGMII_MODE, rs);
110644961713Sgirish 			if (rs != NPI_SUCCESS)
110744961713Sgirish 				goto fail;
110844961713Sgirish 			if (statsp->mac_stats.link_up) {
110944961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
111044961713Sgirish 					goto fail;
111144961713Sgirish 			} else {
111244961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
111344961713Sgirish 					goto fail;
111444961713Sgirish 			}
111544961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
11162e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
1117d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
111800161856Syc 		    (portmode == PORT_1G_TN1010) ||
1119d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
1120d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1121d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1122d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
112344961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
112444961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
112552ccf843Smisaki 				    MAC_GMII_MODE, rs);
112644961713Sgirish 			} else {
112744961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
112852ccf843Smisaki 				    MAC_MII_MODE, rs);
112944961713Sgirish 			}
113044961713Sgirish 			if (rs != NPI_SUCCESS)
113144961713Sgirish 				goto fail;
113244961713Sgirish 		} else {
113344961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
113452ccf843Smisaki 			    "nxge_xif_init: Unknown port mode (%d)"
113552ccf843Smisaki 			    " for port<%d>", portmode, portn));
113644961713Sgirish 			goto fail;
113744961713Sgirish 		}
113844961713Sgirish 
1139d81011f0Ssbehera 		/* Enable ATCA mode */
1140d81011f0Ssbehera 
114144961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
114244961713Sgirish 
114344961713Sgirish 		/* Setup XIF Configuration for BMAC */
114444961713Sgirish 
1145d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
1146d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
114744961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
114844961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
114944961713Sgirish 		}
115044961713Sgirish 
115144961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
115244961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
115344961713Sgirish 
115444961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
115544961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
115644961713Sgirish 
115744961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
115844961713Sgirish 
115944961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
116044961713Sgirish 		if (rs != NPI_SUCCESS)
116144961713Sgirish 			goto fail;
116244961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
116344961713Sgirish 	}
116444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
116544961713Sgirish 	return (NXGE_OK);
116644961713Sgirish fail:
116744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
116852ccf843Smisaki 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
116944961713Sgirish 	return (NXGE_ERROR | rs);
117044961713Sgirish }
117144961713Sgirish 
117244961713Sgirish 
117300161856Syc /*
117400161856Syc  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
117500161856Syc  * support loopback like XPCS.
117600161856Syc  */
117744961713Sgirish nxge_status_t
117844961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
117944961713Sgirish {
118044961713Sgirish 	pcs_cfg_t		pcs_cfg;
118144961713Sgirish 	uint32_t		val;
118244961713Sgirish 	uint8_t			portn;
118344961713Sgirish 	nxge_port_mode_t	portmode;
118444961713Sgirish 	npi_handle_t		handle;
118544961713Sgirish 	p_nxge_stats_t		statsp;
118600161856Syc 	pcs_ctrl_t		pcs_ctrl;
118744961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
118800161856Syc 	uint8_t i;
118944961713Sgirish 
119044961713Sgirish 	handle = nxgep->npi_handle;
119144961713Sgirish 	portmode = nxgep->mac.portmode;
119244961713Sgirish 	portn = nxgep->mac.portnum;
119344961713Sgirish 	statsp = nxgep->statsp;
119444961713Sgirish 
119544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
119644961713Sgirish 
119700161856Syc 	if (portmode == PORT_1G_FIBER ||
119800161856Syc 	    portmode == PORT_1G_TN1010 ||
119900161856Syc 	    portmode == PORT_1G_SERDES) {
120000161856Syc 		if (portmode == PORT_1G_TN1010) {
120100161856Syc 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
120200161856Syc 			for (i = 0; i < 6; i ++) {
120300161856Syc 				if ((rs = npi_mac_pcs_reset(handle, portn))
120400161856Syc 				    != NPI_SUCCESS) {
120500161856Syc 					goto fail;
120600161856Syc 				}
120700161856Syc 			}
120800161856Syc 		} else {
120900161856Syc 			if ((rs = npi_mac_pcs_reset(handle, portn))
121000161856Syc 			    != NPI_SUCCESS)
121100161856Syc 				goto fail;
12122e59129aSraghus 		}
12132e59129aSraghus 
121444961713Sgirish 		/* Initialize port's PCS */
121544961713Sgirish 		pcs_cfg.value = 0;
121644961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
121744961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
121844961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
121944961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
122044961713Sgirish 
12212e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12222e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12232e59129aSraghus 		    portn, pcs_cfg.value));
122400161856Syc 
122500161856Syc 		if (portmode == PORT_1G_TN1010) {
122600161856Syc 			/*
122700161856Syc 			 * Must disable PCS auto-negotiation when the the driver
122800161856Syc 			 * is driving the TN1010 based XAUI card  Otherwise the
122900161856Syc 			 * autonegotiation between the PCS and the TN1010 PCS
123000161856Syc 			 * will never complete and the Neptune/NIU will not work
123100161856Syc 			 */
123200161856Syc 			pcs_ctrl.value = 0;
123300161856Syc 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
123400161856Syc 			    pcs_ctrl.value);
123500161856Syc 		}
123600161856Syc 	} else if (portmode == PORT_10G_FIBER ||
123700161856Syc 	    portmode == PORT_10G_COPPER ||
123800161856Syc 	    portmode == PORT_10G_TN1010 ||
12391c7408c9Stc 	    portmode == PORT_HSP_MODE ||
124000161856Syc 	    portmode == PORT_10G_SERDES) {
124144961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
124244961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
124344961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
124444961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
124544961713Sgirish 
124644961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
124744961713Sgirish 			goto fail;
124844961713Sgirish 
124944961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
125044961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
125152ccf843Smisaki 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
125244961713Sgirish 			goto fail;
125300161856Syc 
125444961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
125552ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
125644961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
125744961713Sgirish 		else
125844961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
125944961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
126052ccf843Smisaki 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
126144961713Sgirish 			goto fail;
126244961713Sgirish 
126344961713Sgirish 		/* Clear descw errors */
126444961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
126552ccf843Smisaki 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
126644961713Sgirish 			goto fail;
126744961713Sgirish 		/* Clear symbol errors */
126844961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
126952ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
127044961713Sgirish 			goto fail;
127144961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
127252ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
127344961713Sgirish 			goto fail;
127444961713Sgirish 
1275d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1276d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1277d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1278d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
127944961713Sgirish 		if (portn < 4) {
128044961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
128152ccf843Smisaki 			    PCS_DATAPATH_MODE_MII);
128244961713Sgirish 		}
128344961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
128444961713Sgirish 			goto fail;
128544961713Sgirish 
128644961713Sgirish 	} else {
128744961713Sgirish 		goto fail;
128844961713Sgirish 	}
128944961713Sgirish pass:
129044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
129144961713Sgirish 	return (NXGE_OK);
129244961713Sgirish fail:
129344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
129452ccf843Smisaki 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
129544961713Sgirish 	return (NXGE_ERROR | rs);
129644961713Sgirish }
129744961713Sgirish 
1298cb9d3ae6Smisaki /*
1299cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1300cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1301cb9d3ae6Smisaki  */
1302cb9d3ae6Smisaki nxge_status_t
1303cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1304cb9d3ae6Smisaki {
1305cb9d3ae6Smisaki 	uint8_t			portn;
1306cb9d3ae6Smisaki 	nxge_port_t		portt;
1307cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1308cb9d3ae6Smisaki 	npi_handle_t		handle;
1309cb9d3ae6Smisaki 	uint32_t		val;
1310cb9d3ae6Smisaki 
1311cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1312cb9d3ae6Smisaki 
1313cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1314cb9d3ae6Smisaki 	    portn));
1315cb9d3ae6Smisaki 
1316cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1317cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1318cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1319cb9d3ae6Smisaki 
1320cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
132100161856Syc 		/* Reading the current XMAC Config Register for XMAC */
1322cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1323cb9d3ae6Smisaki 
1324cb9d3ae6Smisaki 		/*
1325cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1326cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1327cb9d3ae6Smisaki 		 */
1328cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1329cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1330cb9d3ae6Smisaki 				/*
1331cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1332cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1333cb9d3ae6Smisaki 				 */
1334cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1335cb9d3ae6Smisaki 			} else {
1336cb9d3ae6Smisaki 				/*
1337cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1338cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1339cb9d3ae6Smisaki 				 * not supported.
1340cb9d3ae6Smisaki 				 */
1341cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1342cb9d3ae6Smisaki 			}
1343cb9d3ae6Smisaki 		} else {
13441bd6825cSml 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13451bd6825cSml 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13461bd6825cSml 			    portn));
1347cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13481bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13491bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13501bd6825cSml 				    "enable pause", portn));
1351cb9d3ae6Smisaki 				/*
1352cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1353cb9d3ae6Smisaki 				 * is 1, enable receive pause.
1354cb9d3ae6Smisaki 				 */
1355cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1356cb9d3ae6Smisaki 			} else {
1357cb9d3ae6Smisaki 				/*
1358cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1359cb9d3ae6Smisaki 				 * is 0, disable receive pause. Send pause is
1360cb9d3ae6Smisaki 				 * not supported
1361cb9d3ae6Smisaki 				 */
13621bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13631bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13641bd6825cSml 				    "disable pause", portn));
1365cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1366cb9d3ae6Smisaki 			}
1367cb9d3ae6Smisaki 		}
1368cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1369cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
137000161856Syc 		/* Reading the current MAC CTRL Config Register for BMAC */
1371cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1372cb9d3ae6Smisaki 
1373cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1374cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1375cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1376cb9d3ae6Smisaki 				/*
1377cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1378cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1379cb9d3ae6Smisaki 				 * is not supported
1380cb9d3ae6Smisaki 				 */
1381cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1382cb9d3ae6Smisaki 			} else {
1383cb9d3ae6Smisaki 				/*
1384cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1385cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1386cb9d3ae6Smisaki 				 * send pause.
1387cb9d3ae6Smisaki 				 */
1388cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1389cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1390cb9d3ae6Smisaki 			}
1391cb9d3ae6Smisaki 		} else {
1392cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1393cb9d3ae6Smisaki 				/*
1394cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1395cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1396cb9d3ae6Smisaki 				 * not supported.
1397cb9d3ae6Smisaki 				 */
1398cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1399cb9d3ae6Smisaki 			} else {
1400cb9d3ae6Smisaki 				/*
1401cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1402cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1403cb9d3ae6Smisaki 				 * either direction.
1404cb9d3ae6Smisaki 				 */
1405cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
140652ccf843Smisaki 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
1407cb9d3ae6Smisaki 			}
1408cb9d3ae6Smisaki 		}
1409cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1410cb9d3ae6Smisaki 	}
1411cb9d3ae6Smisaki 
1412cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1413cb9d3ae6Smisaki 	    portn));
1414cb9d3ae6Smisaki 
1415cb9d3ae6Smisaki 	return (NXGE_OK);
1416cb9d3ae6Smisaki }
1417cb9d3ae6Smisaki 
141844961713Sgirish /* Initialize the Internal Serdes */
141944961713Sgirish 
142044961713Sgirish nxge_status_t
142144961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
142244961713Sgirish {
142344961713Sgirish 	p_nxge_stats_t		statsp;
142444961713Sgirish #ifdef	NXGE_DEBUG
142544961713Sgirish 	uint8_t			portn;
142644961713Sgirish #endif
142744961713Sgirish 	nxge_status_t		status = NXGE_OK;
142844961713Sgirish 
142944961713Sgirish #ifdef	NXGE_DEBUG
143044961713Sgirish 	portn = nxgep->mac.portnum;
143144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
143259ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
143344961713Sgirish #endif
143444961713Sgirish 
143559ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
143659ac0c16Sdavemq 		statsp = nxgep->statsp;
143759ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
143859ac0c16Sdavemq 		if (status != NXGE_OK)
143944961713Sgirish 			goto fail;
144059ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
144144961713Sgirish 	}
144244961713Sgirish 
144344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
144459ac0c16Sdavemq 	    portn));
144544961713Sgirish 
144644961713Sgirish 	return (NXGE_OK);
144744961713Sgirish 
144844961713Sgirish fail:
144944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
145059ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
145159ac0c16Sdavemq 	    portn));
145244961713Sgirish 
145344961713Sgirish 	return (status);
145444961713Sgirish }
145544961713Sgirish 
145644961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
145744961713Sgirish 
145859ac0c16Sdavemq static nxge_status_t
145944961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
146044961713Sgirish {
146144961713Sgirish 	uint8_t portn;
146244961713Sgirish 	int chan;
146344961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
14642e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
146544961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
146644961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
146744961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
146844961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
14692e59129aSraghus #ifdef NXGE_DEBUG
14702e59129aSraghus 	esr_ti_testcfg_t cfg;
14712e59129aSraghus #endif
147244961713Sgirish 	esr_ti_testcfg_t test_cfg;
147344961713Sgirish 	nxge_status_t status = NXGE_OK;
147444961713Sgirish 
147544961713Sgirish 	portn = nxgep->mac.portnum;
147644961713Sgirish 
147744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
147852ccf843Smisaki 	    portn));
147944961713Sgirish 
148044961713Sgirish 	tx_cfg_l.value = 0;
148144961713Sgirish 	tx_cfg_h.value = 0;
148244961713Sgirish 	rx_cfg_l.value = 0;
148344961713Sgirish 	rx_cfg_h.value = 0;
148444961713Sgirish 	pll_cfg_l.value = 0;
14852e59129aSraghus 	pll_sts_l.value = 0;
148644961713Sgirish 	test_cfg.value = 0;
148744961713Sgirish 
148800161856Syc 	/*
148900161856Syc 	 * If the nxge driver has been plumbed without a link, then it will
149000161856Syc 	 * detect a link up when a cable connecting to an anto-negotiation
149100161856Syc 	 * partner is plugged into the port. Because the TN1010 PHY supports
149200161856Syc 	 * both 1G and 10G speeds, the driver must re-configure the
149300161856Syc 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
149400161856Syc 	 * is called at the post-link-up reconfiguration time. Here it calls
149500161856Syc 	 * nxge_set_tn1010_param to set portmode before re-initializing
149600161856Syc 	 * the serdes.
149700161856Syc 	 */
149800161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
149900161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
150000161856Syc 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
150100161856Syc 			goto fail;
150200161856Syc 		}
150300161856Syc 	}
150400161856Syc 
150500161856Syc 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
150600161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
15071c7408c9Stc 	    nxgep->mac.portmode == PORT_HSP_MODE ||
150800161856Syc 	    nxgep->mac.portmode == PORT_10G_SERDES) {
150944961713Sgirish 		/* 0x0E01 */
151044961713Sgirish 		tx_cfg_l.bits.entx = 1;
151144961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
151244961713Sgirish 
151344961713Sgirish 		/* 0x9101 */
151444961713Sgirish 		rx_cfg_l.bits.enrx = 1;
151544961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
151644961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
151744961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
151844961713Sgirish 
151944961713Sgirish 		/* 0x0008 */
152044961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
152144961713Sgirish 
152244961713Sgirish 		/* Set loopback mode if necessary */
152344961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
152444961713Sgirish 			tx_cfg_l.bits.entest = 1;
152544961713Sgirish 			rx_cfg_l.bits.entest = 1;
152644961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
152744961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
152852ccf843Smisaki 			    ESR_N2_DEV_ADDR,
152952ccf843Smisaki 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
153044961713Sgirish 			goto fail;
153144961713Sgirish 		}
153244961713Sgirish 
153300161856Syc 		/* Initialize PLL for 10G */
153400161856Syc 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
153500161856Syc 		pll_cfg_l.bits.enpll = 1;
153600161856Syc 		pll_sts_l.bits.enpll = 1;
153700161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
153800161856Syc 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
153900161856Syc 			goto fail;
154000161856Syc 
154100161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
154200161856Syc 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
154300161856Syc 			goto fail;
154444961713Sgirish 
154500161856Syc #ifdef  NXGE_DEBUG
154600161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
154700161856Syc 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
154800161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
154900161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
155000161856Syc 		    portn, pll_cfg_l.value, cfg.value));
155144961713Sgirish 
155200161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
155300161856Syc 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
155400161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
155500161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
155600161856Syc 		    portn, pll_sts_l.value, cfg.value));
155700161856Syc #endif
155800161856Syc 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
155900161856Syc 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
156000161856Syc 	    nxgep->mac.portmode == PORT_1G_SERDES) {
156144961713Sgirish 		/* 0x0E21 */
156244961713Sgirish 		tx_cfg_l.bits.entx = 1;
156344961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
156444961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
156544961713Sgirish 
156644961713Sgirish 		/* 0x9121 */
156744961713Sgirish 		rx_cfg_l.bits.enrx = 1;
156844961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
156944961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
157044961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
157144961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
157244961713Sgirish 
15732e59129aSraghus 		if (portn == 0) {
15742e59129aSraghus 			/* 0x8 */
15752e59129aSraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15762e59129aSraghus 		}
157744961713Sgirish 
157800161856Syc 		/* Initialize PLL for 1G */
157944961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
158044961713Sgirish 		pll_cfg_l.bits.enpll = 1;
15812e59129aSraghus 		pll_sts_l.bits.enpll = 1;
158244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
158352ccf843Smisaki 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
158444961713Sgirish 			goto fail;
15852e59129aSraghus 
15862e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15872e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15882e59129aSraghus 			goto fail;
15892e59129aSraghus 
15902e59129aSraghus #ifdef  NXGE_DEBUG
15912e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15922e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15932e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15942e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15952e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
15962e59129aSraghus 
15972e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15982e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15992e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16002e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
16012e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
16022e59129aSraghus #endif
16032e59129aSraghus 
16042e59129aSraghus 		/* Set loopback mode if necessary */
16052e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16062e59129aSraghus 			tx_cfg_l.bits.entest = 1;
16072e59129aSraghus 			rx_cfg_l.bits.entest = 1;
16082e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
16092e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16102e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
16112e59129aSraghus 			    portn, test_cfg.value));
16122e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
16132e59129aSraghus 			    ESR_N2_DEV_ADDR,
16142e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
16152e59129aSraghus 				goto fail;
16162e59129aSraghus 			}
16172e59129aSraghus 		}
161844961713Sgirish 	} else {
161944961713Sgirish 		goto fail;
162044961713Sgirish 	}
162144961713Sgirish 
162244961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
162344961713Sgirish 
162444961713Sgirish 	NXGE_DELAY(20);
162544961713Sgirish 
162644961713Sgirish 	/* init TX channels */
162744961713Sgirish 	for (chan = 0; chan < 4; chan++) {
162844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
162952ccf843Smisaki 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
163044961713Sgirish 			goto fail;
163144961713Sgirish 
163244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
163352ccf843Smisaki 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
163444961713Sgirish 			goto fail;
16352e59129aSraghus 
16362e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16372e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16382e59129aSraghus 		    portn, chan, tx_cfg_l.value));
16392e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16402e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16412e59129aSraghus 		    portn, chan, tx_cfg_h.value));
164244961713Sgirish 	}
164344961713Sgirish 
164444961713Sgirish 	/* init RX channels */
164544961713Sgirish 	for (chan = 0; chan < 4; chan++) {
164644961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
164752ccf843Smisaki 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
164844961713Sgirish 			goto fail;
164944961713Sgirish 
165044961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
165152ccf843Smisaki 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
165244961713Sgirish 			goto fail;
16532e59129aSraghus 
16542e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16552e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16562e59129aSraghus 		    portn, chan, rx_cfg_l.value));
165700161856Syc 
16582e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16592e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16602e59129aSraghus 		    portn, chan, rx_cfg_h.value));
166144961713Sgirish 	}
166244961713Sgirish 
166344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
166452ccf843Smisaki 	    portn));
166544961713Sgirish 
166644961713Sgirish 	return (NXGE_OK);
166744961713Sgirish fail:
16682d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16692d17280bSsbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16702d17280bSsbehera 	    portn));
167144961713Sgirish 
167244961713Sgirish 	return (status);
167344961713Sgirish }
167444961713Sgirish 
167559ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
167644961713Sgirish 
167759ac0c16Sdavemq static nxge_status_t
167859ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
167944961713Sgirish {
168044961713Sgirish 	npi_handle_t		handle;
168144961713Sgirish 	uint8_t			portn;
1682321febdeSsbehera 	int			chan, i;
168344961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
168444961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
168544961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
168644961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
168744961713Sgirish 	uint64_t		val;
168844961713Sgirish 	uint16_t		val16l;
168944961713Sgirish 	uint16_t		val16h;
169044961713Sgirish 	nxge_status_t		status = NXGE_OK;
169144961713Sgirish 
169244961713Sgirish 	portn = nxgep->mac.portnum;
169344961713Sgirish 
169444961713Sgirish 	if ((portn != 0) && (portn != 1))
169544961713Sgirish 		return (NXGE_OK);
169644961713Sgirish 
169759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
169859ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
169944961713Sgirish 	handle = nxgep->npi_handle;
170059ac0c16Sdavemq 	switch (portn) {
170159ac0c16Sdavemq 	case 0:
17024202ea4bSsbehera 		/* Reset Serdes */
17034202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
17044202ea4bSsbehera 		NXGE_DELAY(20);
17054202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17064202ea4bSsbehera 		NXGE_DELAY(2000);
17074202ea4bSsbehera 
17084202ea4bSsbehera 		/* Configure Serdes to 10G mode */
17094202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
17104202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
17114202ea4bSsbehera 
171259ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
171359ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
171459ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
171559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
171659ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
171759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
171859ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
171959ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
172059ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
172159ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
172259ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
172359ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
172459ac0c16Sdavemq 
172559ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
172659ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
172759ac0c16Sdavemq 			ESR_REG_WR(handle,
172859ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
172959ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
173059ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
173159ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
173259ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
173359ac0c16Sdavemq 		} else {
173459ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
173544961713Sgirish 		}
173659ac0c16Sdavemq 		break;
173759ac0c16Sdavemq 	case 1:
17384202ea4bSsbehera 		/* Reset Serdes */
17394202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
17404202ea4bSsbehera 		NXGE_DELAY(20);
17414202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17424202ea4bSsbehera 		NXGE_DELAY(2000);
17434202ea4bSsbehera 
17444202ea4bSsbehera 		/* Configure Serdes to 10G mode */
17454202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
17464202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
17474202ea4bSsbehera 
174859ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
174959ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
175059ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
175159ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
175259ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
175359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
175459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
175559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
175659ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
175759ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
175859ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
175959ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
176059ac0c16Sdavemq 
176159ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
176259ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
176359ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
176459ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
176559ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
176659ac0c16Sdavemq 		} else {
176759ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
176844961713Sgirish 		}
176959ac0c16Sdavemq 		break;
177059ac0c16Sdavemq 	default:
177159ac0c16Sdavemq 		/* Nothing to do here */
177259ac0c16Sdavemq 		goto done;
177359ac0c16Sdavemq 	}
177444961713Sgirish 
177559ac0c16Sdavemq 	/* init TX RX channels */
177659ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
177759ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
177859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
177959ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
178044961713Sgirish 			goto fail;
178159ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
178259ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
178359ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
178444961713Sgirish 			goto fail;
178559ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
178659ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
178759ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
178859ac0c16Sdavemq 			goto fail;
178959ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
179059ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
179159ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
179259ac0c16Sdavemq 			goto fail;
179359ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
179459ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
179559ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
179659ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
179759ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
179859ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
179959ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
180044961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
180159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
180259ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
180344961713Sgirish 			goto fail;
180444961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
180559ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
180659ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
180744961713Sgirish 			goto fail;
180859ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
180959ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
181059ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
181144961713Sgirish 			goto fail;
181259ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
181359ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
181459ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
181544961713Sgirish 			goto fail;
181644961713Sgirish 		}
181744961713Sgirish 
181859ac0c16Sdavemq 	/* Apply Tx core reset */
181959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
182059ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
182159ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
182259ac0c16Sdavemq 		goto fail;
182359ac0c16Sdavemq 
182459ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
182559ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
182659ac0c16Sdavemq 	    NXGE_OK)
182759ac0c16Sdavemq 		goto fail;
182859ac0c16Sdavemq 
182959ac0c16Sdavemq 	NXGE_DELAY(200);
183059ac0c16Sdavemq 
183159ac0c16Sdavemq 	/* Apply Rx core reset */
183259ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
183359ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
183459ac0c16Sdavemq 	    NXGE_OK)
183559ac0c16Sdavemq 		goto fail;
183659ac0c16Sdavemq 
183759ac0c16Sdavemq 	NXGE_DELAY(200);
183859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
183959ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
184059ac0c16Sdavemq 		goto fail;
184159ac0c16Sdavemq 
184259ac0c16Sdavemq 	NXGE_DELAY(200);
184359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
184459ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
184559ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
184659ac0c16Sdavemq 		goto fail;
184759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
184859ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
184959ac0c16Sdavemq 		goto fail;
185059ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
185159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1852d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1853d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
1854d81011f0Ssbehera 		    portn, val16l, val16h));
185559ac0c16Sdavemq 	}
185659ac0c16Sdavemq 
185759ac0c16Sdavemq 	if (portn == 0) {
1858321febdeSsbehera 		/* Wait for serdes to be ready */
1859321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1860321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1861321febdeSsbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
1862321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1863321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P0 |
1864321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH3 |
1865321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH2 |
1866321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH1 |
1867321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
1868321febdeSsbehera 
1869321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1870321febdeSsbehera 			else
1871321febdeSsbehera 				break;
1872321febdeSsbehera 		}
1873321febdeSsbehera 
1874321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1875ab6abb7aSjoycey 			/*
1876ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
1877ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
1878ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
1879ab6abb7aSjoycey 			 * stays down
1880ab6abb7aSjoycey 			 */
1881321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1882321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1883321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
188400161856Syc 				goto done;
188559ac0c16Sdavemq 		}
188659ac0c16Sdavemq 	} else if (portn == 1) {
1887321febdeSsbehera 		/* Wait for serdes to be ready */
1888321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1889321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1890321febdeSsbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
1891321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1892321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P1 |
1893321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH3 |
1894321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH2 |
1895321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH1 |
1896321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
1897321febdeSsbehera 
1898321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1899321febdeSsbehera 			else
1900321febdeSsbehera 				break;
1901321febdeSsbehera 		}
1902321febdeSsbehera 
1903321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1904ab6abb7aSjoycey 			/*
1905ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
1906ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
1907ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
1908ab6abb7aSjoycey 			 * stays down
1909ab6abb7aSjoycey 			 */
1910321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1911321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1912321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
191300161856Syc 				goto done;
191444961713Sgirish 		}
191544961713Sgirish 	}
191644961713Sgirish 
191744961713Sgirish done:
191859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
191959ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
192059ac0c16Sdavemq 
192144961713Sgirish 	return (NXGE_OK);
192244961713Sgirish fail:
19232d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
192459ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
192559ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
192644961713Sgirish 
192744961713Sgirish 	return (status);
192844961713Sgirish }
192944961713Sgirish 
193059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
193144961713Sgirish 
193259ac0c16Sdavemq static nxge_status_t
193359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
193444961713Sgirish {
193559ac0c16Sdavemq 	npi_handle_t		handle;
193659ac0c16Sdavemq 	uint8_t			portn;
1937d81011f0Ssbehera 	int			chan;
1938d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1939d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1940d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1941d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
194259ac0c16Sdavemq 	uint64_t		val;
1943d81011f0Ssbehera 	uint16_t		val16l;
1944d81011f0Ssbehera 	uint16_t		val16h;
1945d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
194644961713Sgirish 
194744961713Sgirish 	portn = nxgep->mac.portnum;
194844961713Sgirish 
194959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
195059ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
195144961713Sgirish 
195259ac0c16Sdavemq 	handle = nxgep->npi_handle;
195344961713Sgirish 
195459ac0c16Sdavemq 	switch (portn) {
195559ac0c16Sdavemq 	case 0:
1956d81011f0Ssbehera 		/* Assert the reset register */
1957d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1958d81011f0Ssbehera 		val |= ESR_RESET_0;
1959d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1960d81011f0Ssbehera 
1961d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
1962d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1963d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1964d81011f0Ssbehera 
1965d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1966d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
1967d81011f0Ssbehera 
1968d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
1969d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1970d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
1971d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
1972d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1973d81011f0Ssbehera 		} else {
1974d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1975d81011f0Ssbehera 		}
1976d81011f0Ssbehera 
1977d81011f0Ssbehera 		/* Deassert the reset register */
1978d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1979d81011f0Ssbehera 		val &= ~ESR_RESET_0;
1980d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
198159ac0c16Sdavemq 		break;
1982d81011f0Ssbehera 
198359ac0c16Sdavemq 	case 1:
1984d81011f0Ssbehera 		/* Assert the reset register */
1985d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1986d81011f0Ssbehera 		val |= ESR_RESET_1;
1987d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1988d81011f0Ssbehera 
1989d81011f0Ssbehera 		/* Set PLL register to 0x79 */
1990d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1991d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1992d81011f0Ssbehera 
1993d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1994d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
1995d81011f0Ssbehera 
1996d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
1997d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1998d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
1999d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2000d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
2001d81011f0Ssbehera 		} else {
2002d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2003d81011f0Ssbehera 		}
2004d81011f0Ssbehera 
2005d81011f0Ssbehera 		/* Deassert the reset register */
2006d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2007d81011f0Ssbehera 		val &= ~ESR_RESET_1;
2008d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
200959ac0c16Sdavemq 		break;
2010d81011f0Ssbehera 
201159ac0c16Sdavemq 	default:
2012d81011f0Ssbehera 		/* Nothing to do here */
2013d81011f0Ssbehera 		goto done;
2014d81011f0Ssbehera 	}
2015d81011f0Ssbehera 
2016d81011f0Ssbehera 	/* init TX RX channels */
2017d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
2018d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2019d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2020d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
2021d81011f0Ssbehera 			goto fail;
2022d81011f0Ssbehera 		}
2023d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2024d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2025d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
2026d81011f0Ssbehera 			goto fail;
2027d81011f0Ssbehera 		}
2028d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2029d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2030d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
2031d81011f0Ssbehera 			goto fail;
2032d81011f0Ssbehera 		}
2033d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2034d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2035d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
2036d81011f0Ssbehera 			goto fail;
2037d81011f0Ssbehera 		}
2038d81011f0Ssbehera 
2039d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
2040d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2041d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
2042d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
2043d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
2044d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2045d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2046d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2047d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2048d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
2049d81011f0Ssbehera 			goto fail;
2050d81011f0Ssbehera 		}
2051d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2052d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2053d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
2054d81011f0Ssbehera 			goto fail;
2055d81011f0Ssbehera 		}
2056d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2057d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2058d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
2059d81011f0Ssbehera 			goto fail;
2060d81011f0Ssbehera 		}
2061d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2062d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2063d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
2064d81011f0Ssbehera 			goto fail;
2065d81011f0Ssbehera 		}
2066d81011f0Ssbehera 	}
2067d81011f0Ssbehera 
2068d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2069d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2070d81011f0Ssbehera 		goto fail;
2071d81011f0Ssbehera 	}
2072d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2073d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2074d81011f0Ssbehera 		goto fail;
2075d81011f0Ssbehera 	}
2076d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2077d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2078d81011f0Ssbehera 		goto fail;
2079d81011f0Ssbehera 	}
2080d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2081d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
208259ac0c16Sdavemq 		goto fail;
208344961713Sgirish 	}
208444961713Sgirish 
2085d81011f0Ssbehera 	/* Apply Tx core reset */
2086d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2087d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2088d81011f0Ssbehera 		goto fail;
2089d81011f0Ssbehera 	}
2090d81011f0Ssbehera 
2091d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2092d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2093d81011f0Ssbehera 	    NXGE_OK) {
2094d81011f0Ssbehera 		goto fail;
2095d81011f0Ssbehera 	}
2096d81011f0Ssbehera 
2097d81011f0Ssbehera 	NXGE_DELAY(200);
2098d81011f0Ssbehera 
2099d81011f0Ssbehera 	/* Apply Rx core reset */
2100d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2101d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2102d81011f0Ssbehera 	    NXGE_OK) {
2103d81011f0Ssbehera 		goto fail;
2104d81011f0Ssbehera 	}
2105d81011f0Ssbehera 
2106d81011f0Ssbehera 	NXGE_DELAY(200);
2107d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2108d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2109d81011f0Ssbehera 		goto fail;
2110d81011f0Ssbehera 	}
2111d81011f0Ssbehera 
2112d81011f0Ssbehera 	NXGE_DELAY(200);
2113d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2114d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2115d81011f0Ssbehera 		goto fail;
2116d81011f0Ssbehera 	}
2117d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2118d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2119d81011f0Ssbehera 		goto fail;
2120d81011f0Ssbehera 	}
2121d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
2122d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2123d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2124d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2125d81011f0Ssbehera 		status = NXGE_ERROR;
2126d81011f0Ssbehera 		goto fail;
2127d81011f0Ssbehera 	}
2128d81011f0Ssbehera 
2129d81011f0Ssbehera 	NXGE_DELAY(200);
2130d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2131d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2132d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2133d81011f0Ssbehera 	    "val 0x%x", portn, val));
2134d81011f0Ssbehera 	if (portn == 0) {
2135d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2136d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2137ab6abb7aSjoycey 			/*
2138ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2139ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2140ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2141ab6abb7aSjoycey 			 * stays down
2142ab6abb7aSjoycey 			 */
2143d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2144ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2145ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
214600161856Syc 				goto done;
2147d81011f0Ssbehera 		}
2148d81011f0Ssbehera 	} else if (portn == 1) {
2149d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2150d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2151ab6abb7aSjoycey 			/*
2152ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2153ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2154ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2155ab6abb7aSjoycey 			 * stays down
2156ab6abb7aSjoycey 			 */
2157d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2158ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2159ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
216000161856Syc 				goto done;
216100161856Syc 
2162d81011f0Ssbehera 		}
2163d81011f0Ssbehera 	}
2164d81011f0Ssbehera done:
216559ac0c16Sdavemq 
216659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
216759ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
216844961713Sgirish 	return (NXGE_OK);
216959ac0c16Sdavemq fail:
2170d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
217159ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
217259ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
217359ac0c16Sdavemq 	    portn));
217459ac0c16Sdavemq 
2175d81011f0Ssbehera 	return (status);
217644961713Sgirish }
217744961713Sgirish 
21782d17280bSsbehera /* Initialize the BCM 8704 xcvr */
217944961713Sgirish 
218059ac0c16Sdavemq static nxge_status_t
21812d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
218244961713Sgirish {
218344961713Sgirish 	uint16_t		val;
218444961713Sgirish #ifdef	NXGE_DEBUG
218514ea4bb7Ssd 	uint8_t			portn;
218644961713Sgirish 	uint16_t		val1;
218744961713Sgirish #endif
218844961713Sgirish 	uint8_t			phy_port_addr;
218944961713Sgirish 	pmd_tx_control_t	tx_ctl;
219044961713Sgirish 	control_t		ctl;
219144961713Sgirish 	phyxs_control_t		phyxs_ctl;
219244961713Sgirish 	pcs_control_t		pcs_ctl;
219344961713Sgirish 	uint32_t		delay = 0;
219444961713Sgirish 	optics_dcntr_t		op_ctr;
219544961713Sgirish 	nxge_status_t		status = NXGE_OK;
219614ea4bb7Ssd #ifdef	NXGE_DEBUG
219744961713Sgirish 	portn = nxgep->mac.portnum;
219814ea4bb7Ssd #endif
21992d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
220059ac0c16Sdavemq 	    portn));
220144961713Sgirish 
220259ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
220359ac0c16Sdavemq 
220459ac0c16Sdavemq 	/* Reset the transceiver */
220559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
220659ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
220759ac0c16Sdavemq 		goto fail;
220859ac0c16Sdavemq 
220959ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
221059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
221159ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
221259ac0c16Sdavemq 		goto fail;
221359ac0c16Sdavemq 
221459ac0c16Sdavemq 	do {
221559ac0c16Sdavemq 		drv_usecwait(500);
221659ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
221759ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
221859ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
221959ac0c16Sdavemq 			goto fail;
222059ac0c16Sdavemq 		delay++;
222159ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
222259ac0c16Sdavemq 	if (delay == 100) {
222359ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
222459ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
222559ac0c16Sdavemq 		status = NXGE_ERROR;
222659ac0c16Sdavemq 		goto fail;
222759ac0c16Sdavemq 	}
222844961713Sgirish 
222959ac0c16Sdavemq 	/* Set to 0x7FBF */
223059ac0c16Sdavemq 	ctl.value = 0;
223159ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
223259ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
223359ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
223459ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
223559ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
223659ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
223759ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
223859ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
223959ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
224059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
224159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
224259ac0c16Sdavemq 	    != NXGE_OK)
224359ac0c16Sdavemq 		goto fail;
224459ac0c16Sdavemq 
224559ac0c16Sdavemq 	/* Set to 0x164 */
224659ac0c16Sdavemq 	tx_ctl.value = 0;
224759ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
224859ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
224959ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
225059ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
225159ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
225259ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
225359ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
225459ac0c16Sdavemq 		goto fail;
225544961713Sgirish 	/*
225659ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
225759ac0c16Sdavemq 	 * back these registers twice after written.
225844961713Sgirish 	 */
225959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
226059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
226159ac0c16Sdavemq 	    != NXGE_OK)
226259ac0c16Sdavemq 		goto fail;
226344961713Sgirish 
226459ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
226559ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
226659ac0c16Sdavemq 	    != NXGE_OK)
226759ac0c16Sdavemq 		goto fail;
226844961713Sgirish 
226959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
227059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
227159ac0c16Sdavemq 	    != NXGE_OK)
227259ac0c16Sdavemq 		goto fail;
227344961713Sgirish 
227459ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
227559ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
227659ac0c16Sdavemq 	    != NXGE_OK)
227759ac0c16Sdavemq 		goto fail;
227844961713Sgirish 
227959ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
228059ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
228159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
228259ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
228359ac0c16Sdavemq 		goto fail;
2284cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2285cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
2286cb9d3ae6Smisaki 	} else {
2287cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x3;
2288cb9d3ae6Smisaki 	}
228959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
229059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
229159ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
229259ac0c16Sdavemq 		goto fail;
229344961713Sgirish 
229459ac0c16Sdavemq 	NXGE_DELAY(1000000);
229544961713Sgirish 
229659ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
229759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
229859ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
229959ac0c16Sdavemq 	    != NXGE_OK)
230059ac0c16Sdavemq 		goto fail;
230159ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
230259ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
230359ac0c16Sdavemq 	else
230459ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
230559ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
230659ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
230759ac0c16Sdavemq 	    != NXGE_OK)
230859ac0c16Sdavemq 		goto fail;
230944961713Sgirish 
231059ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
231159ac0c16Sdavemq 	if (status != NXGE_OK)
231259ac0c16Sdavemq 		goto fail;
231359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
231459ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
231559ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
231659ac0c16Sdavemq 	if (status != NXGE_OK)
231759ac0c16Sdavemq 		goto fail;
231859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
231959ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
232059ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
232159ac0c16Sdavemq 	if (status != NXGE_OK)
232259ac0c16Sdavemq 		goto fail;
232359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
232459ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
232544961713Sgirish 
232659ac0c16Sdavemq #ifdef	NXGE_DEBUG
232759ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
232859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
232959ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
233059ac0c16Sdavemq 	    &val);
233159ac0c16Sdavemq 	if (status != NXGE_OK)
233259ac0c16Sdavemq 		goto fail;
233344961713Sgirish 
233459ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
233552ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
233659ac0c16Sdavemq 	if (status != NXGE_OK)
233759ac0c16Sdavemq 		goto fail;
233844961713Sgirish 
233959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
234052ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
234159ac0c16Sdavemq 	if (status != NXGE_OK)
234259ac0c16Sdavemq 		goto fail;
234344961713Sgirish 
234459ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
234552ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
234659ac0c16Sdavemq 	if (status != NXGE_OK)
234759ac0c16Sdavemq 		goto fail;
234844961713Sgirish 
234959ac0c16Sdavemq 	if (val != 0x3FC) {
235059ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
235159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
235259ac0c16Sdavemq 			    "Cable not connected to peer or bad"
235359ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
235459ac0c16Sdavemq 		} else if (val == 0x639C) {
235559ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
235659ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
235759ac0c16Sdavemq 			    " on port<%d>\n", portn));
235859ac0c16Sdavemq 		}
235959ac0c16Sdavemq 	}
236059ac0c16Sdavemq #endif
236144961713Sgirish 
23622d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
23632d17280bSsbehera 	    portn));
23642d17280bSsbehera 	return (NXGE_OK);
23652d17280bSsbehera 
23662d17280bSsbehera fail:
23672d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23682d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
23692d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
23702d17280bSsbehera 	return (NXGE_ERROR);
23712d17280bSsbehera }
23722d17280bSsbehera 
23732d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
23742d17280bSsbehera 
23752d17280bSsbehera static nxge_status_t
23762d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
23772d17280bSsbehera {
23782d17280bSsbehera 	uint8_t			phy_port_addr;
23792d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
23802d17280bSsbehera 	pcs_control_t		pcs_ctl;
23812d17280bSsbehera 	uint32_t		delay = 0;
23822d17280bSsbehera 	optics_dcntr_t		op_ctr;
23832d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
23842d17280bSsbehera #ifdef	NXGE_DEBUG
23852d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
23862d17280bSsbehera #endif
23872d17280bSsbehera 
23882d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
23892d17280bSsbehera 	    portn));
23902d17280bSsbehera 
23912d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
23922d17280bSsbehera 
23932d17280bSsbehera 	/* Reset the transceiver */
23942d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23952d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
23962d17280bSsbehera 		goto fail;
23972d17280bSsbehera 
23982d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
23992d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
24002d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
24012d17280bSsbehera 		goto fail;
24022d17280bSsbehera 	do {
24032d17280bSsbehera 		drv_usecwait(500);
24042d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24052d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
24062d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
24072d17280bSsbehera 			goto fail;
24082d17280bSsbehera 		delay++;
24092d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
24102d17280bSsbehera 
24112d17280bSsbehera 	if (delay == 100) {
24122d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
24132d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
24142d17280bSsbehera 		status = NXGE_ERROR;
24152d17280bSsbehera 		goto fail;
24162d17280bSsbehera 	}
24172d17280bSsbehera 
24182d17280bSsbehera 	NXGE_DELAY(1000000);
24192d17280bSsbehera 
24202d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
24212d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24222d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
24232d17280bSsbehera 	    != NXGE_OK)
24242d17280bSsbehera 		goto fail;
24252d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24262d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
24272d17280bSsbehera 	else
24282d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
24292d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24302d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
24312d17280bSsbehera 	    != NXGE_OK)
24322d17280bSsbehera 		goto fail;
24332d17280bSsbehera 
24342d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
24352d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24362d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24372d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
24382d17280bSsbehera 		goto fail;
24392d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
24402d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
24412d17280bSsbehera 
24422d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24432d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24442d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
24452d17280bSsbehera 		goto fail;
24462d17280bSsbehera 
24472d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
24482d17280bSsbehera 	    portn));
24492d17280bSsbehera 	return (NXGE_OK);
24502d17280bSsbehera 
24512d17280bSsbehera fail:
24522d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24532d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
24542d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
24552d17280bSsbehera 	return (status);
24562d17280bSsbehera }
24572d17280bSsbehera 
245852cdd236Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
245952cdd236Ssbehera 
246052cdd236Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
246152cdd236Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
246252cdd236Ssbehera 
246352cdd236Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
246452cdd236Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
246552cdd236Ssbehera 
246652cdd236Ssbehera 
246752cdd236Ssbehera static void
246852cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
246952cdd236Ssbehera {
247052cdd236Ssbehera 	uint16_t	value;
247152cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
247252cdd236Ssbehera 
247352cdd236Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
247452cdd236Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
247552cdd236Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
247652cdd236Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
247752cdd236Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
247852cdd236Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
247952cdd236Ssbehera 		    value);
248052cdd236Ssbehera 	}
248152cdd236Ssbehera }
248252cdd236Ssbehera 
248352cdd236Ssbehera static nxge_status_t
248452cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
248552cdd236Ssbehera {
248652cdd236Ssbehera 	nxge_status_t	status;
248752cdd236Ssbehera 	pcs_control_t	pcs_ctl;
248852cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
248952cdd236Ssbehera 
249052cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
249152cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
249252cdd236Ssbehera 
249352cdd236Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
249452cdd236Ssbehera 		pcs_ctl.bits.loopback = 1;
249552cdd236Ssbehera 	else
249652cdd236Ssbehera 		pcs_ctl.bits.loopback = 0;
249752cdd236Ssbehera 
249852cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
249952cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
250052cdd236Ssbehera 
250152cdd236Ssbehera fail:
250252cdd236Ssbehera 	return (status);
250352cdd236Ssbehera }
250452cdd236Ssbehera 
250552cdd236Ssbehera 
250652cdd236Ssbehera static void
250752cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
250852cdd236Ssbehera {
250952cdd236Ssbehera 	uint16_t	val2;
251052cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
251152cdd236Ssbehera 
251252cdd236Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
251352cdd236Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
251452cdd236Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
251552cdd236Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
251652cdd236Ssbehera 
251752cdd236Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
251852cdd236Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
251952cdd236Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
252052cdd236Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
252152cdd236Ssbehera 	}
252252cdd236Ssbehera }
252352cdd236Ssbehera 
252452cdd236Ssbehera 
252552cdd236Ssbehera static nxge_status_t
252652cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
252752cdd236Ssbehera {
252852cdd236Ssbehera 	uint8_t		phy;
252952cdd236Ssbehera 	nxge_status_t	status;
253052cdd236Ssbehera 	uint16_t	clk;
253152cdd236Ssbehera 
253252cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
253352cdd236Ssbehera 
253452cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
253552cdd236Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
253652cdd236Ssbehera 	    nxgep->mac.portnum, phy));
253752cdd236Ssbehera 
253852cdd236Ssbehera 	/* Set LED functions	*/
253952cdd236Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
254052cdd236Ssbehera 	/* PCS activity */
254152cdd236Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
254252cdd236Ssbehera 
254352cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
254452cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
254552cdd236Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
254652cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
254752cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
254852cdd236Ssbehera 
254952cdd236Ssbehera 	/* Set internal loopback mode if necessary */
255052cdd236Ssbehera 
255152cdd236Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
255252cdd236Ssbehera 
255352cdd236Ssbehera 	/* Enable PMD */
255452cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
255552cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
255652cdd236Ssbehera 
255752cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
255852cdd236Ssbehera 
255952cdd236Ssbehera fail:
256052cdd236Ssbehera 	return (status);
256152cdd236Ssbehera }
256252cdd236Ssbehera 
256352cdd236Ssbehera 
256452cdd236Ssbehera 
25652d17280bSsbehera /* Initialize the 10G Transceiver */
25662d17280bSsbehera 
25672d17280bSsbehera static nxge_status_t
25682d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
25692d17280bSsbehera {
25702d17280bSsbehera 	p_nxge_stats_t		statsp;
25711bd6825cSml 	p_nxge_param_t		param_arr = nxgep->param_arr;
25722d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
25732d17280bSsbehera #ifdef	NXGE_DEBUG
25742d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
25752d17280bSsbehera #endif
25762d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
25772d17280bSsbehera 	    portn));
25782d17280bSsbehera 
25792d17280bSsbehera 	statsp = nxgep->statsp;
25802d17280bSsbehera 
25811c7408c9Stc 	/* Disable Link LEDs, with or without PHY */
25821c7408c9Stc 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
25832d17280bSsbehera 		goto done;
25842d17280bSsbehera 
25851c7408c9Stc 	/* Skip MDIO, if PHY absent */
25861c7408c9Stc 	if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
25871c7408c9Stc 		goto done;
25881c7408c9Stc 	}
25892d17280bSsbehera 
25902d17280bSsbehera 	/* Set Clause 45 */
25912d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
25922d17280bSsbehera 
25932d17280bSsbehera 	switch (nxgep->chip_id) {
25942d17280bSsbehera 	case BCM8704_CHIP_ID:
259500161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25962d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
25972d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
25982d17280bSsbehera 		break;
25992d17280bSsbehera 	case BCM8706_CHIP_ID:
260000161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
26012d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
26022d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
26032d17280bSsbehera 		break;
260452cdd236Ssbehera 	case MRVL88X201X_CHIP_ID:
260500161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
260652cdd236Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
260752cdd236Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
260852cdd236Ssbehera 		break;
26092d17280bSsbehera 	default:
26102d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
26112d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
26122d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
26132d17280bSsbehera 		goto fail;
26142d17280bSsbehera 	}
26152d17280bSsbehera 
26162d17280bSsbehera 	if (status != NXGE_OK) {
26172d17280bSsbehera 		goto fail;
26182d17280bSsbehera 	}
26192e59129aSraghus done:
262059ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
262159ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
26221bd6825cSml 	statsp->mac_stats.adv_cap_asmpause =
26231bd6825cSml 	    param_arr[param_anar_asmpause].value;
26241bd6825cSml 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
262544961713Sgirish 
262659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
262759ac0c16Sdavemq 	    portn));
262859ac0c16Sdavemq 	return (NXGE_OK);
262944961713Sgirish 
263059ac0c16Sdavemq fail:
26312d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
263259ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
26332d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
26342d17280bSsbehera 	return (NXGE_ERROR);
263559ac0c16Sdavemq }
263644961713Sgirish 
263759ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
263844961713Sgirish 
263959ac0c16Sdavemq static nxge_status_t
264059ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
264159ac0c16Sdavemq {
264259ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
264359ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
264459ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
264544961713Sgirish 
26462e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
26472e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
26482e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
26492e59129aSraghus 		goto done;
26502e59129aSraghus 	}
26512e59129aSraghus 
265259ac0c16Sdavemq 	/* Set Clause 22 */
265359ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
265444961713Sgirish 
265559ac0c16Sdavemq 	/* Set capability flags */
265659ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
26572e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
26582e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
26592e59129aSraghus 		statsp->mac_stats.cap_100fdx =
26602e59129aSraghus 		    param_arr[param_anar_100fdx].value;
26612e59129aSraghus 		statsp->mac_stats.cap_10fdx =
26622e59129aSraghus 		    param_arr[param_anar_10fdx].value;
26632e59129aSraghus 	}
266444961713Sgirish 
266559ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
26662e59129aSraghus done:
266759ac0c16Sdavemq 	return (status);
266859ac0c16Sdavemq }
266959ac0c16Sdavemq 
267000161856Syc /*
267100161856Syc  * Although the Teranetics copper transceiver (TN1010) does not need
267200161856Syc  * to be initialized by the driver for passing packets, this funtion
267300161856Syc  * initializes the members of nxgep->statsp->mac_stats struct for
267400161856Syc  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
267500161856Syc  * It also configures the TN1010 for PHY loopback to support SunVTS.
267600161856Syc  *
267700161856Syc  * TN1010 only has the option to disable advertisement for the 10G
267800161856Syc  * mode. So we can set it to either Dual Mode or 1G Only mode but
267900161856Syc  * can't set it to 10G Only mode.
268000161856Syc  *
268100161856Syc  * ndd -set command can set the following 6 speed/duplex related parameters.
268200161856Syc  *
268300161856Syc  * ----------------------------------------------------------------
268400161856Syc  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
268500161856Syc  * ----------------------------------------------------------------
268600161856Syc  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
268700161856Syc  * adv_10gfdx_cap
268800161856Syc  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
268900161856Syc  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
269000161856Syc  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
269100161856Syc  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
269200161856Syc  * ----------------------------------------------------------------
269300161856Syc  */
269400161856Syc static nxge_status_t
269500161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep)
269600161856Syc {
269700161856Syc 	p_nxge_param_t		param_arr;
269800161856Syc 	p_nxge_stats_t		statsp;
269900161856Syc 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
270000161856Syc 	uint16_t		speed;
270100161856Syc 	uint8_t			phy_port_addr;
270200161856Syc 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
270300161856Syc 	int			status = NXGE_OK;
270400161856Syc 
270500161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
270600161856Syc 
270700161856Syc 	param_arr	= nxgep->param_arr;
270800161856Syc 	statsp		= nxgep->statsp;
270900161856Syc 
271000161856Syc 	/*
271100161856Syc 	 * Initialize the xcvr statistics which are NOT controlled by ndd
271200161856Syc 	 */
271300161856Syc 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
271400161856Syc 	statsp->mac_stats.cap_100T4    = 0;
271500161856Syc 
271600161856Syc 	/*
271700161856Syc 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
271800161856Syc 	 * that function nxge_check_tn1010_link repeatedly invoked by the
271900161856Syc 	 * timer will update link_speed real time.
272000161856Syc 	 */
272100161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
272200161856Syc 		goto fail;
272300161856Syc 	}
272400161856Syc 	if (speed == TN1010_SPEED_1G) {
272500161856Syc 		statsp->mac_stats.cap_10gfdx = 0;
272600161856Syc 	} else {
272700161856Syc 		statsp->mac_stats.cap_10gfdx = 1;
272800161856Syc 	}
272900161856Syc 
273000161856Syc 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
273100161856Syc 	statsp->mac_stats.cap_1000fdx  = 1;
273200161856Syc 
273300161856Syc 	/* TN1010 is not able to operate in the following states */
273400161856Syc 	statsp->mac_stats.cap_1000hdx  = 0;
273500161856Syc 	statsp->mac_stats.cap_100fdx   = 0;
273600161856Syc 	statsp->mac_stats.cap_100hdx   = 0;
273700161856Syc 	statsp->mac_stats.cap_10fdx    = 0;
273800161856Syc 	statsp->mac_stats.cap_10hdx    = 0;
273900161856Syc 
274000161856Syc 	/* param_anar_pause can be modified by ndd -set */
274100161856Syc 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
274200161856Syc 
274300161856Syc 	/*
274400161856Syc 	 * The following 4 lines actually overwrites what ever the ndd command
274500161856Syc 	 * has set. For example, by command
274600161856Syc 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
274700161856Syc 	 * we could set param_arr[param_autoneg].value to n.  However, because
274800161856Syc 	 * here we assign constants to these parameters, whatever we set with
274900161856Syc 	 * the "ndd -set" command will be replaced. So command
275000161856Syc 	 *	kstat nxge:X | grep param
275100161856Syc 	 * will always show those constant values.  In other words, the
275200161856Syc 	 * "ndd -set" command can NOT change the values of these 4 parameters
275300161856Syc 	 * even though the command appears to be successful.
275400161856Syc 	 *
275500161856Syc 	 * Note: TN1010 auto negotiation is always enabled.
275600161856Syc 	 */
275700161856Syc 	statsp->mac_stats.adv_cap_autoneg
275800161856Syc 	    = param_arr[param_autoneg].value = 1;
275900161856Syc 	statsp->mac_stats.adv_cap_1000fdx
276000161856Syc 	    = param_arr[param_anar_1000fdx].value = 1;
276100161856Syc 	statsp->mac_stats.adv_cap_100fdx
276200161856Syc 	    = param_arr[param_anar_100fdx].value = 0;
276300161856Syc 	statsp->mac_stats.adv_cap_10fdx
276400161856Syc 	    = param_arr[param_anar_10fdx].value = 0;
276500161856Syc 
276600161856Syc 	/*
276700161856Syc 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
276800161856Syc 	 * defined in nxge_param_arr[], therefore they are not seen by the
276900161856Syc 	 * "ndd -get" command and can not be changed by ndd.  We just set
277000161856Syc 	 * them (both ndd param and kstat values) to constant 0 because TN1010
277100161856Syc 	 * does not support those speeds.
277200161856Syc 	 */
277300161856Syc 	statsp->mac_stats.adv_cap_100T4
277400161856Syc 	    = param_arr[param_anar_100T4].value = 0;
277500161856Syc 	statsp->mac_stats.adv_cap_1000hdx
277600161856Syc 	    = param_arr[param_anar_1000hdx].value = 0;
277700161856Syc 	statsp->mac_stats.adv_cap_100hdx
277800161856Syc 	    = param_arr[param_anar_100hdx].value = 0;
277900161856Syc 	statsp->mac_stats.adv_cap_10hdx
278000161856Syc 	    = param_arr[param_anar_10hdx].value = 0;
278100161856Syc 
278200161856Syc 	/*
278300161856Syc 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
278400161856Syc 	 * by ndd
278500161856Syc 	 */
278600161856Syc 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
278700161856Syc 
278800161856Syc 	/*
278900161856Syc 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
279000161856Syc 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
279100161856Syc 	 * "ndd -get" command and can not be changed by ndd. Here we do not
279200161856Syc 	 * assign a constant to it so the default value defined in
279300161856Syc 	 * nxge_param_arr[] will be used to set the parameter and
279400161856Syc 	 * will be shown by the kstat.
279500161856Syc 	 */
279600161856Syc 	statsp->mac_stats.adv_cap_asmpause
279700161856Syc 	    = param_arr[param_anar_asmpause].value;
279800161856Syc 
279900161856Syc 	/*
280000161856Syc 	 * Initialize the link statistics.
280100161856Syc 	 */
280200161856Syc 	statsp->mac_stats.link_T4 = 0;
280300161856Syc 	statsp->mac_stats.link_asmpause = 0;
280400161856Syc 	statsp->mac_stats.link_pause = 0;
280500161856Syc 	if (speed == TN1010_SPEED_1G) {
280600161856Syc 		statsp->mac_stats.link_speed = 1000;
280700161856Syc 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
280800161856Syc 		statsp->mac_stats.link_up = 1;
280900161856Syc 	} else {
281000161856Syc 		statsp->mac_stats.link_speed = 10000;
281100161856Syc 		statsp->mac_stats.link_duplex = 2;
281200161856Syc 		statsp->mac_stats.link_up = 1;
281300161856Syc 	}
281400161856Syc 
281500161856Syc 	/*
281600161856Syc 	 * Because TN1010 does not have a link partner register, to
281700161856Syc 	 * figure out the link partner's capabilities is tricky. Here we
281800161856Syc 	 * just set the kstat based on our knowledge about the partner
281900161856Syc 	 * (The partner must support auto-neg because auto-negotiation
282000161856Syc 	 * has completed, it must support 1G or 10G because that is the
282100161856Syc 	 * negotiated speed we are using.)
282200161856Syc 	 *
282300161856Syc 	 * Note: Current kstat does not show lp_cap_10gfdx and
282400161856Syc 	 *	lp_cap_10ghdx.
282500161856Syc 	 */
282600161856Syc 	if (speed == TN1010_SPEED_1G) {
282700161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 1;
282800161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 0;
282900161856Syc 	} else {
283000161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 0;
283100161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 1;
283200161856Syc 	}
283300161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
283400161856Syc 	statsp->mac_stats.lp_cap_1000hdx  = 0;
283500161856Syc 	statsp->mac_stats.lp_cap_100fdx   = 0;
283600161856Syc 	statsp->mac_stats.lp_cap_100hdx   = 0;
283700161856Syc 	statsp->mac_stats.lp_cap_10fdx    = 0;
283800161856Syc 	statsp->mac_stats.lp_cap_10hdx    = 0;
283900161856Syc 	statsp->mac_stats.lp_cap_10gfdx   = 0;
284000161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
284100161856Syc 	statsp->mac_stats.lp_cap_100T4    = 0;
284200161856Syc 	statsp->mac_stats.lp_cap_autoneg  = 1;
284300161856Syc 	statsp->mac_stats.lp_cap_asmpause = 0;
284400161856Syc 	statsp->mac_stats.lp_cap_pause    = 0;
284500161856Syc 
284600161856Syc 	/* Handle PHY loopback for SunVTS loopback test */
284700161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
284800161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
284900161856Syc 
285000161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
285100161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
285200161856Syc 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
285300161856Syc 		goto fail;
285400161856Syc 	}
285500161856Syc 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
285600161856Syc 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
285700161856Syc 		tn1010_pcs_ctrl.bits.loopback = 1;
285800161856Syc 	} else {
285900161856Syc 		tn1010_pcs_ctrl.bits.loopback = 0;
286000161856Syc 	}
286100161856Syc 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
286200161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
286300161856Syc 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
286400161856Syc 		goto fail;
286500161856Syc 	}
286600161856Syc 
286700161856Syc 	statsp->mac_stats.xcvr_inits++;
286800161856Syc 
286900161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
287000161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
287100161856Syc 	return (status);
287200161856Syc fail:
287300161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
287400161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
287500161856Syc 	return (status);
287600161856Syc }
287700161856Syc 
287859ac0c16Sdavemq /* Initialize transceiver */
287959ac0c16Sdavemq 
288059ac0c16Sdavemq nxge_status_t
288159ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
288259ac0c16Sdavemq {
288359ac0c16Sdavemq 	p_nxge_stats_t		statsp;
288459ac0c16Sdavemq #ifdef	NXGE_DEBUG
288559ac0c16Sdavemq 	uint8_t			portn;
288644961713Sgirish #endif
288744961713Sgirish 
288859ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
288959ac0c16Sdavemq #ifdef	NXGE_DEBUG
289059ac0c16Sdavemq 	portn = nxgep->mac.portnum;
289159ac0c16Sdavemq #endif
289259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
289359ac0c16Sdavemq 	statsp = nxgep->statsp;
289444961713Sgirish 
289559ac0c16Sdavemq 	/*
289600161856Syc 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
289700161856Syc 	 * modify mac_stats.
289859ac0c16Sdavemq 	 */
289959ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
290059ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
290159ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
290259ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
290359ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
290459ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
290559ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
290659ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
290759ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
290859ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
290959ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
291059ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
291159ac0c16Sdavemq 
291259ac0c16Sdavemq 	/*
291359ac0c16Sdavemq 	 * Initialize the link statistics.
291459ac0c16Sdavemq 	 */
291559ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
291659ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
291759ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
291844961713Sgirish 
291959ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
292059ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
292159ac0c16Sdavemq 		if (status != NXGE_OK)
292244961713Sgirish 			goto fail;
292359ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
292444961713Sgirish 	}
292544961713Sgirish 
292659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
292759ac0c16Sdavemq 	    portn));
292844961713Sgirish 	return (NXGE_OK);
292944961713Sgirish 
293044961713Sgirish fail:
293144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
293259ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
293359ac0c16Sdavemq 	    portn));
293444961713Sgirish 	return (status);
293544961713Sgirish }
293644961713Sgirish 
29372e59129aSraghus /* Look for transceiver type */
29382e59129aSraghus 
29392e59129aSraghus nxge_status_t
29402e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
29412e59129aSraghus {
2942d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
2943d81011f0Ssbehera 	    nxgep->mac.portnum));
29442e59129aSraghus 
29452e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
29462e59129aSraghus 		return (NXGE_ERROR);
29472e59129aSraghus 
29482e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
29492e59129aSraghus 		return (NXGE_ERROR);
29502e59129aSraghus 
29512e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
29522e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
29532e59129aSraghus 	return (NXGE_OK);
29542e59129aSraghus }
295544961713Sgirish 
295644961713Sgirish /* Initialize the TxMAC sub-block */
295744961713Sgirish 
295844961713Sgirish nxge_status_t
295944961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
296044961713Sgirish {
296144961713Sgirish 	npi_attr_t		ap;
296244961713Sgirish 	uint8_t			portn;
296344961713Sgirish 	nxge_port_mode_t	portmode;
296444961713Sgirish 	nxge_port_t		portt;
296544961713Sgirish 	npi_handle_t		handle;
296644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
296744961713Sgirish 
296844961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
296944961713Sgirish 	portt    = nxgep->mac.porttype;
297044961713Sgirish 	handle   = nxgep->npi_handle;
297144961713Sgirish 	portmode = nxgep->mac.portmode;
297244961713Sgirish 
297344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
297452ccf843Smisaki 	    portn));
297544961713Sgirish 	/* Set Max and Min Frame Size */
29761bd6825cSml 	/*
29771bd6825cSml 	 * Use maxframesize to configure the hardware maxframe size
297800161856Syc 	 * and minframesize to configure the hardware minframe size.
29791bd6825cSml 	 */
29801bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29811bd6825cSml 	    "==> nxge_tx_mac_init: port<%d> "
29821bd6825cSml 	    "min framesize %d max framesize %d ",
29831bd6825cSml 	    nxgep->mac.minframesize,
29841bd6825cSml 	    nxgep->mac.maxframesize,
29851bd6825cSml 	    portn));
298644961713Sgirish 
29871bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
29881bd6825cSml 	    MAC_PORT_FRAME_SIZE,
29891bd6825cSml 	    nxgep->mac.minframesize,
29901bd6825cSml 	    nxgep->mac.maxframesize,
29911bd6825cSml 	    rs);
299244961713Sgirish 	if (rs != NPI_SUCCESS)
299344961713Sgirish 		goto fail;
299444961713Sgirish 
299544961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
299644961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
299752ccf843Smisaki 		    0)) != NPI_SUCCESS)
299844961713Sgirish 			goto fail;
299944961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
300044961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
30012e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
300200161856Syc 		    (portmode == PORT_10G_TN1010) ||
30031c7408c9Stc 		    (portmode == PORT_HSP_MODE) ||
30042e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
300544961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
300652ccf843Smisaki 			    XGMII_IPG_12_15, rs);
300744961713Sgirish 			if (rs != NPI_SUCCESS)
300844961713Sgirish 				goto fail;
300944961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
301044961713Sgirish 		} else {
301144961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
301252ccf843Smisaki 			    MII_GMII_IPG_12, rs);
301344961713Sgirish 			if (rs != NPI_SUCCESS)
301444961713Sgirish 				goto fail;
301544961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
301644961713Sgirish 		}
301744961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
301852ccf843Smisaki 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
301944961713Sgirish 			goto fail;
302044961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
302144961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
302244961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
302344961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
302444961713Sgirish 
302544961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
302652ccf843Smisaki 		    != NPI_SUCCESS)
302744961713Sgirish 			goto fail;
302844961713Sgirish 
302944961713Sgirish 	} else {
303044961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
303152ccf843Smisaki 		    0)) != NPI_SUCCESS)
303244961713Sgirish 			goto fail;
303344961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
303444961713Sgirish 
303544961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
303652ccf843Smisaki 		    rs);
303744961713Sgirish 		if (rs != NPI_SUCCESS)
303844961713Sgirish 			goto fail;
303944961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
304044961713Sgirish 
304144961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
304244961713Sgirish 		if (rs != NPI_SUCCESS)
304344961713Sgirish 			goto fail;
304444961713Sgirish 		nxgep->mac.pa_size = 0x7;
304544961713Sgirish 
304644961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
304752ccf843Smisaki 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
304844961713Sgirish 			goto fail;
304944961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
305044961713Sgirish 	}
305144961713Sgirish 
305244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
305352ccf843Smisaki 	    portn));
305444961713Sgirish 
305544961713Sgirish 	return (NXGE_OK);
305644961713Sgirish fail:
305744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
305852ccf843Smisaki 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
305944961713Sgirish 
306044961713Sgirish 	return (NXGE_ERROR | rs);
306144961713Sgirish }
306244961713Sgirish 
3063678453a8Sspeer 
306444961713Sgirish /* Initialize the RxMAC sub-block */
306544961713Sgirish 
306644961713Sgirish nxge_status_t
306744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
306844961713Sgirish {
306944961713Sgirish 	npi_attr_t		ap;
307044961713Sgirish 	uint32_t		i;
307144961713Sgirish 	uint16_t		hashtab_e;
307244961713Sgirish 	p_hash_filter_t		hash_filter;
307344961713Sgirish 	nxge_port_t		portt;
307444961713Sgirish 	uint8_t			portn;
307544961713Sgirish 	npi_handle_t		handle;
307644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
307744961713Sgirish 	uint16_t 		*addr16p;
307844961713Sgirish 	uint16_t 		addr0, addr1, addr2;
307944961713Sgirish 	xmac_rx_config_t	xconfig;
308044961713Sgirish 	bmac_rx_config_t	bconfig;
308144961713Sgirish 
308244961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
308344961713Sgirish 
308444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
308552ccf843Smisaki 	    portn));
308644961713Sgirish 	handle = nxgep->npi_handle;
308744961713Sgirish 	portt = nxgep->mac.porttype;
308844961713Sgirish 
308944961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
309044961713Sgirish 	addr0 = ntohs(addr16p[2]);
309144961713Sgirish 	addr1 = ntohs(addr16p[1]);
309244961713Sgirish 	addr2 = ntohs(addr16p[0]);
309344961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
309452ccf843Smisaki 	    rs);
309544961713Sgirish 
309644961713Sgirish 	if (rs != NPI_SUCCESS)
309744961713Sgirish 		goto fail;
309844961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
309944961713Sgirish 	if (rs != NPI_SUCCESS)
310044961713Sgirish 		goto fail;
310144961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
310244961713Sgirish 	if (rs != NPI_SUCCESS)
310344961713Sgirish 		goto fail;
310444961713Sgirish 
310544961713Sgirish 	/*
310644961713Sgirish 	 * Load the multicast hash filter bits.
310744961713Sgirish 	 */
310844961713Sgirish 	hash_filter = nxgep->hash_filter;
310944961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
311044961713Sgirish 		if (hash_filter != NULL) {
311144961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
311252ccf843Smisaki 			    (NMCFILTER_REGS - 1) - i];
311344961713Sgirish 		} else {
311444961713Sgirish 			hashtab_e = 0;
311544961713Sgirish 		}
311644961713Sgirish 
311744961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
311852ccf843Smisaki 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
311944961713Sgirish 			goto fail;
312044961713Sgirish 	}
312144961713Sgirish 
312244961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
312344961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
312452ccf843Smisaki 		    0)) != NPI_SUCCESS)
312544961713Sgirish 			goto fail;
312644961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
312744961713Sgirish 
312844961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
312944961713Sgirish 
313044961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
313152ccf843Smisaki 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
313252ccf843Smisaki 		    ~CFG_XMAC_RX_STRIP_CRC;
313344961713Sgirish 
313444961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
313544961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
313644961713Sgirish 
313744961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
313844961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
313944961713Sgirish 
314044961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
314144961713Sgirish 
314244961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
314352ccf843Smisaki 		    xconfig)) != NPI_SUCCESS)
314444961713Sgirish 			goto fail;
314544961713Sgirish 		nxgep->mac.rx_config = xconfig;
314644961713Sgirish 
314744961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
314844961713Sgirish 
314944961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
315052ccf843Smisaki 		    != NPI_SUCCESS)
315144961713Sgirish 			goto fail;
315244961713Sgirish 	} else {
315344961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
315444961713Sgirish 
315544961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
315652ccf843Smisaki 		    0) != NPI_SUCCESS)
315744961713Sgirish 			goto fail;
315844961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
315944961713Sgirish 
3160a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
316152ccf843Smisaki 		    ~CFG_BMAC_RX_STRIP_CRC;
316244961713Sgirish 
316344961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
316444961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
316544961713Sgirish 
316644961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
316744961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
316844961713Sgirish 
316944961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
317044961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
317152ccf843Smisaki 		    bconfig)) != NPI_SUCCESS)
317244961713Sgirish 			goto fail;
317344961713Sgirish 		nxgep->mac.rx_config = bconfig;
317444961713Sgirish 
317544961713Sgirish 		/* Always enable comparison of mac unique address */
317644961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
317752ccf843Smisaki 		    != NPI_SUCCESS)
317844961713Sgirish 			goto fail;
317944961713Sgirish 	}
318044961713Sgirish 
318144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
318252ccf843Smisaki 	    portn));
318344961713Sgirish 
318444961713Sgirish 	return (NXGE_OK);
318544961713Sgirish 
318644961713Sgirish fail:
318744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
318852ccf843Smisaki 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
318944961713Sgirish 
319044961713Sgirish 	return (NXGE_ERROR | rs);
319144961713Sgirish }
319244961713Sgirish 
319344961713Sgirish /* Enable TXMAC */
319444961713Sgirish 
319544961713Sgirish nxge_status_t
319644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
319744961713Sgirish {
319844961713Sgirish 	npi_handle_t	handle;
319944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
320044961713Sgirish 	nxge_status_t	status = NXGE_OK;
320144961713Sgirish 
320244961713Sgirish 	handle = nxgep->npi_handle;
320344961713Sgirish 
320444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
320552ccf843Smisaki 	    nxgep->mac.portnum));
320644961713Sgirish 
320744961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
320844961713Sgirish 		goto fail;
320944961713Sgirish 
321044961713Sgirish 	/* based on speed */
321144961713Sgirish 	nxgep->msg_min = ETHERMIN;
321244961713Sgirish 
321344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
321444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
321552ccf843Smisaki 		    CFG_XMAC_TX)) != NPI_SUCCESS)
321644961713Sgirish 			goto fail;
321744961713Sgirish 	} else {
321844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
321952ccf843Smisaki 		    CFG_BMAC_TX)) != NPI_SUCCESS)
322044961713Sgirish 			goto fail;
322144961713Sgirish 	}
322244961713Sgirish 
322344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
322452ccf843Smisaki 	    nxgep->mac.portnum));
322544961713Sgirish 
322644961713Sgirish 	return (NXGE_OK);
322744961713Sgirish fail:
322844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
322952ccf843Smisaki 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
323052ccf843Smisaki 	    nxgep->mac.portnum));
323144961713Sgirish 	if (rs != NPI_SUCCESS)
323244961713Sgirish 		return (NXGE_ERROR | rs);
323344961713Sgirish 	else
323444961713Sgirish 		return (status);
323544961713Sgirish }
323644961713Sgirish 
323744961713Sgirish /* Disable TXMAC */
323844961713Sgirish 
323944961713Sgirish nxge_status_t
324044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
324144961713Sgirish {
324244961713Sgirish 	npi_handle_t	handle;
324344961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
324444961713Sgirish 
3245678453a8Sspeer 	if (isLDOMguest(nxgep))
3246678453a8Sspeer 		return (NXGE_OK);
3247678453a8Sspeer 
324844961713Sgirish 	handle = nxgep->npi_handle;
324944961713Sgirish 
325044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
325152ccf843Smisaki 	    nxgep->mac.portnum));
325244961713Sgirish 
325344961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
325444961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
325552ccf843Smisaki 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
325644961713Sgirish 			goto fail;
325744961713Sgirish 	} else {
325844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
325952ccf843Smisaki 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
326044961713Sgirish 			goto fail;
326144961713Sgirish 	}
326244961713Sgirish 
326344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
326452ccf843Smisaki 	    nxgep->mac.portnum));
326544961713Sgirish 	return (NXGE_OK);
326644961713Sgirish fail:
326744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
326852ccf843Smisaki 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
326952ccf843Smisaki 	    nxgep->mac.portnum));
327044961713Sgirish 	return (NXGE_ERROR | rs);
327144961713Sgirish }
327244961713Sgirish 
327344961713Sgirish /* Enable RXMAC */
327444961713Sgirish 
327544961713Sgirish nxge_status_t
327644961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
327744961713Sgirish {
327844961713Sgirish 	npi_handle_t	handle;
327944961713Sgirish 	uint8_t 	portn;
328044961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
328144961713Sgirish 	nxge_status_t	status = NXGE_OK;
328244961713Sgirish 
3283678453a8Sspeer 	/* This is a service-domain-only activity. */
3284678453a8Sspeer 	if (isLDOMguest(nxgep))
3285678453a8Sspeer 		return (status);
3286678453a8Sspeer 
328744961713Sgirish 	handle = nxgep->npi_handle;
328844961713Sgirish 	portn = nxgep->mac.portnum;
328944961713Sgirish 
329044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
329152ccf843Smisaki 	    portn));
329244961713Sgirish 
329344961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
329444961713Sgirish 		goto fail;
329544961713Sgirish 
329644961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
329744961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
3298678453a8Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
329944961713Sgirish 			goto fail;
330044961713Sgirish 	} else {
330144961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
3302678453a8Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
330344961713Sgirish 			goto fail;
330444961713Sgirish 	}
330544961713Sgirish 
3306678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3307678453a8Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
330844961713Sgirish 
330944961713Sgirish 	return (NXGE_OK);
331044961713Sgirish fail:
331144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3312678453a8Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
331344961713Sgirish 
331444961713Sgirish 	if (rs != NPI_SUCCESS)
331544961713Sgirish 		return (NXGE_ERROR | rs);
331644961713Sgirish 	else
331744961713Sgirish 		return (status);
331844961713Sgirish }
331944961713Sgirish 
332044961713Sgirish /* Disable RXMAC */
332144961713Sgirish 
332244961713Sgirish nxge_status_t
332344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
332444961713Sgirish {
332544961713Sgirish 	npi_handle_t	handle;
332644961713Sgirish 	uint8_t		portn;
332744961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
332844961713Sgirish 
3329678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
3330678453a8Sspeer 	if (isLDOMguest(nxgep))
3331678453a8Sspeer 		return (NXGE_OK);
3332678453a8Sspeer 
333344961713Sgirish 	handle = nxgep->npi_handle;
333444961713Sgirish 	portn = nxgep->mac.portnum;
333544961713Sgirish 
333644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
333752ccf843Smisaki 	    portn));
333844961713Sgirish 
333944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
334044961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
334152ccf843Smisaki 		    CFG_XMAC_RX)) != NPI_SUCCESS)
334244961713Sgirish 			goto fail;
334344961713Sgirish 	} else {
334444961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
334552ccf843Smisaki 		    CFG_BMAC_RX)) != NPI_SUCCESS)
334644961713Sgirish 			goto fail;
334744961713Sgirish 	}
334844961713Sgirish 
334944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
335052ccf843Smisaki 	    portn));
335144961713Sgirish 	return (NXGE_OK);
335244961713Sgirish fail:
335344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
335452ccf843Smisaki 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
335544961713Sgirish 
335644961713Sgirish 	return (NXGE_ERROR | rs);
335744961713Sgirish }
335844961713Sgirish 
335944961713Sgirish /* Reset TXMAC */
336044961713Sgirish 
336144961713Sgirish nxge_status_t
336244961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
336344961713Sgirish {
336444961713Sgirish 	npi_handle_t	handle;
336544961713Sgirish 	uint8_t		portn;
336644961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
336744961713Sgirish 
336844961713Sgirish 	handle = nxgep->npi_handle;
336944961713Sgirish 	portn = nxgep->mac.portnum;
337044961713Sgirish 
337144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
337252ccf843Smisaki 	    portn));
337344961713Sgirish 
337444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
337544961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
337644961713Sgirish 		    != NPI_SUCCESS)
337744961713Sgirish 			goto fail;
337844961713Sgirish 	} else {
337944961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
338052ccf843Smisaki 		    != NPI_SUCCESS)
338144961713Sgirish 			goto fail;
338244961713Sgirish 	}
338344961713Sgirish 
338444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
338552ccf843Smisaki 	    portn));
338644961713Sgirish 
338744961713Sgirish 	return (NXGE_OK);
338844961713Sgirish fail:
338944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
339052ccf843Smisaki 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
339144961713Sgirish 
339244961713Sgirish 	return (NXGE_ERROR | rs);
339344961713Sgirish }
339444961713Sgirish 
339544961713Sgirish /* Reset RXMAC */
339644961713Sgirish 
339744961713Sgirish nxge_status_t
339844961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
339944961713Sgirish {
340044961713Sgirish 	npi_handle_t	handle;
340144961713Sgirish 	uint8_t		portn;
340244961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
340344961713Sgirish 
340444961713Sgirish 	handle = nxgep->npi_handle;
340544961713Sgirish 	portn = nxgep->mac.portnum;
340644961713Sgirish 
340744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
340852ccf843Smisaki 	    portn));
340944961713Sgirish 
341044961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
341144961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
341244961713Sgirish 		    != NPI_SUCCESS)
341344961713Sgirish 		goto fail;
341444961713Sgirish 	} else {
341544961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
341652ccf843Smisaki 		    != NPI_SUCCESS)
341744961713Sgirish 		goto fail;
341844961713Sgirish 	}
341944961713Sgirish 
342044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
342152ccf843Smisaki 	    portn));
342244961713Sgirish 
342359ac0c16Sdavemq 	return (NXGE_OK);
342459ac0c16Sdavemq fail:
342559ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
342652ccf843Smisaki 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
342759ac0c16Sdavemq 	return (NXGE_ERROR | rs);
342859ac0c16Sdavemq }
342959ac0c16Sdavemq 
343059ac0c16Sdavemq /* 10G fiber link interrupt start routine */
343159ac0c16Sdavemq 
343259ac0c16Sdavemq static nxge_status_t
343359ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
343459ac0c16Sdavemq {
343559ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
343659ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
343759ac0c16Sdavemq 
343859ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
343959ac0c16Sdavemq 
344059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
344159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
344259ac0c16Sdavemq 	else
344359ac0c16Sdavemq 		return (NXGE_OK);
344459ac0c16Sdavemq }
344559ac0c16Sdavemq 
344659ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
344759ac0c16Sdavemq 
344859ac0c16Sdavemq static nxge_status_t
344959ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
345059ac0c16Sdavemq {
345159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
345259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
345359ac0c16Sdavemq 
345459ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
345559ac0c16Sdavemq 
345659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
345759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
345859ac0c16Sdavemq 	else
345959ac0c16Sdavemq 		return (NXGE_OK);
346059ac0c16Sdavemq }
346159ac0c16Sdavemq 
346259ac0c16Sdavemq /* 1G fiber link interrupt start routine */
346359ac0c16Sdavemq 
346459ac0c16Sdavemq static nxge_status_t
346559ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
346659ac0c16Sdavemq {
346759ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
346859ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
346959ac0c16Sdavemq 
347059ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
347159ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
347259ac0c16Sdavemq 		return (NXGE_ERROR | rs);
347359ac0c16Sdavemq 	else
347459ac0c16Sdavemq 		return (NXGE_OK);
347559ac0c16Sdavemq }
347659ac0c16Sdavemq 
347759ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
347859ac0c16Sdavemq 
347959ac0c16Sdavemq static nxge_status_t
348059ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
348159ac0c16Sdavemq {
348259ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
348359ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
348459ac0c16Sdavemq 
348559ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
348659ac0c16Sdavemq 
348759ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
348859ac0c16Sdavemq 		return (NXGE_ERROR | rs);
348959ac0c16Sdavemq 	else
349059ac0c16Sdavemq 		return (NXGE_OK);
349159ac0c16Sdavemq }
349259ac0c16Sdavemq 
349359ac0c16Sdavemq /* 1G copper link interrupt start routine */
349459ac0c16Sdavemq 
349559ac0c16Sdavemq static nxge_status_t
349659ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
349759ac0c16Sdavemq {
349859ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
349959ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
350059ac0c16Sdavemq 
350159ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
35026b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
350359ac0c16Sdavemq 
350459ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
350559ac0c16Sdavemq 		return (NXGE_ERROR | rs);
350659ac0c16Sdavemq 	else
350759ac0c16Sdavemq 		return (NXGE_OK);
350844961713Sgirish }
350944961713Sgirish 
351059ac0c16Sdavemq /* 1G copper link interrupt stop routine */
351159ac0c16Sdavemq 
351259ac0c16Sdavemq static nxge_status_t
351359ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
351459ac0c16Sdavemq {
351559ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
351659ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
351759ac0c16Sdavemq 
351859ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
351959ac0c16Sdavemq 
352059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
352159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
352259ac0c16Sdavemq 	else
352359ac0c16Sdavemq 		return (NXGE_OK);
352459ac0c16Sdavemq }
352544961713Sgirish 
352659ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
352744961713Sgirish 
352844961713Sgirish nxge_status_t
352944961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
353044961713Sgirish {
353159ac0c16Sdavemq 	uint8_t		portn;
353259ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
353344961713Sgirish 
353444961713Sgirish 	portn = nxgep->mac.portnum;
353544961713Sgirish 
353644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
353759ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
353859ac0c16Sdavemq 		return (NXGE_OK);
353944961713Sgirish 
354059ac0c16Sdavemq 	if (enable == LINK_INTR_START)
354159ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
354259ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
354359ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
354459ac0c16Sdavemq 	if (status != NXGE_OK)
354559ac0c16Sdavemq 		goto fail;
354644961713Sgirish 
354744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
354844961713Sgirish 
354944961713Sgirish 	return (NXGE_OK);
355044961713Sgirish fail:
355144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
355252ccf843Smisaki 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
355344961713Sgirish 
355459ac0c16Sdavemq 	return (status);
355544961713Sgirish }
355644961713Sgirish 
355744961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
355844961713Sgirish 
355944961713Sgirish nxge_status_t
356044961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
356144961713Sgirish {
356244961713Sgirish 	p_nxge_param_t	param_arr;
356344961713Sgirish 	p_nxge_stats_t	statsp;
356444961713Sgirish 	uint8_t		xcvr_portn;
356544961713Sgirish 	p_mii_regs_t	mii_regs;
356644961713Sgirish 	mii_bmcr_t	bmcr;
356744961713Sgirish 	mii_bmsr_t	bmsr;
356844961713Sgirish 	mii_anar_t	anar;
356944961713Sgirish 	mii_gcr_t	gcr;
357044961713Sgirish 	mii_esr_t	esr;
357144961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
357244961713Sgirish 	int		status = NXGE_OK;
357344961713Sgirish 
357444961713Sgirish 	uint_t delay;
357544961713Sgirish 
357644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
357744961713Sgirish 
357844961713Sgirish 	param_arr = nxgep->param_arr;
357944961713Sgirish 	statsp = nxgep->statsp;
358044961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
358144961713Sgirish 
358244961713Sgirish 	mii_regs = NULL;
358344961713Sgirish 
358444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
358552ccf843Smisaki 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
358644961713Sgirish 
3587d81011f0Ssbehera 	/*
3588d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
3589d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
3590d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
3591d81011f0Ssbehera 	 */
3592d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
3593d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3594d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
3595d81011f0Ssbehera 	}
3596d81011f0Ssbehera 
359744961713Sgirish 	/*
359844961713Sgirish 	 * Reset the transceiver.
359944961713Sgirish 	 */
360044961713Sgirish 	delay = 0;
360144961713Sgirish 	bmcr.value = 0;
360244961713Sgirish 	bmcr.bits.reset = 1;
360344961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3604adfcba55Sjoycey #if defined(__i386)
360552ccf843Smisaki 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
3606adfcba55Sjoycey #else
360752ccf843Smisaki 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
3608adfcba55Sjoycey #endif
360952ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
361044961713Sgirish 		goto fail;
361144961713Sgirish 	do {
361244961713Sgirish 		drv_usecwait(500);
361344961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3614adfcba55Sjoycey #if defined(__i386)
361552ccf843Smisaki 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
3616adfcba55Sjoycey #else
361752ccf843Smisaki 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
3618adfcba55Sjoycey #endif
361952ccf843Smisaki 		    &bmcr.value)) != NXGE_OK)
362044961713Sgirish 			goto fail;
362144961713Sgirish 		delay++;
362244961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
362344961713Sgirish 	if (delay == 1000) {
362444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
362544961713Sgirish 		goto fail;
362644961713Sgirish 	}
362744961713Sgirish 
362844961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3629adfcba55Sjoycey #if defined(__i386)
363052ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3631adfcba55Sjoycey #else
363252ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3633adfcba55Sjoycey #endif
363452ccf843Smisaki 	    &bmsr.value)) != NXGE_OK)
363544961713Sgirish 		goto fail;
363644961713Sgirish 
363744961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
363844961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
363944961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
364044961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
364144961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
364244961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
364344961713Sgirish 
364444961713Sgirish 	/*
364558324dfcSspeer 	 * Initialize the xcvr statistics.
364644961713Sgirish 	 */
364744961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
364844961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
364944961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
365044961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
365144961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
365244961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
365344961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
365444961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
365544961713Sgirish 
365644961713Sgirish 	/*
365700161856Syc 	 * Initialize the xcvr advertised capability statistics.
365844961713Sgirish 	 */
365944961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
366044961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
366144961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
366244961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
366344961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
366444961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
366544961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
366644961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
366744961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
366852ccf843Smisaki 	    param_arr[param_anar_asmpause].value;
366944961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
367044961713Sgirish 
367144961713Sgirish 
367244961713Sgirish 	/*
367344961713Sgirish 	 * Check for extended status just in case we're
367444961713Sgirish 	 * running a Gigibit phy.
367544961713Sgirish 	 */
367644961713Sgirish 	if (bmsr.bits.extend_status) {
367744961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3678adfcba55Sjoycey #if defined(__i386)
367952ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->esr),
3680adfcba55Sjoycey #else
368152ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->esr),
3682adfcba55Sjoycey #endif
368352ccf843Smisaki 		    &esr.value)) != NXGE_OK)
368444961713Sgirish 			goto fail;
368552ccf843Smisaki 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
368644961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
368744961713Sgirish 
368844961713Sgirish 		statsp->mac_stats.cap_1000fdx =
368952ccf843Smisaki 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
369044961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
369144961713Sgirish 	} else {
369244961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
369344961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
369444961713Sgirish 	}
369544961713Sgirish 
369644961713Sgirish 	/*
369744961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
369844961713Sgirish 	 */
369944961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
370044961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
370144961713Sgirish 
370244961713Sgirish 	/*
370300161856Syc 	 * Initialize the link statistics.
370444961713Sgirish 	 */
370544961713Sgirish 	statsp->mac_stats.link_T4 = 0;
370644961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
370744961713Sgirish 	statsp->mac_stats.link_pause = 0;
370844961713Sgirish 	statsp->mac_stats.link_speed = 0;
370944961713Sgirish 	statsp->mac_stats.link_duplex = 0;
371044961713Sgirish 	statsp->mac_stats.link_up = 0;
371144961713Sgirish 
371244961713Sgirish 	/*
371344961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
371444961713Sgirish 	 */
371544961713Sgirish 	bmcr.value = 0;
371644961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3717adfcba55Sjoycey #if defined(__i386)
371852ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3719adfcba55Sjoycey #else
372052ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3721adfcba55Sjoycey #endif
372252ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
372344961713Sgirish 		goto fail;
372444961713Sgirish 
372544961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
372652ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
372744961713Sgirish 		bmcr.bits.loopback = 1;
372844961713Sgirish 		bmcr.bits.enable_autoneg = 0;
372944961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
373044961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
373144961713Sgirish 		bmcr.bits.duplex_mode = 1;
373244961713Sgirish 		param_arr[param_autoneg].value = 0;
373344961713Sgirish 	} else {
373444961713Sgirish 		bmcr.bits.loopback = 0;
373544961713Sgirish 	}
373644961713Sgirish 
373744961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
373852ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
373952ccf843Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
374044961713Sgirish 		param_arr[param_autoneg].value = 0;
374144961713Sgirish 		bcm5464r_aux.value = 0;
374244961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
374344961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
374444961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
374552ccf843Smisaki 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
374644961713Sgirish 			goto fail;
374744961713Sgirish 	}
374844961713Sgirish 
374900161856Syc 	/* If auto-negotiation is desired */
375044961713Sgirish 	if (param_arr[param_autoneg].value) {
375144961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
375252ccf843Smisaki 		    "Restarting Auto-negotiation."));
375344961713Sgirish 		/*
375444961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
375544961713Sgirish 		 */
375644961713Sgirish 		anar.value = 0;
375744961713Sgirish 		anar.bits.selector = 1;
375844961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
375944961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
376044961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
376144961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
376244961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
376344961713Sgirish 		anar.bits.cap_asmpause = 0;
376444961713Sgirish 		anar.bits.cap_pause = 0;
376544961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
376652ccf843Smisaki 		    param_arr[param_anar_100fdx].value ||
376752ccf843Smisaki 		    param_arr[param_anar_10fdx].value) {
376844961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
376944961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
377044961713Sgirish 		}
377144961713Sgirish 
377200161856Syc 		/* Write to the auto-negotiation advertisement register */
377344961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3774adfcba55Sjoycey #if defined(__i386)
377552ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->anar),
3776adfcba55Sjoycey #else
377752ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->anar),
3778adfcba55Sjoycey #endif
377952ccf843Smisaki 		    anar.value)) != NXGE_OK)
378044961713Sgirish 			goto fail;
378144961713Sgirish 		if (bmsr.bits.extend_status) {
378244961713Sgirish 			gcr.value = 0;
378344961713Sgirish 			gcr.bits.ms_mode_en =
378452ccf843Smisaki 			    param_arr[param_master_cfg_enable].value;
378544961713Sgirish 			gcr.bits.master =
378652ccf843Smisaki 			    param_arr[param_master_cfg_value].value;
378744961713Sgirish 			gcr.bits.link_1000fdx =
378852ccf843Smisaki 			    param_arr[param_anar_1000fdx].value;
378944961713Sgirish 			gcr.bits.link_1000hdx =
379052ccf843Smisaki 			    param_arr[param_anar_1000hdx].value;
379144961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3792adfcba55Sjoycey #if defined(__i386)
379352ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
3794adfcba55Sjoycey #else
379552ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
3796adfcba55Sjoycey #endif
379752ccf843Smisaki 			    gcr.value)) != NXGE_OK)
379844961713Sgirish 				goto fail;
379944961713Sgirish 		}
380044961713Sgirish 
380144961713Sgirish 		bmcr.bits.enable_autoneg = 1;
380244961713Sgirish 		bmcr.bits.restart_autoneg = 1;
380344961713Sgirish 
380444961713Sgirish 	} else {
380544961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
380644961713Sgirish 		bmcr.bits.speed_1000_sel =
380752ccf843Smisaki 		    param_arr[param_anar_1000fdx].value |
380852ccf843Smisaki 		    param_arr[param_anar_1000hdx].value;
380944961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
381052ccf843Smisaki 		    (param_arr[param_anar_100fdx].value |
381152ccf843Smisaki 		    param_arr[param_anar_100hdx].value);
381200161856Syc 
381300161856Syc 		/* Force to 1G */
381444961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
381544961713Sgirish 			statsp->mac_stats.link_speed = 1000;
381644961713Sgirish 			gcr.value = 0;
381744961713Sgirish 			gcr.bits.ms_mode_en =
381852ccf843Smisaki 			    param_arr[param_master_cfg_enable].value;
381944961713Sgirish 			gcr.bits.master =
382052ccf843Smisaki 			    param_arr[param_master_cfg_value].value;
382144961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
3822adfcba55Sjoycey #if defined(__i386)
382352ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
3824adfcba55Sjoycey #else
382552ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
3826adfcba55Sjoycey #endif
382752ccf843Smisaki 			    gcr.value)) != NXGE_OK)
382844961713Sgirish 				goto fail;
382944961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
383044961713Sgirish 				bmcr.bits.duplex_mode = 1;
383144961713Sgirish 				statsp->mac_stats.link_duplex = 2;
383244961713Sgirish 			} else
383344961713Sgirish 				statsp->mac_stats.link_duplex = 1;
383400161856Syc 
383500161856Syc 		/* Force to 100M */
383644961713Sgirish 		} else if (bmcr.bits.speed_sel) {
383744961713Sgirish 			statsp->mac_stats.link_speed = 100;
383844961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
383944961713Sgirish 				bmcr.bits.duplex_mode = 1;
384044961713Sgirish 				statsp->mac_stats.link_duplex = 2;
384144961713Sgirish 			} else
384244961713Sgirish 				statsp->mac_stats.link_duplex = 1;
384300161856Syc 
384400161856Syc 		/* Force to 10M */
384544961713Sgirish 		} else {
384644961713Sgirish 			statsp->mac_stats.link_speed = 10;
384744961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
384844961713Sgirish 				bmcr.bits.duplex_mode = 1;
384944961713Sgirish 				statsp->mac_stats.link_duplex = 2;
385044961713Sgirish 			} else
385144961713Sgirish 				statsp->mac_stats.link_duplex = 1;
385244961713Sgirish 		}
385344961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
385444961713Sgirish 			statsp->mac_stats.link_asmpause =
385552ccf843Smisaki 			    statsp->mac_stats.cap_asmpause;
385644961713Sgirish 			statsp->mac_stats.link_pause =
385752ccf843Smisaki 			    statsp->mac_stats.cap_pause;
385844961713Sgirish 		}
385944961713Sgirish 
386044961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
386152ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
386252ccf843Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
386344961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
386444961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
386544961713Sgirish 				gcr.value = 0;
386644961713Sgirish 				gcr.bits.ms_mode_en = 1;
386744961713Sgirish 				gcr.bits.master = 1;
386844961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
3869adfcba55Sjoycey #if defined(__i386)
387052ccf843Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
3871adfcba55Sjoycey #else
387252ccf843Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
3873adfcba55Sjoycey #endif
387452ccf843Smisaki 				    gcr.value)) != NXGE_OK)
387544961713Sgirish 					goto fail;
387644961713Sgirish 				bmcr.value = 0;
387744961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
387844961713Sgirish 				statsp->mac_stats.link_speed = 1000;
387944961713Sgirish 			} else if (statsp->port_stats.lb_mode
388044961713Sgirish 			    == nxge_lb_ext100) {
388144961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
388244961713Sgirish 				bmcr.value = 0;
388344961713Sgirish 				bmcr.bits.speed_sel = 1;
388444961713Sgirish 				bmcr.bits.duplex_mode = 1;
388544961713Sgirish 				statsp->mac_stats.link_speed = 100;
388644961713Sgirish 			} else if (statsp->port_stats.lb_mode
388744961713Sgirish 			    == nxge_lb_ext10) {
388844961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
388944961713Sgirish 				bmcr.value = 0;
389044961713Sgirish 				bmcr.bits.duplex_mode = 1;
389144961713Sgirish 				statsp->mac_stats.link_speed = 10;
389244961713Sgirish 			}
389344961713Sgirish 		}
389444961713Sgirish 	}
389544961713Sgirish 
389644961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3897adfcba55Sjoycey #if defined(__i386)
389852ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3899adfcba55Sjoycey #else
390052ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3901adfcba55Sjoycey #endif
390252ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
390344961713Sgirish 		goto fail;
390444961713Sgirish 
390544961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3906adfcba55Sjoycey #if defined(__i386)
390752ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
3908adfcba55Sjoycey #else
390952ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
3910adfcba55Sjoycey #endif
391152ccf843Smisaki 	    &bmcr.value)) != NXGE_OK)
391244961713Sgirish 		goto fail;
391344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
391444961713Sgirish 
391544961713Sgirish 	/*
391644961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
391744961713Sgirish 	 */
391844961713Sgirish 	nxgep->soft_bmsr.value = 0;
391944961713Sgirish 
392044961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3921adfcba55Sjoycey #if defined(__i386)
392252ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
3923adfcba55Sjoycey #else
392452ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
3925adfcba55Sjoycey #endif
392652ccf843Smisaki 	    &nxgep->bmsr.value)) != NXGE_OK)
392744961713Sgirish 		goto fail;
392844961713Sgirish 
392944961713Sgirish 	statsp->mac_stats.xcvr_inits++;
393044961713Sgirish 	nxgep->bmsr.value = 0;
393144961713Sgirish 
393244961713Sgirish fail:
393344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
393452ccf843Smisaki 	    "<== nxge_mii_xcvr_init status 0x%x", status));
393544961713Sgirish 	return (status);
393644961713Sgirish }
393744961713Sgirish 
3938d81011f0Ssbehera nxge_status_t
3939d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
3940d81011f0Ssbehera {
3941d81011f0Ssbehera 	p_nxge_param_t	param_arr;
3942d81011f0Ssbehera 	p_nxge_stats_t	statsp;
3943d81011f0Ssbehera 	uint8_t		xcvr_portn;
3944d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
3945d81011f0Ssbehera 	mii_bmcr_t	bmcr;
3946d81011f0Ssbehera 	mii_bmsr_t	bmsr;
3947d81011f0Ssbehera 	mii_gcr_t	gcr;
3948d81011f0Ssbehera 	mii_esr_t	esr;
3949d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
3950d81011f0Ssbehera 	int		status = NXGE_OK;
3951d81011f0Ssbehera 
3952d81011f0Ssbehera 	uint_t delay;
3953d81011f0Ssbehera 
3954d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
3955d81011f0Ssbehera 
3956d81011f0Ssbehera 	param_arr = nxgep->param_arr;
3957d81011f0Ssbehera 	statsp = nxgep->statsp;
3958d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
3959d81011f0Ssbehera 
3960d81011f0Ssbehera 	mii_regs = NULL;
3961d81011f0Ssbehera 
3962d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3963d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
3964d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
3965d81011f0Ssbehera 
3966d81011f0Ssbehera 	/*
3967d81011f0Ssbehera 	 * Reset the transceiver.
3968d81011f0Ssbehera 	 */
3969d81011f0Ssbehera 	delay = 0;
3970d81011f0Ssbehera 	bmcr.value = 0;
3971d81011f0Ssbehera 	bmcr.bits.reset = 1;
3972d81011f0Ssbehera 
3973d81011f0Ssbehera #if defined(__i386)
3974d81011f0Ssbehera 
3975d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3976d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3977d81011f0Ssbehera 		goto fail;
3978d81011f0Ssbehera #else
3979d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3980d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3981d81011f0Ssbehera 		goto fail;
3982d81011f0Ssbehera #endif
3983d81011f0Ssbehera 	do {
3984d81011f0Ssbehera 		drv_usecwait(500);
3985d81011f0Ssbehera #if defined(__i386)
3986d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3987d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
3988d81011f0Ssbehera 		    != NXGE_OK)
3989d81011f0Ssbehera 			goto fail;
3990d81011f0Ssbehera #else
3991d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3992d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
3993d81011f0Ssbehera 		    != NXGE_OK)
3994d81011f0Ssbehera 			goto fail;
3995d81011f0Ssbehera #endif
3996d81011f0Ssbehera 		delay++;
3997d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
3998d81011f0Ssbehera 	if (delay == 1000) {
3999d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4000d81011f0Ssbehera 		goto fail;
4001d81011f0Ssbehera 	}
4002d81011f0Ssbehera 
4003d81011f0Ssbehera #if defined(__i386)
4004d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4005d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4006d81011f0Ssbehera 		goto fail;
4007d81011f0Ssbehera #else
4008d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4009d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4010d81011f0Ssbehera 		goto fail;
4011d81011f0Ssbehera #endif
4012d81011f0Ssbehera 
4013d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4014d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
4015d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
4016d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
4017d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
4018d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
4019d81011f0Ssbehera 
4020d81011f0Ssbehera 	/*
4021d81011f0Ssbehera 	 * Initialize the xcvr statistics.
4022d81011f0Ssbehera 	 */
4023d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4024d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
4025d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
4026d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
4027d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
4028d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
4029d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4030d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4031d81011f0Ssbehera 
4032d81011f0Ssbehera 	/*
4033d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
4034d81011f0Ssbehera 	 */
4035d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4036d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4037d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4038d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4039d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4040d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4041d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4042d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4043d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
4044d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
4045d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4046d81011f0Ssbehera 
4047d81011f0Ssbehera 	/*
4048d81011f0Ssbehera 	 * Check for extended status just in case we're
4049d81011f0Ssbehera 	 * running a Gigibit phy.
4050d81011f0Ssbehera 	 */
4051d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
4052d81011f0Ssbehera #if defined(__i386)
4053d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4054d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
4055d81011f0Ssbehera 		    NXGE_OK)
4056d81011f0Ssbehera 			goto fail;
4057d81011f0Ssbehera #else
4058d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4059d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
4060d81011f0Ssbehera 		    NXGE_OK)
4061d81011f0Ssbehera 			goto fail;
4062d81011f0Ssbehera #endif
4063d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
4064d81011f0Ssbehera 		    esr.bits.link_1000fdx;
4065d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4066d81011f0Ssbehera 
4067d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
4068d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4069d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
4070d81011f0Ssbehera 	} else {
4071d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
4072d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4073d81011f0Ssbehera 	}
4074d81011f0Ssbehera 
4075d81011f0Ssbehera 	/*
4076d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
4077d81011f0Ssbehera 	 */
4078d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4079d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4080d81011f0Ssbehera 
4081d81011f0Ssbehera 	/*
4082d81011f0Ssbehera 	 * Initialize the link statistics.
4083d81011f0Ssbehera 	 */
4084d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
4085d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
4086d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
4087d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
4088d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
4089d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
4090d81011f0Ssbehera 
4091d81011f0Ssbehera 	/*
4092d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
4093d81011f0Ssbehera 	 */
4094d81011f0Ssbehera 	bmcr.value = 0;
4095d81011f0Ssbehera #if defined(__i386)
4096d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4097d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4098d81011f0Ssbehera 		goto fail;
4099d81011f0Ssbehera #else
4100d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4101d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4102d81011f0Ssbehera 		goto fail;
4103d81011f0Ssbehera #endif
4104d81011f0Ssbehera 
4105d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4106d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4107d81011f0Ssbehera 		bmcr.bits.loopback = 1;
4108d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
4109d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4110d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
4111d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
4112d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4113d81011f0Ssbehera 	} else {
4114d81011f0Ssbehera 		bmcr.bits.loopback = 0;
4115d81011f0Ssbehera 	}
4116d81011f0Ssbehera 
4117d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
4118d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4119d81011f0Ssbehera 		bcm5464r_aux.value = 0;
4120d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
4121d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
4122d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4123d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4124d81011f0Ssbehera 			goto fail;
4125d81011f0Ssbehera 	}
4126d81011f0Ssbehera 
4127d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
4128d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
4129d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
4130d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
4131d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
4132d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
4133d81011f0Ssbehera 
4134d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
4135d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
4136d81011f0Ssbehera 		gcr.value = 0;
4137d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
4138d81011f0Ssbehera 		gcr.bits.master = 1;
4139d81011f0Ssbehera #if defined(__i386)
4140d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4141d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
4142d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4143d81011f0Ssbehera 			goto fail;
4144d81011f0Ssbehera #else
4145d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4146d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
4147d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4148d81011f0Ssbehera 			goto fail;
4149d81011f0Ssbehera #endif
4150d81011f0Ssbehera 		bmcr.value = 0;
4151d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
4152d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
4153d81011f0Ssbehera 	}
4154d81011f0Ssbehera 
4155d81011f0Ssbehera #if defined(__i386)
4156d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4157d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4158d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4159d81011f0Ssbehera 		goto fail;
4160d81011f0Ssbehera #else
4161d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4162d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4163d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4164d81011f0Ssbehera 		goto fail;
4165d81011f0Ssbehera #endif
4166d81011f0Ssbehera 
4167d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4168d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
4169d81011f0Ssbehera 	    bmcr.value));
4170d81011f0Ssbehera 
4171d81011f0Ssbehera #if defined(__i386)
4172d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4173d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4174d81011f0Ssbehera 		goto fail;
4175d81011f0Ssbehera #else
4176d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4177d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4178d81011f0Ssbehera 		goto fail;
4179d81011f0Ssbehera #endif
4180d81011f0Ssbehera 
4181d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4182d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
4183d81011f0Ssbehera 
4184d81011f0Ssbehera 	/*
4185d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
4186d81011f0Ssbehera 	 */
4187d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
4188d81011f0Ssbehera #if defined(__i386)
4189d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4190d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4191d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4192d81011f0Ssbehera 		goto fail;
4193d81011f0Ssbehera #else
4194d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4195d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4196d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4197d81011f0Ssbehera 		goto fail;
4198d81011f0Ssbehera #endif
4199d81011f0Ssbehera 
4200d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
4201d81011f0Ssbehera 	nxgep->bmsr.value = 0;
4202d81011f0Ssbehera 
4203d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4204d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4205d81011f0Ssbehera 	return (status);
4206d81011f0Ssbehera 
4207d81011f0Ssbehera fail:
4208d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4209d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4210d81011f0Ssbehera 	return (status);
4211d81011f0Ssbehera }
4212d81011f0Ssbehera 
421344961713Sgirish /* Read from a MII compliant register */
421444961713Sgirish 
421544961713Sgirish nxge_status_t
421644961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
421744961713Sgirish 		uint16_t *value)
421844961713Sgirish {
421944961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
422044961713Sgirish 
422144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
422252ccf843Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
422344961713Sgirish 
4224321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
422544961713Sgirish 
4226d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4227d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
422844961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
422952ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
423044961713Sgirish 			goto fail;
42312e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42322e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
423344961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
423452ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
423544961713Sgirish 			goto fail;
423644961713Sgirish 	} else
423744961713Sgirish 		goto fail;
423844961713Sgirish 
4239321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
424044961713Sgirish 
424144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
424252ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
424344961713Sgirish 	return (NXGE_OK);
424444961713Sgirish fail:
4245321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
424644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
424752ccf843Smisaki 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
424844961713Sgirish 
424944961713Sgirish 	return (NXGE_ERROR | rs);
425044961713Sgirish }
425144961713Sgirish 
425244961713Sgirish /* Write to a MII compliant Register */
425344961713Sgirish 
425444961713Sgirish nxge_status_t
425544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
425644961713Sgirish 		uint16_t value)
425744961713Sgirish {
425844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
425944961713Sgirish 
426044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
426152ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
426244961713Sgirish 
4263321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
426444961713Sgirish 
4265d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4266d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
426744961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
426852ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
426944961713Sgirish 			goto fail;
42702e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42712e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
427244961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
427352ccf843Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
427444961713Sgirish 			goto fail;
427544961713Sgirish 	} else
427644961713Sgirish 		goto fail;
427744961713Sgirish 
4278321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
427944961713Sgirish 
428044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
428152ccf843Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
428244961713Sgirish 	return (NXGE_OK);
428344961713Sgirish fail:
4284321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
428544961713Sgirish 
428644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
428752ccf843Smisaki 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
428844961713Sgirish 
428944961713Sgirish 	return (NXGE_ERROR | rs);
429044961713Sgirish }
429144961713Sgirish 
429200161856Syc /*
429300161856Syc  * Perform write to Clause45 serdes / transceiver device
429400161856Syc  * Arguments:
429500161856Syc  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
429600161856Syc  *			number if nxge_mdio_write is used for accessing the
429700161856Syc  *			internal LSIL serdes. Otherwise PHYAD is different
429800161856Syc  * 			for different platforms.
429900161856Syc  *	device:		With each PHYAD, the driver can use MDIO to control
430000161856Syc  *			multiple devices inside the PHY, here "device" is an
430100161856Syc  *			MMD (MDIO managable device).
430200161856Syc  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
430300161856Syc  *			the register which the driver will write value to.
430400161856Syc  *	value:		The register value will be filled in.
430500161856Syc  */
430644961713Sgirish nxge_status_t
430744961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
430844961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
430944961713Sgirish {
431044961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
431144961713Sgirish 
431244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
431352ccf843Smisaki 	    xcvr_portn));
431444961713Sgirish 
431553560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
431644961713Sgirish 
431744961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
431852ccf843Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
431944961713Sgirish 		goto fail;
432044961713Sgirish 
432153560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
432244961713Sgirish 
432344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
432452ccf843Smisaki 	    xcvr_portn));
432544961713Sgirish 	return (NXGE_OK);
432644961713Sgirish fail:
432753560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
432844961713Sgirish 
432944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
433052ccf843Smisaki 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
433144961713Sgirish 
433244961713Sgirish 	return (NXGE_ERROR | rs);
433344961713Sgirish }
433444961713Sgirish 
433544961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
433644961713Sgirish 
433744961713Sgirish nxge_status_t
433844961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
433944961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
434044961713Sgirish {
434144961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
434244961713Sgirish 
434344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
434452ccf843Smisaki 	    xcvr_portn));
434544961713Sgirish 
434653560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
434744961713Sgirish 
434844961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
434952ccf843Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
435044961713Sgirish 		goto fail;
435144961713Sgirish 
435253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
435344961713Sgirish 
435444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
435552ccf843Smisaki 	    xcvr_portn));
435644961713Sgirish 	return (NXGE_OK);
435744961713Sgirish fail:
435853560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
435944961713Sgirish 
436044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
436152ccf843Smisaki 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
436244961713Sgirish 
436344961713Sgirish 	return (NXGE_ERROR | rs);
436444961713Sgirish }
436544961713Sgirish 
436644961713Sgirish 
436744961713Sgirish /* Check MII to see if there is any link status change */
436844961713Sgirish 
436944961713Sgirish nxge_status_t
4370a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
4371a3c5bd6dSspeer 		nxge_link_state_t *link_up)
437244961713Sgirish {
437344961713Sgirish 	p_nxge_param_t	param_arr;
437444961713Sgirish 	p_nxge_stats_t	statsp;
437544961713Sgirish 	p_mii_regs_t	mii_regs;
437644961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
437744961713Sgirish 	mii_anar_t	anar;
437844961713Sgirish 	mii_anlpar_t	anlpar;
437944961713Sgirish 	mii_anar_t	an_common;
438044961713Sgirish 	mii_aner_t	aner;
438144961713Sgirish 	mii_gsr_t	gsr;
438244961713Sgirish 	nxge_status_t	status = NXGE_OK;
438344961713Sgirish 
438444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
438544961713Sgirish 
438644961713Sgirish 	mii_regs = NULL;
438744961713Sgirish 	param_arr = nxgep->param_arr;
438844961713Sgirish 	statsp = nxgep->statsp;
438944961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
4390a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
439144961713Sgirish 
4392d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4393d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
4394d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
4395d81011f0Ssbehera 
439644961713Sgirish 	if (bmsr_ints.bits.link_status) {
4397d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4398d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
4399d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
440044961713Sgirish 		if (bmsr.bits.link_status) {
440144961713Sgirish 			soft_bmsr->bits.link_status = 1;
4402d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4403d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
4404d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
440544961713Sgirish 		} else {
440644961713Sgirish 			statsp->mac_stats.link_up = 0;
440744961713Sgirish 			soft_bmsr->bits.link_status = 0;
440844961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
440952ccf843Smisaki 			    "Link down cable problem"));
4410a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
441144961713Sgirish 		}
441244961713Sgirish 	}
441344961713Sgirish 
4414d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
4415d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
441644961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
441744961713Sgirish 			if (bmsr.bits.auto_neg_complete)
441844961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
441944961713Sgirish 			else
442044961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
442144961713Sgirish 		}
442244961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
442344961713Sgirish 			statsp->mac_stats.link_T4 = 0;
442444961713Sgirish 			statsp->mac_stats.link_speed = 0;
442544961713Sgirish 			statsp->mac_stats.link_duplex = 0;
442644961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
442744961713Sgirish 			statsp->mac_stats.link_pause = 0;
442844961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
442944961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
443044961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
443144961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
443244961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
443344961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
443444961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
443544961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
443644961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
443744961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
443844961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
443944961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
444044961713Sgirish 		}
444144961713Sgirish 	} else
444244961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
444344961713Sgirish 
444444961713Sgirish 	if ((bmsr_ints.bits.link_status ||
444552ccf843Smisaki 	    bmsr_ints.bits.auto_neg_complete) &&
444652ccf843Smisaki 	    soft_bmsr->bits.link_status &&
444752ccf843Smisaki 	    soft_bmsr->bits.auto_neg_complete) {
444844961713Sgirish 		statsp->mac_stats.link_up = 1;
4449d81011f0Ssbehera 
4450d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4451d81011f0Ssbehera 		    "==> nxge_mii_check "
4452d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
4453d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
4454d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
4455d81011f0Ssbehera 
4456d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4457d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
445844961713Sgirish 			if ((status = nxge_mii_read(nxgep,
445952ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4460adfcba55Sjoycey #if defined(__i386)
446152ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anar),
4462adfcba55Sjoycey #else
446352ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anar),
4464adfcba55Sjoycey #endif
446552ccf843Smisaki 			    &anar.value)) != NXGE_OK)
446644961713Sgirish 				goto fail;
446744961713Sgirish 			if ((status = nxge_mii_read(nxgep,
446852ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4469adfcba55Sjoycey #if defined(__i386)
447052ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
4471adfcba55Sjoycey #else
447252ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
4473adfcba55Sjoycey #endif
447452ccf843Smisaki 			    &anlpar.value)) != NXGE_OK)
447544961713Sgirish 				goto fail;
447644961713Sgirish 			if ((status = nxge_mii_read(nxgep,
447752ccf843Smisaki 			    statsp->mac_stats.xcvr_portn,
4478adfcba55Sjoycey #if defined(__i386)
447952ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->aner),
4480adfcba55Sjoycey #else
448152ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->aner),
4482adfcba55Sjoycey #endif
448352ccf843Smisaki 			    &aner.value)) != NXGE_OK)
448444961713Sgirish 				goto fail;
448544961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
448644961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
448744961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
448852ccf843Smisaki 			    anlpar.bits.cap_100fdx;
448944961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
449052ccf843Smisaki 			    anlpar.bits.cap_100hdx;
449144961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
449244961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
449344961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
449452ccf843Smisaki 			    anlpar.bits.cap_asmpause;
449544961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
449644961713Sgirish 			an_common.value = anar.value & anlpar.value;
449744961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
449852ccf843Smisaki 			    param_arr[param_anar_1000hdx].value) {
449944961713Sgirish 				if ((status = nxge_mii_read(nxgep,
450052ccf843Smisaki 				    statsp->mac_stats.xcvr_portn,
4501adfcba55Sjoycey #if defined(__i386)
450252ccf843Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
4503adfcba55Sjoycey #else
450452ccf843Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
4505adfcba55Sjoycey #endif
450652ccf843Smisaki 				    &gsr.value)) != NXGE_OK)
450744961713Sgirish 					goto fail;
450844961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
450952ccf843Smisaki 				    gsr.bits.link_1000fdx;
451044961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
451152ccf843Smisaki 				    gsr.bits.link_1000hdx;
451244961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
451352ccf843Smisaki 				    gsr.bits.link_1000fdx) {
451444961713Sgirish 					statsp->mac_stats.link_speed = 1000;
451544961713Sgirish 					statsp->mac_stats.link_duplex = 2;
451644961713Sgirish 				} else if (
451752ccf843Smisaki 				    param_arr[param_anar_1000hdx].value &&
451852ccf843Smisaki 				    gsr.bits.link_1000hdx) {
451944961713Sgirish 					statsp->mac_stats.link_speed = 1000;
452044961713Sgirish 					statsp->mac_stats.link_duplex = 1;
452144961713Sgirish 				}
452244961713Sgirish 			}
452344961713Sgirish 			if ((an_common.value != 0) &&
452452ccf843Smisaki 			    !(statsp->mac_stats.link_speed)) {
452544961713Sgirish 				if (an_common.bits.cap_100T4) {
452644961713Sgirish 					statsp->mac_stats.link_T4 = 1;
452744961713Sgirish 					statsp->mac_stats.link_speed = 100;
452844961713Sgirish 					statsp->mac_stats.link_duplex = 1;
452944961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
453044961713Sgirish 					statsp->mac_stats.link_speed = 100;
453144961713Sgirish 					statsp->mac_stats.link_duplex = 2;
453244961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
453344961713Sgirish 					statsp->mac_stats.link_speed = 100;
453444961713Sgirish 					statsp->mac_stats.link_duplex = 1;
453544961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
453644961713Sgirish 					statsp->mac_stats.link_speed = 10;
453744961713Sgirish 					statsp->mac_stats.link_duplex = 2;
453844961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
453944961713Sgirish 					statsp->mac_stats.link_speed = 10;
454044961713Sgirish 					statsp->mac_stats.link_duplex = 1;
454144961713Sgirish 				} else {
454244961713Sgirish 					goto fail;
454344961713Sgirish 				}
454444961713Sgirish 			}
454544961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
454652ccf843Smisaki 				int	link_pause;
454752ccf843Smisaki 				int	cp, lcp;
454852ccf843Smisaki 
454944961713Sgirish 				statsp->mac_stats.link_asmpause =
455052ccf843Smisaki 				    an_common.bits.cap_asmpause;
455152ccf843Smisaki 				cp = statsp->mac_stats.cap_pause;
455252ccf843Smisaki 				lcp = statsp->mac_stats.lp_cap_pause;
455352ccf843Smisaki 				if (statsp->mac_stats.link_asmpause) {
455452ccf843Smisaki 					if ((cp == 0) && (lcp == 1)) {
455552ccf843Smisaki 						link_pause = 0;
455652ccf843Smisaki 					} else {
455752ccf843Smisaki 						link_pause = 1;
455852ccf843Smisaki 					}
455952ccf843Smisaki 				} else {
456052ccf843Smisaki 					link_pause = an_common.bits.cap_pause;
456152ccf843Smisaki 				}
456252ccf843Smisaki 				statsp->mac_stats.link_pause = link_pause;
456344961713Sgirish 			}
4564d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4565d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
4566d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
456744961713Sgirish 		}
4568a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
4569a3c5bd6dSspeer 	}
4570a3c5bd6dSspeer 
4571a3c5bd6dSspeer 	if (nxgep->link_notify) {
4572a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
457352ccf843Smisaki 		    LINK_IS_DOWN);
4574a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
457544961713Sgirish 	}
457644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
457744961713Sgirish 	return (NXGE_OK);
457844961713Sgirish fail:
457944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
458052ccf843Smisaki 	    "nxge_mii_check: Unable to check MII"));
458144961713Sgirish 	return (status);
458244961713Sgirish }
458344961713Sgirish 
458400161856Syc /*
458500161856Syc  * Check PCS to see if there is any link status change.
458600161856Syc  * This function is called by PORT_1G_SERDES only.
458700161856Syc  */
458800161856Syc void
45892e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
45902e59129aSraghus {
45912e59129aSraghus 	p_nxge_stats_t	statsp;
45922e59129aSraghus 	boolean_t	linkup;
45932e59129aSraghus 
45942e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
45952e59129aSraghus 
45962e59129aSraghus 	statsp = nxgep->statsp;
45972e59129aSraghus 	*link_up = LINK_NO_CHANGE;
45982e59129aSraghus 
45992e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
46002e59129aSraghus 	if (linkup) {
46012e59129aSraghus 		if (nxgep->link_notify ||
46022e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
46032e59129aSraghus 			statsp->mac_stats.link_up = 1;
46042e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
46052e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
46062e59129aSraghus 			*link_up = LINK_IS_UP;
46072e59129aSraghus 			nxgep->link_notify = B_FALSE;
46082e59129aSraghus 		}
46092e59129aSraghus 	} else {
46102e59129aSraghus 		if (nxgep->link_notify ||
46112e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
46122e59129aSraghus 			statsp->mac_stats.link_up = 0;
46132e59129aSraghus 			statsp->mac_stats.link_speed = 0;
46142e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
46152e59129aSraghus 			*link_up = LINK_IS_DOWN;
46162e59129aSraghus 			nxgep->link_notify = B_FALSE;
46172e59129aSraghus 		}
46182e59129aSraghus 	}
46192e59129aSraghus 
46202e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
46212e59129aSraghus }
46222e59129aSraghus 
462344961713Sgirish /* Add a multicast address entry into the HW hash table */
462444961713Sgirish 
462544961713Sgirish nxge_status_t
462644961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
462744961713Sgirish {
462844961713Sgirish 	uint32_t mchash;
462944961713Sgirish 	p_hash_filter_t hash_filter;
463044961713Sgirish 	uint16_t hash_bit;
463144961713Sgirish 	boolean_t rx_init = B_FALSE;
463244961713Sgirish 	uint_t j;
463344961713Sgirish 	nxge_status_t status = NXGE_OK;
463444961713Sgirish 
463544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
463644961713Sgirish 
463744961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
463844961713Sgirish 	mchash = crc32_mchash(addrp);
463944961713Sgirish 	if (nxgep->hash_filter == NULL) {
464044961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
464152ccf843Smisaki 		    "Allocating hash filter storage."));
464244961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
464352ccf843Smisaki 		    KM_SLEEP);
464444961713Sgirish 	}
464544961713Sgirish 	hash_filter = nxgep->hash_filter;
464644961713Sgirish 	j = mchash / HASH_REG_WIDTH;
464744961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
464844961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
464944961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
465044961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
465144961713Sgirish 		hash_filter->hash_ref_cnt++;
465244961713Sgirish 		rx_init = B_TRUE;
465344961713Sgirish 	}
465444961713Sgirish 	if (rx_init) {
465544961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
465644961713Sgirish 			goto fail;
465744961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
465844961713Sgirish 			goto fail;
465944961713Sgirish 	}
466044961713Sgirish 
466144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
466244961713Sgirish 
466344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
466444961713Sgirish 
466544961713Sgirish 	return (NXGE_OK);
466644961713Sgirish fail:
466744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
466844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
466952ccf843Smisaki 	    "Unable to add multicast address"));
467044961713Sgirish 	return (status);
467144961713Sgirish }
467244961713Sgirish 
467344961713Sgirish /* Remove a multicast address entry from the HW hash table */
467444961713Sgirish 
467544961713Sgirish nxge_status_t
467644961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
467744961713Sgirish {
467844961713Sgirish 	uint32_t mchash;
467944961713Sgirish 	p_hash_filter_t hash_filter;
468044961713Sgirish 	uint16_t hash_bit;
468144961713Sgirish 	boolean_t rx_init = B_FALSE;
468244961713Sgirish 	uint_t j;
468344961713Sgirish 	nxge_status_t status = NXGE_OK;
468444961713Sgirish 
468544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
468644961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
468744961713Sgirish 	mchash = crc32_mchash(addrp);
468844961713Sgirish 	if (nxgep->hash_filter == NULL) {
468944961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
469052ccf843Smisaki 		    "Hash filter already de_allocated."));
469144961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
469244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
469344961713Sgirish 		return (NXGE_OK);
469444961713Sgirish 	}
469544961713Sgirish 	hash_filter = nxgep->hash_filter;
469644961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
469744961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
469844961713Sgirish 		j = mchash / HASH_REG_WIDTH;
469944961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
470044961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
470144961713Sgirish 		hash_filter->hash_ref_cnt--;
470244961713Sgirish 		rx_init = B_TRUE;
470344961713Sgirish 	}
470444961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
470544961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
470652ccf843Smisaki 		    "De-allocating hash filter storage."));
470744961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
470844961713Sgirish 		nxgep->hash_filter = NULL;
470944961713Sgirish 	}
471044961713Sgirish 
471144961713Sgirish 	if (rx_init) {
471244961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
471344961713Sgirish 			goto fail;
471444961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
471544961713Sgirish 			goto fail;
471644961713Sgirish 	}
471744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
471844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
471944961713Sgirish 
472044961713Sgirish 	return (NXGE_OK);
472144961713Sgirish fail:
472244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
472344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
472452ccf843Smisaki 	    "Unable to remove multicast address"));
472544961713Sgirish 
472644961713Sgirish 	return (status);
472744961713Sgirish }
472844961713Sgirish 
472944961713Sgirish /* Set MAC address into MAC address HW registers */
473044961713Sgirish 
473144961713Sgirish nxge_status_t
473244961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
473344961713Sgirish {
473444961713Sgirish 	nxge_status_t status = NXGE_OK;
473544961713Sgirish 
473644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
473744961713Sgirish 
473844961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
473944961713Sgirish 	/*
474044961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
474144961713Sgirish 	 */
474244961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
474352ccf843Smisaki 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
474452ccf843Smisaki 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
474544961713Sgirish 		goto nxge_set_mac_addr_exit;
474644961713Sgirish 	}
474744961713Sgirish 	nxgep->ouraddr = *addrp;
474844961713Sgirish 	/*
474944961713Sgirish 	 * Set new interface local address and re-init device.
475044961713Sgirish 	 * This is destructive to any other streams attached
475144961713Sgirish 	 * to this device.
475244961713Sgirish 	 */
475344961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
475444961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
475544961713Sgirish 		goto fail;
475644961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
475744961713Sgirish 		goto fail;
475844961713Sgirish 
475944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
476044961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
476144961713Sgirish 	goto nxge_set_mac_addr_end;
476244961713Sgirish nxge_set_mac_addr_exit:
476344961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
476444961713Sgirish nxge_set_mac_addr_end:
476544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
476644961713Sgirish 
476744961713Sgirish 	return (NXGE_OK);
476844961713Sgirish fail:
476944961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
477044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
477152ccf843Smisaki 	    "Unable to set mac address"));
477244961713Sgirish 	return (status);
477344961713Sgirish }
477444961713Sgirish 
477598ecde52Stm static
477698ecde52Stm check_link_state_t
477700161856Syc nxge_check_link_stop(nxge_t *nxge)
477898ecde52Stm {
477998ecde52Stm 	/* If the poll has been cancelled, return STOP. */
478098ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
478198ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
478298ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
478398ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
478498ecde52Stm 		cv_broadcast(&nxge->poll_cv);
478598ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
478698ecde52Stm 
478798ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
478898ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
478998ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
479098ecde52Stm 		    nxge->mac.portnum));
479198ecde52Stm 		return (CHECK_LINK_STOP);
479298ecde52Stm 	}
479398ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
479498ecde52Stm 
479598ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
479698ecde52Stm }
479798ecde52Stm 
479800161856Syc /*
479900161856Syc  * Check status of MII (MIF or PCS) link.
480000161856Syc  * This function is called once per second, that is because this function
480100161856Syc  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
480200161856Syc  * call this function recursively.
480300161856Syc  */
480459ac0c16Sdavemq static nxge_status_t
480544961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
480644961713Sgirish {
480744961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
480844961713Sgirish 	mii_anlpar_t anlpar;
480944961713Sgirish 	mii_gsr_t gsr;
481044961713Sgirish 	p_mii_regs_t mii_regs;
481144961713Sgirish 	nxge_status_t status = NXGE_OK;
481244961713Sgirish 	uint8_t portn;
4813a3c5bd6dSspeer 	nxge_link_state_t link_up;
481444961713Sgirish 
481598ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
481698ecde52Stm 		return (NXGE_ERROR);
481798ecde52Stm 
481898ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
481998ecde52Stm 		return (NXGE_OK);
482098ecde52Stm 
482144961713Sgirish 	portn = nxgep->mac.portnum;
482244961713Sgirish 
482344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
482498ecde52Stm 	    portn));
482544961713Sgirish 
482644961713Sgirish 	mii_regs = NULL;
482744961713Sgirish 
482844961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
482944961713Sgirish 
483044961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
483144961713Sgirish 		goto nxge_check_mii_link_exit;
483244961713Sgirish 
48332e59129aSraghus 	switch (nxgep->mac.portmode) {
48342e59129aSraghus 	default:
4835d81011f0Ssbehera 		bmsr_data.value = 0;
483644961713Sgirish 		if ((status = nxge_mii_read(nxgep,
48372e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
4838adfcba55Sjoycey #if defined(__i386)
4839adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4840adfcba55Sjoycey #else
48412e59129aSraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4842adfcba55Sjoycey #endif
48432e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
484444961713Sgirish 			goto fail;
484544961713Sgirish 		}
484644961713Sgirish 
4847d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4848d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
4849d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
48502d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
4851d81011f0Ssbehera 
48522e59129aSraghus 		if (nxgep->param_arr[param_autoneg].value) {
48532e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
485452ccf843Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
4855adfcba55Sjoycey #if defined(__i386)
485652ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
4857adfcba55Sjoycey #else
485852ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
4859adfcba55Sjoycey #endif
486052ccf843Smisaki 			    &gsr.value)) != NXGE_OK)
48612e59129aSraghus 				goto fail;
48622e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
486352ccf843Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
4864adfcba55Sjoycey #if defined(__i386)
486552ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
4866adfcba55Sjoycey #else
486752ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
4868adfcba55Sjoycey #endif
486952ccf843Smisaki 			    &anlpar.value)) != NXGE_OK)
48702e59129aSraghus 				goto fail;
4871d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
4872d81011f0Ssbehera 
4873d81011f0Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
4874d81011f0Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
4875d81011f0Ssbehera 				    gsr.bits.link_1000fdx) ||
4876d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
4877d81011f0Ssbehera 				    gsr.bits.link_1000hdx) ||
4878d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
4879d81011f0Ssbehera 				    anlpar.bits.cap_100T4) ||
4880d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
4881d81011f0Ssbehera 				    anlpar.bits.cap_100fdx) ||
4882d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
4883d81011f0Ssbehera 				    anlpar.bits.cap_100hdx) ||
4884d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
4885d81011f0Ssbehera 				    anlpar.bits.cap_10fdx) ||
4886d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
4887d81011f0Ssbehera 				    anlpar.bits.cap_10hdx))) {
4888d81011f0Ssbehera 					bmsr_data.bits.link_status = 0;
4889d81011f0Ssbehera 				}
48902e59129aSraghus 			}
48912e59129aSraghus 		}
489244961713Sgirish 
48932e59129aSraghus 		/* Workaround for link down issue */
48942e59129aSraghus 		if (bmsr_data.value == 0) {
48952e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
48962e59129aSraghus 			goto nxge_check_mii_link_exit;
48972e59129aSraghus 		}
48982e59129aSraghus 
4899d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4900d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
4901d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
49022d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
4903d81011f0Ssbehera 
49042e59129aSraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
49052e59129aSraghus 		nxgep->bmsr.value = bmsr_data.value;
4906d81011f0Ssbehera 
4907d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4908d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
4909d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
49102d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
4911d81011f0Ssbehera 
49122e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
49132e59129aSraghus 		    &link_up)) != NXGE_OK) {
49142e59129aSraghus 			goto fail;
49152e59129aSraghus 		}
49162e59129aSraghus 		break;
49172e59129aSraghus 
49182e59129aSraghus 	case PORT_1G_SERDES:
491900161856Syc 		/*
492000161856Syc 		 * Above default is for all cases except PORT_1G_SERDES.
492100161856Syc 		 * The default case gets information from the PHY, but a
492200161856Syc 		 * nxge whose portmode equals PORT_1G_SERDES does not
492300161856Syc 		 * have a PHY.
492400161856Syc 		 */
49252e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49262e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
492700161856Syc 		nxge_pcs_check(nxgep, portn, &link_up);
49282e59129aSraghus 		break;
49292e59129aSraghus 	}
493044961713Sgirish 
493144961713Sgirish nxge_check_mii_link_exit:
493244961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
4933a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
4934a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
4935a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
4936a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
4937a3c5bd6dSspeer 	}
493844961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
493944961713Sgirish 
494044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
494152ccf843Smisaki 	    portn));
494244961713Sgirish 	return (NXGE_OK);
494344961713Sgirish 
494444961713Sgirish fail:
494544961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
494644961713Sgirish 
494744961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
494844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
494952ccf843Smisaki 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
495044961713Sgirish 	return (status);
495144961713Sgirish }
495244961713Sgirish 
495344961713Sgirish /*ARGSUSED*/
495459ac0c16Sdavemq static nxge_status_t
495544961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
495644961713Sgirish {
495744961713Sgirish 	uint8_t		portn;
495844961713Sgirish 	nxge_status_t	status = NXGE_OK;
4959763fcc44Ssbehera 	boolean_t	link_up;
49602e59129aSraghus 	uint32_t	val;
49612e59129aSraghus 	npi_status_t	rs;
496244961713Sgirish 
496398ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
496498ecde52Stm 		return (NXGE_ERROR);
496598ecde52Stm 
496698ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
496798ecde52Stm 		return (NXGE_OK);
496898ecde52Stm 
496944961713Sgirish 	portn = nxgep->mac.portnum;
4970d81011f0Ssbehera 	val = 0;
4971d81011f0Ssbehera 	rs = NPI_SUCCESS;
497244961713Sgirish 
497344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
497498ecde52Stm 	    portn));
497544961713Sgirish 
49762e59129aSraghus 	switch (nxgep->mac.portmode) {
49772e59129aSraghus 	default:
49782d17280bSsbehera 		/*
49792d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
49802d17280bSsbehera 		 */
49812d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
49822d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
49832d17280bSsbehera 
49842d17280bSsbehera 			/*
49852d17280bSsbehera 			 * If this is the 2nd Goa port, then check 2 addresses
49862d17280bSsbehera 			 * to take care of the Goa NEM card requirements.
49872d17280bSsbehera 			 */
49882d17280bSsbehera 			if (portn == 1) {
49892d17280bSsbehera 				if (nxge_is_phy_present(nxgep,
499000161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
49912d17280bSsbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
49922d17280bSsbehera 					phy_present_now = B_TRUE;
49932d17280bSsbehera 					nxgep->xcvr_addr =
499400161856Syc 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
49952d17280bSsbehera 					goto phy_check_done;
49962d17280bSsbehera 				}
49972d17280bSsbehera 			}
49982d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
499900161856Syc 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
50002d17280bSsbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
50012d17280bSsbehera 				nxgep->xcvr_addr =
500200161856Syc 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
50032d17280bSsbehera 				phy_present_now = B_TRUE;
50042d17280bSsbehera 			}
50052d17280bSsbehera 
50062d17280bSsbehera phy_check_done:
50071c7408c9Stc 			/* Check back-to-back XAUI connect to detect Opus NEM */
50081c7408c9Stc 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
50091c7408c9Stc 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
50101c7408c9Stc 			if (rs != 0)
50111c7408c9Stc 				goto fail;
50121c7408c9Stc 
50131c7408c9Stc 			link_up = B_FALSE;
50141c7408c9Stc 			if (val & XPCS_STATUS_LANE_ALIGN) {
50151c7408c9Stc 				link_up = B_TRUE;
50161c7408c9Stc 			}
50171c7408c9Stc 
50182d17280bSsbehera 			if (nxgep->phy_absent) {
50192d17280bSsbehera 				if (phy_present_now) {
50202d17280bSsbehera 				/*
50212d17280bSsbehera 				 * Detect, Initialize phy and do link up
50222d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
50232d17280bSsbehera 				 */
50242d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50252d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
50262d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
50272d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
50282d17280bSsbehera 					(void) nxge_link_init(nxgep);
50292d17280bSsbehera 					if (!(nxgep->drv_state &
50302d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
50312d17280bSsbehera 						status = nxge_init(nxgep);
50322d17280bSsbehera 						if (status != NXGE_OK) {
50332d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
50342d17280bSsbehera 							    NXGE_ERR_CTL,
50352d17280bSsbehera 							    "Hot swappable "
50362d17280bSsbehera 							    "phy present, but"
50372d17280bSsbehera 							    " driver init"
50382d17280bSsbehera 							    "  failed..."));
50392d17280bSsbehera 							goto fail;
50402d17280bSsbehera 						}
50412d17280bSsbehera 					}
50421c7408c9Stc 				} else if (link_up) { /* XAUI linkup, no PHY */
504348056c53SMichael Speer 					/*
50441c7408c9Stc 					 * This is the back-to-back XAUI
50451c7408c9Stc 					 * connect case for Opus NEM.
50461c7408c9Stc 					 */
50471c7408c9Stc 					nxgep->statsp->mac_stats.xcvr_inuse =
50481c7408c9Stc 					    XPCS_XCVR;
50491c7408c9Stc 					nxgep->mac.portmode = PORT_10G_SERDES;
50501c7408c9Stc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50511c7408c9Stc 					    "HSP 10G Serdes DETECTED!!"));
50521c7408c9Stc 					break;
50532d17280bSsbehera 				}
50542d17280bSsbehera 
50552d17280bSsbehera 				goto start_link_check;
50562d17280bSsbehera 
50572d17280bSsbehera 			} else if (!phy_present_now) {
50582d17280bSsbehera 				/*
50592d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
50602d17280bSsbehera 				 */
50612d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50622d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
50632d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
50642d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
50652d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
50662d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
50672d17280bSsbehera 				nxge_link_is_down(nxgep);
50682d17280bSsbehera 				nxgep->link_notify = B_FALSE;
50692d17280bSsbehera 
50702d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
50712d17280bSsbehera 
50722d17280bSsbehera 				goto start_link_check;
50732d17280bSsbehera 
50742d17280bSsbehera 			}
50752d17280bSsbehera 		}
507652cdd236Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
507700161856Syc 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
507852cdd236Ssbehera 		} else {
507952cdd236Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
508052cdd236Ssbehera 		}
50812e59129aSraghus 		if (status != NXGE_OK)
50822e59129aSraghus 			goto fail;
50832e59129aSraghus 		break;
50842e59129aSraghus 	case PORT_10G_SERDES:
50852e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5086763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
50872e59129aSraghus 		if (rs != 0)
50882e59129aSraghus 			goto fail;
50892e59129aSraghus 
50902e59129aSraghus 		link_up = B_FALSE;
5091763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
5092763fcc44Ssbehera 			link_up = B_TRUE;
50932e59129aSraghus 		}
50942e59129aSraghus 
50952e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50962e59129aSraghus 		    "==> nxge_check_10g_link port<%d> "
5097763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
5098763fcc44Ssbehera 		    portn, val, link_up));
50992e59129aSraghus 
51002e59129aSraghus 		break;
51012e59129aSraghus 	}
510244961713Sgirish 
510344961713Sgirish 	if (link_up) {
5104a3c5bd6dSspeer 		if (nxgep->link_notify ||
510552ccf843Smisaki 		    nxgep->statsp->mac_stats.link_up == 0) {
510644961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
510744961713Sgirish 				goto fail;
510844961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
510944961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
511044961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
511144961713Sgirish 
511244961713Sgirish 			nxge_link_is_up(nxgep);
5113a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
511444961713Sgirish 		}
511544961713Sgirish 	} else {
5116a3c5bd6dSspeer 		if (nxgep->link_notify ||
511752ccf843Smisaki 		    nxgep->statsp->mac_stats.link_up == 1) {
511844961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
511944961713Sgirish 				goto fail;
512044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
512152ccf843Smisaki 			    "Link down cable problem"));
512244961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
512344961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
512444961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
512544961713Sgirish 
512644961713Sgirish 			nxge_link_is_down(nxgep);
5127a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
51281c7408c9Stc 
51291c7408c9Stc 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
51301c7408c9Stc 				/*
51311c7408c9Stc 				 * NEM was unplugged, set up xcvr table
51321c7408c9Stc 				 * to find another xcvr in the future.
51331c7408c9Stc 				 */
51341c7408c9Stc 				(void) nxge_xcvr_find(nxgep);
51351c7408c9Stc 			}
513644961713Sgirish 		}
513744961713Sgirish 	}
513844961713Sgirish 
51392d17280bSsbehera start_link_check:
514044961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
514144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
514298ecde52Stm 	    portn));
514344961713Sgirish 	return (NXGE_OK);
514444961713Sgirish 
514544961713Sgirish fail:
514698ecde52Stm 	(void) nxge_check_link_stop(nxgep);
514798ecde52Stm 
514844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
514998ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
515098ecde52Stm 	    portn));
515144961713Sgirish 	return (status);
515244961713Sgirish }
515344961713Sgirish 
515444961713Sgirish 
515544961713Sgirish /* Declare link down */
515644961713Sgirish 
515744961713Sgirish void
515844961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
515944961713Sgirish {
516059ac0c16Sdavemq 	p_nxge_stats_t statsp;
516159ac0c16Sdavemq 	char link_stat_msg[64];
516259ac0c16Sdavemq 
516344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
516444961713Sgirish 
516559ac0c16Sdavemq 	statsp = nxgep->statsp;
516659ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
516759ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
516859ac0c16Sdavemq 
516959ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
517059ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
517159ac0c16Sdavemq 	}
517259ac0c16Sdavemq 
517344961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
517444961713Sgirish 
517544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
517644961713Sgirish }
517744961713Sgirish 
517844961713Sgirish /* Declare link up */
517944961713Sgirish 
518044961713Sgirish void
518144961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
518244961713Sgirish {
518359ac0c16Sdavemq 	p_nxge_stats_t statsp;
518459ac0c16Sdavemq 	char link_stat_msg[64];
518544961713Sgirish 	uint32_t val;
518644961713Sgirish 
518744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
518844961713Sgirish 
518959ac0c16Sdavemq 	statsp = nxgep->statsp;
519059ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
519159ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
519259ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
519359ac0c16Sdavemq 
519459ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
519559ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
519659ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
519759ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
519859ac0c16Sdavemq 	else
519959ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
520059ac0c16Sdavemq 
520144961713Sgirish 
520244961713Sgirish 	/* Clean up symbol errors incurred during link transition */
52032e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
52042e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
520544961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
520652ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
520744961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
520852ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
520944961713Sgirish 	}
521044961713Sgirish 
521100161856Syc 	/*
521200161856Syc 	 * If the driver was plumbed without a link (therefore auto-negotiation
521300161856Syc 	 * could not complete), the driver will detect a link up when a cable
521400161856Syc 	 * conneting to a link partner is plugged into the port. By the time
521500161856Syc 	 * link-up is detected, auto-negotiation should have completed (The
521600161856Syc 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
521700161856Syc 	 * configure the Neptune/NIU according to the newly negotiated speed.
521800161856Syc 	 * This is necessary only for the TN1010 basad device because only the
521900161856Syc 	 * TN1010 supports dual speeds.
522000161856Syc 	 */
522100161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
522200161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
522300161856Syc 
522400161856Syc 		(void) nxge_set_tn1010_param(nxgep);
522500161856Syc 
522600161856Syc 		/*
522700161856Syc 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
522800161856Syc 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
522900161856Syc 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
523000161856Syc 		 */
523100161856Syc 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
523200161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
523300161856Syc 			    "nxge_link_is_up: nxge_xcvr_find failed"));
523400161856Syc 		}
523500161856Syc 
523600161856Syc 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
523700161856Syc 		if (nxge_link_init(nxgep) != NXGE_OK) {
523800161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
523900161856Syc 			    "nxge_link_is_up: nxge_link_init failed"));
524000161856Syc 		}
524100161856Syc 
524200161856Syc 		/*
524300161856Syc 		 * nxge_mac_init calls many subroutines including
524400161856Syc 		 * nxge_xif_init which sets XGMII or GMII mode
524500161856Syc 		 */
524600161856Syc 		if (nxge_mac_init(nxgep) != NXGE_OK) {
524700161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
524800161856Syc 			    "nxge_link_is_up: nxge_mac_init failed"));
524900161856Syc 		}
525000161856Syc 	} else {
525100161856Syc 		(void) nxge_xif_init(nxgep);
525200161856Syc 	}
525300161856Syc 
525459ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
525559ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
525659ac0c16Sdavemq 	}
525759ac0c16Sdavemq 
525844961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
525944961713Sgirish 
526044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
526144961713Sgirish }
526244961713Sgirish 
526300161856Syc #ifdef NXGE_DEBUG
526400161856Syc /* Dump all TN1010 Status registers */
526500161856Syc static void
526600161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
526700161856Syc {
526800161856Syc 	uint16_t val;
526900161856Syc 
527000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
527100161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
527200161856Syc 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
527300161856Syc 
527400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
527500161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
527600161856Syc 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
527700161856Syc 
527800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
527900161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
528000161856Syc 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
528100161856Syc 
528200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
528300161856Syc 	    TN1010_PCS_DEV_ADDR, 1, &val);
528400161856Syc 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
528500161856Syc 
528600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
528700161856Syc 	    TN1010_PCS_DEV_ADDR, 8, &val);
528800161856Syc 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
528900161856Syc 
529000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
529100161856Syc 	    TN1010_PCS_DEV_ADDR, 32, &val);
529200161856Syc 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
529300161856Syc 
529400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
529500161856Syc 	    TN1010_PCS_DEV_ADDR, 33, &val);
529600161856Syc 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
529700161856Syc 
529800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
529900161856Syc 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
530000161856Syc 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
530100161856Syc 
530200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
530300161856Syc 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
530400161856Syc 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
530500161856Syc 
530600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
530700161856Syc 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
530800161856Syc 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
530900161856Syc 
531000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
531100161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
531200161856Syc 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
531300161856Syc 
531400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
531500161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
531600161856Syc 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
531700161856Syc 
531800161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
531900161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
532000161856Syc 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
532100161856Syc 
532200161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
532300161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
532400161856Syc 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
532500161856Syc 
532600161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
532700161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
532800161856Syc 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
532900161856Syc 
533000161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
533100161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
533200161856Syc 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
533300161856Syc 
533400161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
533500161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
533600161856Syc 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
533700161856Syc 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
533800161856Syc }
533900161856Syc #endif
534000161856Syc 
534144961713Sgirish /*
534244961713Sgirish  * Calculate the bit in the multicast address filter
534344961713Sgirish  * that selects the given * address.
534444961713Sgirish  * Note: For GEM, the last 8-bits are used.
534544961713Sgirish  */
534644961713Sgirish uint32_t
534744961713Sgirish crc32_mchash(p_ether_addr_t addr)
534844961713Sgirish {
534944961713Sgirish 	uint8_t *cp;
535044961713Sgirish 	uint32_t crc;
535144961713Sgirish 	uint32_t c;
535244961713Sgirish 	int byte;
535344961713Sgirish 	int bit;
535444961713Sgirish 
535544961713Sgirish 	cp = (uint8_t *)addr;
535644961713Sgirish 	crc = (uint32_t)0xffffffff;
535744961713Sgirish 	for (byte = 0; byte < 6; byte++) {
535844961713Sgirish 		c = (uint32_t)cp[byte];
535944961713Sgirish 		for (bit = 0; bit < 8; bit++) {
536044961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
536144961713Sgirish 				crc = (crc >> 1)^0xedb88320;
536244961713Sgirish 			else
536344961713Sgirish 				crc = (crc >> 1);
536444961713Sgirish 			c >>= 1;
536544961713Sgirish 		}
536644961713Sgirish 	}
536744961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
536844961713Sgirish }
536944961713Sgirish 
537044961713Sgirish /* Reset serdes */
537144961713Sgirish 
537244961713Sgirish nxge_status_t
537344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
537444961713Sgirish {
537544961713Sgirish 	npi_handle_t		handle;
537644961713Sgirish 
537744961713Sgirish 	handle = nxgep->npi_handle;
537844961713Sgirish 
537944961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
538044961713Sgirish 	drv_usecwait(500);
538144961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
538244961713Sgirish 
538344961713Sgirish 	return (NXGE_OK);
538444961713Sgirish }
538544961713Sgirish 
538600161856Syc /*
538700161856Syc  * This function monitors link status using interrupt or polling.
538800161856Syc  * It calls nxgep->xcvr.check_link, a member function of
538900161856Syc  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
539000161856Syc  * function back, that is why the check_link routine is
539100161856Syc  * executed periodically.
539200161856Syc  */
539344961713Sgirish nxge_status_t
539444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
539544961713Sgirish {
539644961713Sgirish 	nxge_status_t status = NXGE_OK;
539744961713Sgirish 
5398678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
5399678453a8Sspeer 	if (isLDOMguest(nxgep))
5400678453a8Sspeer 		return (status);
5401678453a8Sspeer 
540244961713Sgirish 	/*
540398ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
540498ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
540544961713Sgirish 	 */
54062e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
54072e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
54082e59129aSraghus 	    (nxgep->mac.portnum > 1))
540944961713Sgirish 		return (NXGE_OK);
541044961713Sgirish 
541144961713Sgirish 	if (nxgep->statsp == NULL) {
541244961713Sgirish 		/* stats has not been allocated. */
541344961713Sgirish 		return (NXGE_OK);
541444961713Sgirish 	}
5415321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
5416321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
541744961713Sgirish 		return (NXGE_OK);
541844961713Sgirish 
541944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
542098ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
542198ecde52Stm 	    nxgep->mac.portnum, enable));
542244961713Sgirish 	if (enable == LINK_MONITOR_START) {
542344961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
542444961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
542598ecde52Stm 			    != NXGE_OK)
542644961713Sgirish 				goto fail;
542744961713Sgirish 		} else {
542898ecde52Stm 			timeout_id_t timerid;
542900161856Syc 			/*
543000161856Syc 			 * check_link_stop means "Stop the link check", so
543100161856Syc 			 * we return without starting the timer.
543200161856Syc 			 */
543398ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
543498ecde52Stm 				return (NXGE_OK);
543598ecde52Stm 
543600161856Syc 			/*
543700161856Syc 			 * Otherwise fire the timer for the nxge to check
543800161856Syc 			 * the link using the check_link function
543900161856Syc 			 * of the nxge_xcvr_table and pass "nxgep" as the
544000161856Syc 			 * argument to the check_link function.
544100161856Syc 			 */
544259ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
544359ac0c16Sdavemq 				timerid = timeout(
544459ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
544598ecde52Stm 				    nxgep,
544698ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
544759ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
544859ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
544959ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
545059ac0c16Sdavemq 			} else {
545198ecde52Stm 				return (NXGE_ERROR);
545244961713Sgirish 			}
545344961713Sgirish 		}
545444961713Sgirish 	} else {
545544961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
545644961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
545798ecde52Stm 			    != NXGE_OK)
545844961713Sgirish 				goto fail;
545944961713Sgirish 		} else {
546098ecde52Stm 			clock_t rv;
546198ecde52Stm 
546298ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
546398ecde52Stm 
546498ecde52Stm 			/* If <timerid> == 0, the link monitor has */
546598ecde52Stm 			/* never been started, or just now stopped. */
546698ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
546798ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
546898ecde52Stm 				return (NXGE_OK);
546998ecde52Stm 			}
547098ecde52Stm 
547198ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
547298ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
547398ecde52Stm 			    &nxgep->poll_lock,
547498ecde52Stm 			    ddi_get_lbolt() +
547598ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
547698ecde52Stm 			    LINK_MONITOR_PERIOD));
547798ecde52Stm 			if (rv == -1) {
547898ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
547998ecde52Stm 				    "==> stopping port %d: "
548098ecde52Stm 				    "cv_timedwait(%d) timed out",
548198ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
548298ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
548344961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
548444961713Sgirish 			}
548598ecde52Stm 
548698ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
548744961713Sgirish 		}
548844961713Sgirish 	}
548944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
549098ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
549198ecde52Stm 	    nxgep->mac.portnum, enable));
5492678453a8Sspeer 
549344961713Sgirish 	return (NXGE_OK);
549444961713Sgirish fail:
549544961713Sgirish 	return (status);
549600161856Syc 
549700161856Syc }
549800161856Syc 
549900161856Syc nxge_status_t
550000161856Syc nxge_check_tn1010_link(p_nxge_t nxgep)
550100161856Syc {
550200161856Syc 	nxge_status_t	status = NXGE_OK;
550300161856Syc 	nxge_link_state_t link_up;
550400161856Syc 
550500161856Syc 	if (nxgep->nxge_magic != NXGE_MAGIC) {
550600161856Syc 		/* magic is 0 if driver is not attached */
550700161856Syc 		return (NXGE_ERROR);
550800161856Syc 	}
550900161856Syc 
551000161856Syc 	/* Link has been stopped, no need to continue */
551100161856Syc 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
551200161856Syc 		return (NXGE_OK);
551300161856Syc 	}
551400161856Syc 
551500161856Syc 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
551600161856Syc 		goto nxge_check_tn1010_link_exit;
551700161856Syc 
551800161856Syc 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
551900161856Syc 		goto fail;
552000161856Syc 
552100161856Syc nxge_check_tn1010_link_exit:
552200161856Syc 	if (link_up == LINK_IS_UP)
552300161856Syc 		nxge_link_is_up(nxgep);
552400161856Syc 	else if (link_up == LINK_IS_DOWN)
552500161856Syc 		nxge_link_is_down(nxgep);
552600161856Syc 
552700161856Syc 	/*
552800161856Syc 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
552900161856Syc 	 * which could be THIS function.
553000161856Syc 	 */
553100161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
553200161856Syc 
553300161856Syc 	return (NXGE_OK);
553400161856Syc 
553500161856Syc fail:
553600161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
553700161856Syc 
553800161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
553900161856Syc 	    "nxge_check_tn1010_link: Failed to check link"));
554000161856Syc 	return (status);
554100161856Syc }
554200161856Syc 
554300161856Syc 
554400161856Syc /*
554500161856Syc  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
554600161856Syc  */
554700161856Syc static nxge_status_t
554800161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
554900161856Syc {
555000161856Syc 	nxge_status_t	status = NXGE_OK;
555100161856Syc 	p_nxge_stats_t	statsp;
555200161856Syc 	uint8_t		phy_port_addr, portn;
555300161856Syc 	uint16_t	val;
555400161856Syc 
555500161856Syc 	*link_up = LINK_NO_CHANGE;
555600161856Syc 
555700161856Syc 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
555800161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
555900161856Syc 	statsp = nxgep->statsp;
556000161856Syc 
556100161856Syc 	/* Check if link is up */
556200161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
556300161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
556400161856Syc 	    != NXGE_OK) {
556500161856Syc 		goto fail;
556600161856Syc 	}
556700161856Syc 	/*
556800161856Syc 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
556900161856Syc 	 * portmode and link_speed
557000161856Syc 	 */
557100161856Syc 	if (val & TN1010_AN_LINK_STAT_BIT) {
557200161856Syc 		if (nxgep->link_notify ||
557300161856Syc 		    nxgep->statsp->mac_stats.link_up == 0) {
557400161856Syc 			statsp->mac_stats.link_up = 1;
557500161856Syc 			statsp->mac_stats.link_duplex = 2;
557600161856Syc 			*link_up = LINK_IS_UP;
557700161856Syc 			nxgep->link_notify = B_FALSE;
557800161856Syc 		}
557900161856Syc 	} else {
558000161856Syc 		if (nxgep->link_notify ||
558100161856Syc 		    nxgep->statsp->mac_stats.link_up == 1) {
558200161856Syc 			statsp->mac_stats.link_up = 0;
558300161856Syc 			statsp->mac_stats.link_speed = 0;
558400161856Syc 			statsp->mac_stats.link_duplex = 0;
558500161856Syc 			*link_up = LINK_IS_DOWN;
558600161856Syc 			nxgep->link_notify = B_FALSE;
558700161856Syc 		}
558800161856Syc 	}
558900161856Syc 	return (NXGE_OK);
559000161856Syc 
559100161856Syc fail:
559200161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
559300161856Syc 	    "nxge_tn1010_check: Unable to check TN1010"));
559400161856Syc 	return (status);
559544961713Sgirish }
559644961713Sgirish 
559700161856Syc 
559844961713Sgirish /* Set promiscous mode */
559944961713Sgirish 
560044961713Sgirish nxge_status_t
560144961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
560244961713Sgirish {
560344961713Sgirish 	nxge_status_t status = NXGE_OK;
560444961713Sgirish 
560559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
560644961713Sgirish 
560744961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
560844961713Sgirish 
560944961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
561044961713Sgirish 
561144961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
561244961713Sgirish 		goto fail;
561344961713Sgirish 	}
561444961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
561544961713Sgirish 		goto fail;
561644961713Sgirish 	}
561744961713Sgirish 
561844961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
561944961713Sgirish 
562044961713Sgirish 	if (on)
562144961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
562244961713Sgirish 	else
562344961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
562444961713Sgirish 
562544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
562644961713Sgirish 
562744961713Sgirish 	return (NXGE_OK);
562844961713Sgirish fail:
562944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
563044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
563159ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
563244961713Sgirish 
563344961713Sgirish 	return (status);
563444961713Sgirish }
563544961713Sgirish 
563644961713Sgirish /*ARGSUSED*/
563744961713Sgirish uint_t
563844961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
563944961713Sgirish {
564044961713Sgirish #ifdef	NXGE_DEBUG
564144961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
564244961713Sgirish #endif
564344961713Sgirish #if NXGE_MIF
564444961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
564544961713Sgirish 	uint32_t		status;
564644961713Sgirish 	npi_handle_t		handle;
564744961713Sgirish 	uint8_t			portn;
564844961713Sgirish 	p_nxge_stats_t		statsp;
564944961713Sgirish #endif
565044961713Sgirish 
565144961713Sgirish #ifdef	NXGE_MIF
565244961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
565344961713Sgirish 		nxgep = ldvp->nxgep;
565444961713Sgirish 	}
565544961713Sgirish 	nxgep = ldvp->nxgep;
565644961713Sgirish #endif
565744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
565844961713Sgirish 
565944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
566044961713Sgirish 	return (DDI_INTR_CLAIMED);
566144961713Sgirish 
566244961713Sgirish mif_intr_fail:
566344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
566444961713Sgirish 	return (DDI_INTR_UNCLAIMED);
566544961713Sgirish }
566644961713Sgirish 
566744961713Sgirish /*ARGSUSED*/
566844961713Sgirish uint_t
566944961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
567044961713Sgirish {
567144961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
567244961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
567344961713Sgirish 	p_nxge_ldg_t		ldgp;
567444961713Sgirish 	uint32_t		status;
567544961713Sgirish 	npi_handle_t		handle;
567644961713Sgirish 	uint8_t			portn;
567744961713Sgirish 	p_nxge_stats_t		statsp;
567844961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
567944961713Sgirish 
568044961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
568144961713Sgirish 		nxgep = ldvp->nxgep;
568244961713Sgirish 	}
568344961713Sgirish 
568444961713Sgirish 	ldgp = ldvp->ldgp;
568544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
568659ac0c16Sdavemq 	    "group %d", ldgp->ldg));
568744961713Sgirish 
568844961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
568944961713Sgirish 	/*
569044961713Sgirish 	 * This interrupt handler is for a specific
569144961713Sgirish 	 * mac port.
569244961713Sgirish 	 */
569344961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
569444961713Sgirish 	portn = nxgep->mac.portnum;
569544961713Sgirish 
569644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
569759ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
569844961713Sgirish 
569944961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
570044961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
570152ccf843Smisaki 		    (xmac_tx_iconfig_t *)&status);
570244961713Sgirish 		if (rs != NPI_SUCCESS)
570344961713Sgirish 			goto npi_fail;
570444961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
570544961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
570644961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
570744961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
570852ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
570944961713Sgirish 			}
571044961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
571144961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
5712f6485eecSyc 				/*
5713f6485eecSyc 				 * Do not send FMA ereport because this
5714f6485eecSyc 				 * error does not indicate HW failure.
5715f6485eecSyc 				 */
571644961713Sgirish 			}
571744961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
571844961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
571944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
572052ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
572144961713Sgirish 			}
572244961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
572344961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
572444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
572552ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
572644961713Sgirish 			}
572744961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
572844961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
572952ccf843Smisaki 				    XTXMAC_BYTE_CNT_MASK;
573044961713Sgirish 			}
573144961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
573244961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
573352ccf843Smisaki 				    XTXMAC_FRM_CNT_MASK;
573444961713Sgirish 			}
573544961713Sgirish 		}
573644961713Sgirish 
573744961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
573852ccf843Smisaki 		    (xmac_rx_iconfig_t *)&status);
573944961713Sgirish 		if (rs != NPI_SUCCESS)
574044961713Sgirish 			goto npi_fail;
574144961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
574244961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
574344961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
574444961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
574544961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
574644961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
574752ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
574844961713Sgirish 			}
5749f6485eecSyc 			/*
5750f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5751f6485eecSyc 			 * because they do not indicate HW failures.
5752f6485eecSyc 			 */
575344961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
575444961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
575552ccf843Smisaki 				    XRXMAC_CRC_ER_CNT_MASK;
575644961713Sgirish 			}
575744961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
575844961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
575952ccf843Smisaki 				    MAC_LEN_ER_CNT_MASK;
576044961713Sgirish 			}
576144961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
576244961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
576352ccf843Smisaki 				    XRXMAC_CD_VIO_CNT_MASK;
576444961713Sgirish 			}
576544961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
576644961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
576752ccf843Smisaki 				    XRXMAC_BT_CNT_MASK;
576844961713Sgirish 			}
576944961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
577044961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
577152ccf843Smisaki 				    XRXMAC_HIST_CNT1_MASK;
577244961713Sgirish 			}
577344961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
577444961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
577552ccf843Smisaki 				    XRXMAC_HIST_CNT2_MASK;
577644961713Sgirish 			}
577744961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
577844961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
577952ccf843Smisaki 				    XRXMAC_HIST_CNT3_MASK;
578044961713Sgirish 			}
578144961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
578244961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
578352ccf843Smisaki 				    XRXMAC_HIST_CNT4_MASK;
578444961713Sgirish 			}
578544961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
578644961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
578752ccf843Smisaki 				    XRXMAC_HIST_CNT5_MASK;
578844961713Sgirish 			}
578944961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
579044961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
579152ccf843Smisaki 				    XRXMAC_HIST_CNT6_MASK;
579244961713Sgirish 			}
579344961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
579444961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
579552ccf843Smisaki 				    XRXMAC_BC_FRM_CNT_MASK;
579644961713Sgirish 			}
579744961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
579844961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
579952ccf843Smisaki 				    XRXMAC_MC_FRM_CNT_MASK;
580044961713Sgirish 			}
5801f6485eecSyc 			/*
5802f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5803f6485eecSyc 			 * because they do not indicate HW failures.
5804f6485eecSyc 			 */
580544961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
580644961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
580752ccf843Smisaki 				    XRXMAC_FRAG_CNT_MASK;
580844961713Sgirish 			}
580944961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
581044961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
581152ccf843Smisaki 				    XRXMAC_AL_ER_CNT_MASK;
581244961713Sgirish 			}
581344961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
581444961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
581552ccf843Smisaki 				    XMAC_LINK_FLT_CNT_MASK;
581644961713Sgirish 			}
581744961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
581844961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
581944961713Sgirish 			}
582044961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
582144961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
582244961713Sgirish 			}
582344961713Sgirish 		}
582444961713Sgirish 
582544961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
582652ccf843Smisaki 		    (xmac_ctl_iconfig_t *)&status);
582744961713Sgirish 		if (rs != NPI_SUCCESS)
582844961713Sgirish 			goto npi_fail;
582944961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
583044961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
583144961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
583244961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
583344961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
583444961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
583544961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
583644961713Sgirish 		}
583744961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
583844961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
583952ccf843Smisaki 		    (bmac_tx_iconfig_t *)&status);
584044961713Sgirish 		if (rs != NPI_SUCCESS)
584144961713Sgirish 			goto npi_fail;
584244961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
584344961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
584444961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
584544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
584652ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
584744961713Sgirish 			}
584844961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
584944961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
585044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
585152ccf843Smisaki 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
585244961713Sgirish 			}
585344961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
585444961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
585552ccf843Smisaki 				    BTXMAC_BYTE_CNT_MASK;
585644961713Sgirish 			}
585744961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
585844961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
585952ccf843Smisaki 				    BTXMAC_FRM_CNT_MASK;
586044961713Sgirish 			}
586144961713Sgirish 		}
586244961713Sgirish 
586344961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
586452ccf843Smisaki 		    (bmac_rx_iconfig_t *)&status);
586544961713Sgirish 		if (rs != NPI_SUCCESS)
586644961713Sgirish 			goto npi_fail;
586744961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
586844961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
586944961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
587044961713Sgirish 			}
587144961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
587244961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
587352ccf843Smisaki 				    RXMAC_FRM_CNT_MASK;
587444961713Sgirish 			}
587544961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
587644961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
587752ccf843Smisaki 				    BMAC_CRC_ER_CNT_MASK;
587844961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
587952ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
588044961713Sgirish 			}
588144961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
588244961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
588352ccf843Smisaki 				    MAC_LEN_ER_CNT_MASK;
588444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
588552ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
588644961713Sgirish 			}
588744961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
588844961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
588952ccf843Smisaki 				    BMAC_CD_VIO_CNT_MASK;
589044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
589152ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
589244961713Sgirish 			}
589344961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
589444961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
589552ccf843Smisaki 				    BRXMAC_BYTE_CNT_MASK;
589644961713Sgirish 			}
589744961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
589844961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
589952ccf843Smisaki 				    BMAC_AL_ER_CNT_MASK;
590044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
590152ccf843Smisaki 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
590244961713Sgirish 			}
590344961713Sgirish 
590444961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
590552ccf843Smisaki 			    (bmac_ctl_iconfig_t *)&status);
590644961713Sgirish 			if (rs != NPI_SUCCESS)
590744961713Sgirish 				goto npi_fail;
590844961713Sgirish 
590944961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
591044961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
591144961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
591244961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
591344961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
591444961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
591544961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
591644961713Sgirish 			}
591744961713Sgirish 		}
591844961713Sgirish 
591944961713Sgirish 	if (ldgp->nldvs == 1) {
592044961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
592152ccf843Smisaki 		    B_TRUE, ldgp->ldg_timer);
592244961713Sgirish 	}
592344961713Sgirish 
592444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
592544961713Sgirish 	return (DDI_INTR_CLAIMED);
592644961713Sgirish 
592744961713Sgirish npi_fail:
592844961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
592944961713Sgirish 	return (DDI_INTR_UNCLAIMED);
593044961713Sgirish }
593144961713Sgirish 
593244961713Sgirish nxge_status_t
593344961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
593444961713Sgirish {
593544961713Sgirish 	uint8_t		phy_port_addr;
593644961713Sgirish 	nxge_status_t	status = NXGE_OK;
593744961713Sgirish 	boolean_t	rx_sig_ok;
593844961713Sgirish 	boolean_t	pcs_blk_lock;
593944961713Sgirish 	boolean_t	link_align;
594044961713Sgirish 	uint16_t	val1, val2, val3;
594144961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
594244961713Sgirish 	uint16_t	val_debug;
594344961713Sgirish 	uint16_t	val;
594444961713Sgirish #endif
594544961713Sgirish 
594644961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
594744961713Sgirish 
594844961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
594944961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
595044961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
595144961713Sgirish 	if ((val_debug & ~0x200) != 0) {
595244961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
595352ccf843Smisaki 		    nxgep->mac.portnum, val_debug);
595444961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
595552ccf843Smisaki 		    &val_debug);
595644961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
595752ccf843Smisaki 		    nxgep->mac.portnum, val_debug);
595844961713Sgirish 	}
595944961713Sgirish 
596044961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
596152ccf843Smisaki 	    XPCS_REG_DESCWERR_COUNTER, &val);
596244961713Sgirish 	if (val != 0)
596344961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
596444961713Sgirish 
596544961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
596652ccf843Smisaki 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
596744961713Sgirish 	if (val != 0)
596844961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
596944961713Sgirish 
597044961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
597152ccf843Smisaki 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
597244961713Sgirish 	if (val != 0)
597344961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
597444961713Sgirish #endif
597544961713Sgirish 
597644961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
597744961713Sgirish 
597844961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
597952ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
598052ccf843Smisaki 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
598144961713Sgirish 	if (status != NXGE_OK)
598244961713Sgirish 		goto fail;
598344961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
598444961713Sgirish 
598544961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
598652ccf843Smisaki 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
598752ccf843Smisaki 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
598844961713Sgirish 		goto fail;
598944961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
599044961713Sgirish 
599144961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
599252ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
599352ccf843Smisaki 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
599444961713Sgirish 	if (status != NXGE_OK)
599544961713Sgirish 		goto fail;
59962d17280bSsbehera 
59972d17280bSsbehera 	switch (nxgep->chip_id) {
59982d17280bSsbehera 	case BCM8704_CHIP_ID:
59992d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
60002d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
60012d17280bSsbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
60022d17280bSsbehera 		break;
60032d17280bSsbehera 	case BCM8706_CHIP_ID:
60042d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
60052d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
60062d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
60072d17280bSsbehera 		    B_TRUE : B_FALSE;
60082d17280bSsbehera 		break;
60092d17280bSsbehera 	default:
60102d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
60112d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
60122d17280bSsbehera 		goto fail;
60132d17280bSsbehera 	}
60142d17280bSsbehera 
601544961713Sgirish 
601644961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
601744961713Sgirish 	/* Temp workaround for link down issue */
601844961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
601944961713Sgirish 		if (val2 != 0x4) {
602044961713Sgirish 			pcs_blk_lock = B_TRUE;
602152ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
602252ccf843Smisaki 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
602344961713Sgirish 		}
602444961713Sgirish 	}
602544961713Sgirish 
602644961713Sgirish 	if (link_align == B_FALSE) {
602744961713Sgirish 		if (val3 != 0x140f) {
602844961713Sgirish 			link_align = B_TRUE;
602952ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
603052ccf843Smisaki 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
603144961713Sgirish 		}
603244961713Sgirish 	}
603344961713Sgirish 
603444961713Sgirish 	if (rx_sig_ok == B_FALSE) {
603544961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
603644961713Sgirish 			rx_sig_ok = B_TRUE;
603744961713Sgirish 			cmn_err(CE_NOTE,
603852ccf843Smisaki 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
603952ccf843Smisaki 			    nxgep->mac.portnum);
604044961713Sgirish 		}
604144961713Sgirish 	}
604244961713Sgirish #endif
604344961713Sgirish 
604444961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
604552ccf843Smisaki 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
604644961713Sgirish 
604744961713Sgirish 	return (NXGE_OK);
604844961713Sgirish fail:
604944961713Sgirish 	return (status);
605044961713Sgirish }
605144961713Sgirish 
605252cdd236Ssbehera static nxge_status_t
605300161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
605452cdd236Ssbehera {
605552cdd236Ssbehera 	uint8_t		phy;
605652cdd236Ssbehera 	nxge_status_t   status = NXGE_OK;
605752cdd236Ssbehera 	boolean_t	pma_status;
605852cdd236Ssbehera 	boolean_t	pcs_status;
605952cdd236Ssbehera 	boolean_t	xgxs_status;
606052cdd236Ssbehera 	uint16_t	val;
606152cdd236Ssbehera 
606252cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
606352cdd236Ssbehera 
606452cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
606552cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
606652cdd236Ssbehera 
606752cdd236Ssbehera 	*link_up = B_FALSE;
606852cdd236Ssbehera 
606952cdd236Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
607052cdd236Ssbehera 
607152cdd236Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
607252cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
607352cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
607452cdd236Ssbehera 
607552cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
607652cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
607752cdd236Ssbehera 
607852cdd236Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
607952cdd236Ssbehera 
608052cdd236Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
608152cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
608252cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
608352cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
608452cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
608552cdd236Ssbehera 
608652cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
608752cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
608852cdd236Ssbehera 
608952cdd236Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
609052cdd236Ssbehera 
609152cdd236Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
609252cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
609352cdd236Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
609452cdd236Ssbehera 
609552cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
609652cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
609752cdd236Ssbehera 
609852cdd236Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
609952cdd236Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
610052cdd236Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
610152cdd236Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
610252cdd236Ssbehera 
610352cdd236Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
610452cdd236Ssbehera 	    B_TRUE : B_FALSE;
610552cdd236Ssbehera 
610652cdd236Ssbehera fail:
610752cdd236Ssbehera 
610852cdd236Ssbehera 	if (*link_up == B_FALSE) {
610952cdd236Ssbehera 		/* PCS OFF */
611052cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
611152cdd236Ssbehera 	} else {
611252cdd236Ssbehera 		/* PCS Activity */
611352cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
611452cdd236Ssbehera 	}
611552cdd236Ssbehera 
611652cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
611752cdd236Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
611852cdd236Ssbehera 
611952cdd236Ssbehera 	return (status);
612052cdd236Ssbehera }
612152cdd236Ssbehera 
612259ac0c16Sdavemq nxge_status_t
612359ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
612459ac0c16Sdavemq {
612559ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
612659ac0c16Sdavemq 	    != NPI_SUCCESS)
612759ac0c16Sdavemq 		return (NXGE_ERROR);
612859ac0c16Sdavemq 	else
612959ac0c16Sdavemq 		return (NXGE_OK);
613059ac0c16Sdavemq }
613144961713Sgirish 
613244961713Sgirish nxge_status_t
613359ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
613444961713Sgirish {
613559ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
613659ac0c16Sdavemq 	    != NPI_SUCCESS)
613759ac0c16Sdavemq 		return (NXGE_ERROR);
613859ac0c16Sdavemq 	else
613959ac0c16Sdavemq 		return (NXGE_OK);
614059ac0c16Sdavemq }
614144961713Sgirish 
61422d17280bSsbehera static boolean_t
61432d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
61442d17280bSsbehera {
61452d17280bSsbehera 	uint32_t pma_pmd_id = 0;
61462d17280bSsbehera 	uint32_t pcs_id = 0;
61472d17280bSsbehera 	uint32_t phy_id = 0;
61482d17280bSsbehera 
61492d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
61502d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61512d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
61522d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
61532d17280bSsbehera 		goto found_phy;
61542d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
61552d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61562d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
61572d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
61582d17280bSsbehera 		goto found_phy;
61592d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
61602d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61612d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
61622d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
61632d17280bSsbehera 		goto found_phy;
61642d17280bSsbehera 
61652d17280bSsbehera 	return (B_FALSE);
61662d17280bSsbehera 
61672d17280bSsbehera found_phy:
61682d17280bSsbehera 	return (B_TRUE);
61692d17280bSsbehera }
61702d17280bSsbehera 
617159ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
617259ac0c16Sdavemq 
617359ac0c16Sdavemq static boolean_t
617459ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
617559ac0c16Sdavemq {
617659ac0c16Sdavemq 	int		i;
617759ac0c16Sdavemq 	boolean_t	found = B_FALSE;
617859ac0c16Sdavemq 
617959ac0c16Sdavemq 	switch (type) {
618059ac0c16Sdavemq 	case CLAUSE_45_TYPE:
618100161856Syc 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
618200161856Syc 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
618300161856Syc 			    (id & BCM_PHY_ID_MASK)) ||
618400161856Syc 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
618559ac0c16Sdavemq 				found = B_TRUE;
618659ac0c16Sdavemq 				break;
618759ac0c16Sdavemq 			}
618859ac0c16Sdavemq 		}
618959ac0c16Sdavemq 		break;
619059ac0c16Sdavemq 	case CLAUSE_22_TYPE:
619100161856Syc 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
619230505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
619330505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
619459ac0c16Sdavemq 				found = B_TRUE;
619559ac0c16Sdavemq 				break;
619656d930aeSspeer 			}
619744961713Sgirish 		}
619859ac0c16Sdavemq 		break;
619959ac0c16Sdavemq 	default:
620059ac0c16Sdavemq 		break;
620156d930aeSspeer 	}
620256d930aeSspeer 
620359ac0c16Sdavemq 	return (found);
620459ac0c16Sdavemq }
620559ac0c16Sdavemq 
62062e59129aSraghus static uint32_t
62072e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
62082e59129aSraghus {
62092e59129aSraghus 	uint16_t	val1 = 0;
62102e59129aSraghus 	uint16_t	val2 = 0;
62112e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
62122e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62132e59129aSraghus 
621453560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62152e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
62162e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
62172e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
62182e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
621953560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62202e59129aSraghus 
622100161856Syc 	/* Concatenate the Device ID stored in two registers. */
62222e59129aSraghus 	pma_pmd_dev_id = val1;
62232e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
62242e59129aSraghus 	pma_pmd_dev_id |= val2;
62252e59129aSraghus 
62262e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
62272e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
62282e59129aSraghus 
62292e59129aSraghus 	return (pma_pmd_dev_id);
62302e59129aSraghus }
62312e59129aSraghus 
62322e59129aSraghus static uint32_t
62332e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
62342e59129aSraghus {
62352e59129aSraghus 	uint16_t	val1 = 0;
62362e59129aSraghus 	uint16_t	val2 = 0;
62372e59129aSraghus 	uint32_t	pcs_dev_id = 0;
62382e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62392e59129aSraghus 
624053560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62412e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
62422e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
62432e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
62442e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
624553560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62462e59129aSraghus 
62472e59129aSraghus 	pcs_dev_id = val1;
62482e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
62492e59129aSraghus 	pcs_dev_id |= val2;
62502e59129aSraghus 
62512e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
62522e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
62532e59129aSraghus 
62542e59129aSraghus 	return (pcs_dev_id);
62552e59129aSraghus }
62562e59129aSraghus 
62572e59129aSraghus static uint32_t
62582e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
62592e59129aSraghus {
62602e59129aSraghus 	uint16_t	val1 = 0;
62612e59129aSraghus 	uint16_t	val2 = 0;
62622e59129aSraghus 	uint32_t	phy_id = 0;
62632e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62642e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
62652e59129aSraghus 
6266321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62672e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
62682e59129aSraghus 	    &val1);
62692e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
62702e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62712e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
62722e59129aSraghus 		goto exit;
62732e59129aSraghus 	}
62742e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
62752e59129aSraghus 	    &val2);
62762e59129aSraghus 	if (npi_status != 0) {
62772e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62782e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
62792e59129aSraghus 		goto exit;
62802e59129aSraghus 	}
62812e59129aSraghus 	phy_id = val1;
62822e59129aSraghus 	phy_id = (phy_id << 16);
62832e59129aSraghus 	phy_id |= val2;
62842e59129aSraghus 
62852e59129aSraghus exit:
6286321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62872e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
62882e59129aSraghus 	    phy_port, phy_id));
62892e59129aSraghus 
62902e59129aSraghus 	return (phy_id);
62912e59129aSraghus }
62922e59129aSraghus 
629359ac0c16Sdavemq /*
629459ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
629559ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
629659ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
629759ac0c16Sdavemq  * and the Neptune type.
629800161856Syc  *
629900161856Syc  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
630000161856Syc  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
630100161856Syc  * in case the portmode information is not available via OBP, nxge.conf,
630200161856Syc  * VPD or SEEPROM.
630359ac0c16Sdavemq  */
630459ac0c16Sdavemq nxge_status_t
630559ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
630659ac0c16Sdavemq {
630759a835ddSjoycey 	int		i, j, l;
630859ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
630959ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
631059ac0c16Sdavemq 	uint32_t	phy_id = 0;
631130505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
631230505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
631330505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
631459ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
631559ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
63162d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
63172d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
631859ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
631900161856Syc 	uint8_t		num_xaui;
632059ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
632156d930aeSspeer 
632259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
632356d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
632459ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
632559ac0c16Sdavemq 	    nxgep->niu_type));
632659ac0c16Sdavemq 
6327678453a8Sspeer 	if (isLDOMguest(nxgep)) {
6328678453a8Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
6329678453a8Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
6330678453a8Sspeer 		return (NXGE_OK);
6331678453a8Sspeer 	}
6332678453a8Sspeer 
633359a835ddSjoycey 	j = l = 0;
633459ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
633556d930aeSspeer 	/*
633623b952a3SSantwona Behera 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
633723b952a3SSantwona Behera 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
633856d930aeSspeer 	 */
633959ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
63402e59129aSraghus 
63412e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
634259ac0c16Sdavemq 
634359ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
634459ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
634559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
634652cdd236Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
634730505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
634800161856Syc 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
634900161856Syc 				    == TN1010_DEV_ID) {
635000161856Syc 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
635100161856Syc 				} else {
635200161856Syc 					port_pma_pmd_dev_id[j] =
635352ccf843Smisaki 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
635400161856Syc 				}
63552d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
635659ac0c16Sdavemq 				j++;
635759ac0c16Sdavemq 			}
635859ac0c16Sdavemq 		} else {
635959ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
636059ac0c16Sdavemq 		}
636159ac0c16Sdavemq 
63622e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
636359ac0c16Sdavemq 
636459ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
636559ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
636659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
636752cdd236Ssbehera 			    "dev %x found", i, pcs_dev_id));
636859a835ddSjoycey 			if (pma_pmd_dev_fd[i] == 1) {
636900161856Syc 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
637000161856Syc 				    == TN1010_DEV_ID) {
637100161856Syc 					port_pcs_dev_id[j - 1] =
637200161856Syc 					    TN1010_DEV_ID;
637300161856Syc 				} else {
637400161856Syc 					port_pcs_dev_id[j - 1] =
637500161856Syc 					    pcs_dev_id &
637600161856Syc 					    BCM_PHY_ID_MASK;
637700161856Syc 				}
637859a835ddSjoycey 			} else {
637959a835ddSjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
638000161856Syc 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
638152ccf843Smisaki 					    == TN1010_DEV_ID) {
638200161856Syc 						port_pcs_dev_id[j] =
638300161856Syc 						    TN1010_DEV_ID;
638400161856Syc 					} else {
638500161856Syc 						port_pcs_dev_id[j] =
638600161856Syc 						    pcs_dev_id &
638700161856Syc 						    BCM_PHY_ID_MASK;
638800161856Syc 					}
638959a835ddSjoycey 					port_fd_arr[j] = (uint8_t)i;
639059a835ddSjoycey 					j++;
639159a835ddSjoycey 				}
639259ac0c16Sdavemq 			}
639359ac0c16Sdavemq 		} else {
639459ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
639559ac0c16Sdavemq 		}
639659ac0c16Sdavemq 
63972d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
63982d17280bSsbehera 			total_port_fd ++;
63992d17280bSsbehera 		}
640059ac0c16Sdavemq 
64012e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
640259ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
64032d17280bSsbehera 			total_phy_fd ++;
640459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
640552cdd236Ssbehera 			    "%x found", i, phy_id));
640630505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
640700161856Syc 				if ((phy_id & TN1010_DEV_ID_MASK)
640800161856Syc 				    == TN1010_DEV_ID) {
640900161856Syc 					port_phy_id[l] = TN1010_DEV_ID;
641000161856Syc 				} else {
641100161856Syc 					port_phy_id[l]
641200161856Syc 					    = phy_id & BCM_PHY_ID_MASK;
641300161856Syc 				}
64142d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
641559ac0c16Sdavemq 				l++;
641659ac0c16Sdavemq 			}
641759ac0c16Sdavemq 		}
641859ac0c16Sdavemq 	}
641959ac0c16Sdavemq 
642059ac0c16Sdavemq 	switch (total_port_fd) {
642159ac0c16Sdavemq 	case 2:
642259ac0c16Sdavemq 		switch (total_phy_fd) {
642359ac0c16Sdavemq 		case 2:
642423b952a3SSantwona Behera 			/* 2 10G, 2 1G RGMII Fiber / copper */
642559a835ddSjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
642659a835ddSjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
642759a835ddSjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
642859a835ddSjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
642959a835ddSjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
643059a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
643159a835ddSjoycey 
643223b952a3SSantwona Behera 				switch (hw_p->platform_type) {
643323b952a3SSantwona Behera 				case P_NEPTUNE_ROCK:
643423b952a3SSantwona Behera 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
643523b952a3SSantwona Behera 					/*
643623b952a3SSantwona Behera 					 * ROCK platform has assigned a lower
643723b952a3SSantwona Behera 					 * addr to port 1. (port 0 = 0x9 and
643823b952a3SSantwona Behera 					 * port 1 = 0x8).
643923b952a3SSantwona Behera 					 */
644023b952a3SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
644123b952a3SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[1];
644223b952a3SSantwona Behera 
644323b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
644423b952a3SSantwona Behera 					    "Rock with 2 10G, 2 1GC"));
644523b952a3SSantwona Behera 					break;
644623b952a3SSantwona Behera 
644723b952a3SSantwona Behera 				case P_NEPTUNE_NONE:
644823b952a3SSantwona Behera 				default:
644923b952a3SSantwona Behera 					hw_p->platform_type =
645023b952a3SSantwona Behera 					    P_NEPTUNE_GENERIC;
645123b952a3SSantwona Behera 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
645259a835ddSjoycey 
645323b952a3SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
645423b952a3SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[1];
645523b952a3SSantwona Behera 
645623b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
645723b952a3SSantwona Behera 					    "ARTM card with 2 10G, 2 1GF"));
645823b952a3SSantwona Behera 					break;
645923b952a3SSantwona Behera 				}
646059a835ddSjoycey 
646159a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
646259a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
646359a835ddSjoycey 
646459a835ddSjoycey 			} else {
646559a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
646659a835ddSjoycey 				    "Unsupported neptune type 1"));
646759a835ddSjoycey 				goto error_exit;
646859a835ddSjoycey 			}
646959a835ddSjoycey 			break;
647059a835ddSjoycey 
647159ac0c16Sdavemq 		case 1:
647259ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
647359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
647459ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
647559ac0c16Sdavemq 			goto error_exit;
647659ac0c16Sdavemq 		case 0:
647700161856Syc 			/*
647800161856Syc 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
647900161856Syc 			 * cards, etc.
648000161856Syc 			 */
648130505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
648230505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
648330505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
648452cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
648552cdd236Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
648652cdd236Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
648752cdd236Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
648852cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
648952cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] ==
649052cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
64912e59129aSraghus 
64922e59129aSraghus 				/*
64932e59129aSraghus 				 * Check the first phy port address against
64942e59129aSraghus 				 * the known phy start addresses to determine
64952e59129aSraghus 				 * the platform type.
64962e59129aSraghus 				 */
64972d17280bSsbehera 
64982d17280bSsbehera 				switch (port_fd_arr[0]) {
649900161856Syc 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
650052cdd236Ssbehera 					/*
650152cdd236Ssbehera 					 * The Marvell case also falls into
650252cdd236Ssbehera 					 * this case as
650352cdd236Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
650400161856Syc 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
650552cdd236Ssbehera 					 * This is OK for the 2 10G case.
650652cdd236Ssbehera 					 */
65072e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
65082e59129aSraghus 					hw_p->platform_type =
65092e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
65102d17280bSsbehera 					break;
651100161856Syc 				case GOA_CLAUSE45_PORT_ADDR_BASE:
65122d17280bSsbehera 					if (hw_p->platform_type !=
65132d17280bSsbehera 					    P_NEPTUNE_NIU) {
65142d17280bSsbehera 						hw_p->platform_type =
65152d17280bSsbehera 						    P_NEPTUNE_GENERIC;
65162d17280bSsbehera 						hw_p->niu_type =
65172d17280bSsbehera 						    NEPTUNE_2_10GF;
65182d17280bSsbehera 					}
65192d17280bSsbehera 					break;
65202d17280bSsbehera 				default:
65212d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
65222e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
65232e59129aSraghus 					goto error_exit;
65242e59129aSraghus 				}
65252d17280bSsbehera 
65262d17280bSsbehera 				for (i = 0; i < 2; i++) {
65272d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
65282d17280bSsbehera 				}
652900161856Syc 
653000161856Syc 			/* Both XAUI slots have copper XAUI cards */
653100161856Syc 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
653200161856Syc 			    == TN1010_DEV_ID) &&
653300161856Syc 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
653400161856Syc 			    == TN1010_DEV_ID)) ||
653500161856Syc 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
653600161856Syc 			    == TN1010_DEV_ID) &&
653700161856Syc 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
653800161856Syc 			    == TN1010_DEV_ID))) {
653900161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010;
654000161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
654100161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
654200161856Syc 
654300161856Syc 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
654400161856Syc 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
654500161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
654600161856Syc 			    == TN1010_DEV_ID) ||
654700161856Syc 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
654800161856Syc 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
654900161856Syc 			    TN1010_DEV_ID)) {
655000161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
655100161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
655200161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
655300161856Syc 
655400161856Syc 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
655500161856Syc 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
655600161856Syc 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
655700161856Syc 			    == TN1010_DEV_ID) ||
655800161856Syc 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
655900161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
656000161856Syc 			    == TN1010_DEV_ID)) {
656100161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
656200161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
656300161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
656400161856Syc 
656559ac0c16Sdavemq 			} else {
656659ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
656759ac0c16Sdavemq 				    "Unsupported neptune type 2"));
656859ac0c16Sdavemq 				goto error_exit;
656959ac0c16Sdavemq 			}
657059ac0c16Sdavemq 			break;
657100161856Syc 
657259ac0c16Sdavemq 		case 4:
657300161856Syc 			if (nxge_get_num_of_xaui(
657400161856Syc 			    port_pma_pmd_dev_id, port_pcs_dev_id,
657500161856Syc 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
657600161856Syc 				goto error_exit;
657700161856Syc 			}
657800161856Syc 			if (num_xaui != 2)
657900161856Syc 				goto error_exit;
658059ac0c16Sdavemq 
658100161856Syc 			/*
658200161856Syc 			 *  Maramba with 2 XAUIs (either fiber or copper)
658300161856Syc 			 *
658400161856Syc 			 * Check the first phy port address against
658500161856Syc 			 * the known phy start addresses to determine
658600161856Syc 			 * the platform type.
658700161856Syc 			 */
658800161856Syc 			switch (phy_fd_arr[0]) {
658900161856Syc 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
659000161856Syc 				hw_p->platform_type =
659100161856Syc 				    P_NEPTUNE_MARAMBA_P0;
659200161856Syc 				break;
659300161856Syc 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
659400161856Syc 				hw_p->platform_type =
659500161856Syc 				    P_NEPTUNE_MARAMBA_P1;
659600161856Syc 				break;
659700161856Syc 			default:
659800161856Syc 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
659900161856Syc 				    "Unknown port %d...Cannot "
660000161856Syc 				    "determine platform type", i));
660100161856Syc 				goto error_exit;
660200161856Syc 			}
66032d17280bSsbehera 
660400161856Syc 			hw_p->xcvr_addr[0] = port_fd_arr[0];
660500161856Syc 			hw_p->xcvr_addr[1] = port_fd_arr[1];
660600161856Syc 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
660700161856Syc 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
660800161856Syc 
660900161856Syc 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
661000161856Syc 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
661100161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
661200161856Syc 			    == TN1010_DEV_ID) {
661300161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
661400161856Syc 
661500161856Syc 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
661600161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
661700161856Syc 			    == TN1010_DEV_ID) &&
661800161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
661900161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
662000161856Syc 
662100161856Syc 			/* Both slots have fiber XAUI */
662200161856Syc 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
662300161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
66242e59129aSraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
66252e59129aSraghus 
662600161856Syc 			/* Both slots have copper XAUI */
662700161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
662800161856Syc 			    == TN1010_DEV_ID) &&
662900161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
663000161856Syc 			    == TN1010_DEV_ID) {
663100161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
66322d17280bSsbehera 
663359ac0c16Sdavemq 			} else {
663459ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
663559ac0c16Sdavemq 				    "Unsupported neptune type 3"));
663659ac0c16Sdavemq 				goto error_exit;
663759ac0c16Sdavemq 			}
663859ac0c16Sdavemq 			break;
663959ac0c16Sdavemq 		default:
664059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
664159ac0c16Sdavemq 			    "Unsupported neptune type 5"));
664259ac0c16Sdavemq 			goto error_exit;
664359ac0c16Sdavemq 		}
664430505775Ssbehera 		break;
664500161856Syc 	case 1: 	/* Only one clause45 port */
664600161856Syc 		switch (total_phy_fd) {	/* Number of clause22 ports */
664759ac0c16Sdavemq 		case 3:
66482e59129aSraghus 			/*
66492e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
66502e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
66512e59129aSraghus 			 * 1_10G_3_1G
66522e59129aSraghus 			 */
66532e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66542e59129aSraghus 			    "Unsupported neptune type 7"));
66552e59129aSraghus 			goto error_exit;
665659ac0c16Sdavemq 		case 2:
665759ac0c16Sdavemq 			/*
665859ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
665959ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
666059ac0c16Sdavemq 			 * 1_10G_2_1G
666159ac0c16Sdavemq 			 */
666259ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
666359ac0c16Sdavemq 			    "Unsupported neptune type 8"));
666459ac0c16Sdavemq 			goto error_exit;
666559ac0c16Sdavemq 		case 1:
666659ac0c16Sdavemq 			/*
666759ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
666859ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
666959ac0c16Sdavemq 			 * 1_10G_1_1G
667059ac0c16Sdavemq 			 */
667159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
667259ac0c16Sdavemq 			    "Unsupported neptune type 9"));
667359ac0c16Sdavemq 			goto error_exit;
667400161856Syc 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
667500161856Syc 			/* Fiber XAUI */
66762d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
66772d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
66782d17280bSsbehera 
66792d17280bSsbehera 				/*
66802d17280bSsbehera 				 * Check the first phy port address against
66812d17280bSsbehera 				 * the known phy start addresses to determine
66822d17280bSsbehera 				 * the platform type.
66832d17280bSsbehera 				 */
66842d17280bSsbehera 
66852d17280bSsbehera 				switch (port_fd_arr[0]) {
668600161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
668700161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
668800161856Syc 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
668900161856Syc 					/*
669000161856Syc 					 * If hw_p->platform_type ==
669100161856Syc 					 * P_NEPTUNE_NIU, then portmode
669200161856Syc 					 * is already known, so there is
669300161856Syc 					 * no need to figure out hw_p->
669400161856Syc 					 * platform_type because
669500161856Syc 					 * platform_type is only for
669600161856Syc 					 * figuring out portmode.
669700161856Syc 					 */
66982d17280bSsbehera 					if (hw_p->platform_type !=
66992d17280bSsbehera 					    P_NEPTUNE_NIU) {
67002d17280bSsbehera 						hw_p->platform_type =
67012d17280bSsbehera 						    P_NEPTUNE_GENERIC;
67022d17280bSsbehera 						hw_p->niu_type =
67032d17280bSsbehera 						    NEPTUNE_2_10GF;
67042d17280bSsbehera 					}
67052d17280bSsbehera 					break;
67062d17280bSsbehera 				default:
67072d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67082d17280bSsbehera 					    "Unsupported neptune type 10"));
67092d17280bSsbehera 					goto error_exit;
67102d17280bSsbehera 				}
6711321febdeSsbehera 				/*
6712321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
6713321febdeSsbehera 				 * phy address to function number mapping
6714321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
6715321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
6716321febdeSsbehera 				 * But for Huron XAUI, the assignment should
6717321febdeSsbehera 				 * be by function number, i.e., whichever
6718321febdeSsbehera 				 * function number attaches should be
6719321febdeSsbehera 				 * assigned the available PHY (this is required
6720321febdeSsbehera 				 * primarily to support pre-production Huron
6721321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
6722321febdeSsbehera 				 */
6723321febdeSsbehera 				if (port_fd_arr[0] ==
672400161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
6725321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
6726321febdeSsbehera 				} else {
6727321febdeSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
6728321febdeSsbehera 					    port_fd_arr[0];
6729321febdeSsbehera 				}
673000161856Syc 
673100161856Syc 			/* A 10G copper XAUI in either slot0 or slot1 */
673200161856Syc 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
673300161856Syc 			    == TN1010_DEV_ID ||
673400161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
673500161856Syc 			    == TN1010_DEV_ID) {
673600161856Syc 				switch (port_fd_arr[0]) {
673700161856Syc 				/* The XAUI is in slot0 */
673800161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
673900161856Syc 					hw_p->niu_type = NEPTUNE_1_TN1010;
674000161856Syc 					break;
674100161856Syc 
674200161856Syc 				/* The XAUI is in slot1 */
674300161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
674400161856Syc 					hw_p->niu_type
674500161856Syc 					    = NEPTUNE_1_NONE_1_TN1010;
674600161856Syc 					break;
674700161856Syc 				default:
674800161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
674900161856Syc 					    "Unsupported XAUI port address"));
675000161856Syc 					goto error_exit;
675100161856Syc 				}
675200161856Syc 				hw_p->xcvr_addr[nxgep->function_num]
675300161856Syc 				    = port_fd_arr[0];
675400161856Syc 
67552d17280bSsbehera 			} else {
67562d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
675700161856Syc 				    "Unsupported PHY type"));
67582d17280bSsbehera 				goto error_exit;
67592d17280bSsbehera 			}
67602d17280bSsbehera 			break;
676100161856Syc 		case 4: /* Maramba always have 4 clause 45 ports */
676259ac0c16Sdavemq 
676300161856Syc 			/* Maramba with 1 XAUI */
676452ccf843Smisaki 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
676552ccf843Smisaki 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
676600161856Syc 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
676752ccf843Smisaki 			    != TN1010_DEV_ID) &&
676800161856Syc 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
676952ccf843Smisaki 			    != TN1010_DEV_ID)) {
677052ccf843Smisaki 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
677152ccf843Smisaki 				    "Unsupported neptune type 12"));
677252ccf843Smisaki 				goto error_exit;
677352ccf843Smisaki 			}
67742e59129aSraghus 
677552ccf843Smisaki 			/*
677652ccf843Smisaki 			 * Check the first phy port address against
677752ccf843Smisaki 			 * the known phy start addresses to determine
677852ccf843Smisaki 			 * the platform type.
677952ccf843Smisaki 			 */
678052ccf843Smisaki 			switch (phy_fd_arr[0]) {
678152ccf843Smisaki 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
678252ccf843Smisaki 				hw_p->platform_type =
678352ccf843Smisaki 				    P_NEPTUNE_MARAMBA_P0;
678452ccf843Smisaki 				break;
678552ccf843Smisaki 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
678652ccf843Smisaki 				hw_p->platform_type =
678752ccf843Smisaki 				    P_NEPTUNE_MARAMBA_P1;
678852ccf843Smisaki 				break;
678952ccf843Smisaki 			default:
679052ccf843Smisaki 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
679152ccf843Smisaki 				    "Unknown port %d...Cannot "
679252ccf843Smisaki 				    "determine platform type 10 - 2",
679352ccf843Smisaki 				    i));
679452ccf843Smisaki 				goto error_exit;
679552ccf843Smisaki 			}
679652ccf843Smisaki 
679752ccf843Smisaki 			/*
679852ccf843Smisaki 			 * Check the clause45 address to determine
679952ccf843Smisaki 			 * if XAUI is in port 0 or port 1.
680052ccf843Smisaki 			 */
680152ccf843Smisaki 			switch (port_fd_arr[0]) {
680252ccf843Smisaki 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
680352ccf843Smisaki 				if (port_pcs_dev_id[0]
680452ccf843Smisaki 				    == PHY_BCM8704_FAMILY ||
680552ccf843Smisaki 				    port_pma_pmd_dev_id[0]
680652ccf843Smisaki 				    == PHY_BCM8704_FAMILY) {
680752ccf843Smisaki 					hw_p->niu_type
680852ccf843Smisaki 					    = NEPTUNE_1_10GF_3_1GC;
680952ccf843Smisaki 				} else {
681052ccf843Smisaki 					hw_p->niu_type
681152ccf843Smisaki 					    = NEPTUNE_1_TN1010_3_1GC;
681259ac0c16Sdavemq 				}
681352ccf843Smisaki 				hw_p->xcvr_addr[0] = port_fd_arr[0];
681452ccf843Smisaki 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
681552ccf843Smisaki 					hw_p->xcvr_addr[i] =
681652ccf843Smisaki 					    phy_fd_arr[i];
681752ccf843Smisaki 				}
681852ccf843Smisaki 				break;
681952ccf843Smisaki 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
682052ccf843Smisaki 				if (port_pcs_dev_id[0]
682152ccf843Smisaki 				    == PHY_BCM8704_FAMILY ||
682252ccf843Smisaki 				    port_pma_pmd_dev_id[0]
682352ccf843Smisaki 				    == PHY_BCM8704_FAMILY) {
682452ccf843Smisaki 					hw_p->niu_type =
682552ccf843Smisaki 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
682652ccf843Smisaki 				} else {
682752ccf843Smisaki 					hw_p->niu_type =
682852ccf843Smisaki 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
682952ccf843Smisaki 				}
683052ccf843Smisaki 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
683152ccf843Smisaki 				hw_p->xcvr_addr[1] = port_fd_arr[0];
683252ccf843Smisaki 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
683352ccf843Smisaki 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
683452ccf843Smisaki 				break;
683552ccf843Smisaki 			default:
683659ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
683752ccf843Smisaki 				    "Unsupported neptune type 11"));
683859ac0c16Sdavemq 				goto error_exit;
683959ac0c16Sdavemq 			}
684052ccf843Smisaki 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
684152ccf843Smisaki 			    "Maramba with 1 XAUI (fiber or copper)"));
684259ac0c16Sdavemq 			break;
684359ac0c16Sdavemq 		default:
684459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
684559ac0c16Sdavemq 			    "Unsupported neptune type 13"));
684659ac0c16Sdavemq 			goto error_exit;
684759ac0c16Sdavemq 		}
684859ac0c16Sdavemq 		break;
684900161856Syc 	case 0: /* 4 ports Neptune based NIC */
685059ac0c16Sdavemq 		switch (total_phy_fd) {
685159ac0c16Sdavemq 		case 4:
685230505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
685330505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
685430505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
685530505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
685659ac0c16Sdavemq 
685759ac0c16Sdavemq 				/*
685859ac0c16Sdavemq 				 * Check the first phy port address against
685959ac0c16Sdavemq 				 * the known phy start addresses to determine
686059ac0c16Sdavemq 				 * the platform type.
686159ac0c16Sdavemq 				 */
68622d17280bSsbehera 				switch (phy_fd_arr[0]) {
686300161856Syc 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
686459ac0c16Sdavemq 					hw_p->platform_type =
686559ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
68662d17280bSsbehera 					break;
686700161856Syc 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
68682e59129aSraghus 					hw_p->platform_type =
68692e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
68702d17280bSsbehera 					break;
68712d17280bSsbehera 				default:
68722e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68732e59129aSraghus 					    "Unknown port %d...Cannot "
68742e59129aSraghus 					    "determine platform type", i));
68752e59129aSraghus 					goto error_exit;
687659ac0c16Sdavemq 				}
68772e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
68782d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
68792d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
68802d17280bSsbehera 				}
688159ac0c16Sdavemq 			} else {
688259ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
688359ac0c16Sdavemq 				    "Unsupported neptune type 14"));
688459ac0c16Sdavemq 				goto error_exit;
688559ac0c16Sdavemq 			}
688659ac0c16Sdavemq 			break;
688759ac0c16Sdavemq 		case 3:
688859ac0c16Sdavemq 			/* TODO 3 1G mode */
688959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
689059ac0c16Sdavemq 			    "Unsupported neptune type 15"));
689159ac0c16Sdavemq 			goto error_exit;
689259ac0c16Sdavemq 		case 2:
689359ac0c16Sdavemq 			/* TODO 2 1G mode */
689459a835ddSjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
689559a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
689659a835ddSjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
689759a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
689859a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
689959a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
690059a835ddSjoycey 			} else {
690159a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
690259a835ddSjoycey 				    "Unsupported neptune type 16"));
690359a835ddSjoycey 				goto error_exit;
690459a835ddSjoycey 			}
690559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
690659a835ddSjoycey 			    "2 RGMII Fiber ports - RTM"));
690759a835ddSjoycey 			break;
690859a835ddSjoycey 
690959ac0c16Sdavemq 		case 1:
691059ac0c16Sdavemq 			/* TODO 1 1G mode */
691159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
691259ac0c16Sdavemq 			    "Unsupported neptune type 17"));
691359ac0c16Sdavemq 			goto error_exit;
691459ac0c16Sdavemq 		default:
691559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
691659ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
691759ac0c16Sdavemq 			    total_phy_fd));
691859ac0c16Sdavemq 			goto error_exit;
691959ac0c16Sdavemq 		}
692059ac0c16Sdavemq 		break;
692159ac0c16Sdavemq 	default:
692256d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
692359ac0c16Sdavemq 		    "Unsupported neptune type 19"));
692459ac0c16Sdavemq 		goto error_exit;
692544961713Sgirish 	}
692644961713Sgirish 
692759ac0c16Sdavemq scan_exit:
692844961713Sgirish 
692959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
693059ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
693159ac0c16Sdavemq 	return (status);
693244961713Sgirish 
693359ac0c16Sdavemq error_exit:
693459ac0c16Sdavemq 	return (NXGE_ERROR);
693544961713Sgirish }
693656d930aeSspeer 
693756d930aeSspeer boolean_t
693856d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
693956d930aeSspeer {
694056d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
694156d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
694256d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
694356d930aeSspeer 		return (B_FALSE);
694456d930aeSspeer 	else
694556d930aeSspeer 		return (B_TRUE);
694656d930aeSspeer }
694759ac0c16Sdavemq 
694859ac0c16Sdavemq static void
694959ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
695059ac0c16Sdavemq 
695159ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
695259ac0c16Sdavemq 	uint8_t xcvr_portn;
695359ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
695459ac0c16Sdavemq 
695559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
695659ac0c16Sdavemq 
695759ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
695800161856Syc 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
695959ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
696000161856Syc 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
696159ac0c16Sdavemq 	}
696259ac0c16Sdavemq 	/*
696359ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
696459ac0c16Sdavemq 	 * swapped with ethernet port number. This is
696559ac0c16Sdavemq 	 * designed for better signal integrity in routing.
696659ac0c16Sdavemq 	 */
696759ac0c16Sdavemq 	switch (portn) {
696859ac0c16Sdavemq 	case 0:
696959ac0c16Sdavemq 		xcvr_portn += 3;
697059ac0c16Sdavemq 		break;
697159ac0c16Sdavemq 	case 1:
697259ac0c16Sdavemq 		xcvr_portn += 2;
697359ac0c16Sdavemq 		break;
697459ac0c16Sdavemq 	case 2:
697559ac0c16Sdavemq 		xcvr_portn += 1;
697659ac0c16Sdavemq 		break;
697759ac0c16Sdavemq 	case 3:
697859ac0c16Sdavemq 	default:
697959ac0c16Sdavemq 		break;
698059ac0c16Sdavemq 	}
698159ac0c16Sdavemq 
6982321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
698359ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
698459ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
698559ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
698659ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
698759ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
698859ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
6989321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
699059ac0c16Sdavemq 		return;
699159ac0c16Sdavemq 	}
699259ac0c16Sdavemq 
699359ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
699459ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
699559ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
699659ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
699759ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
699859ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
699959ac0c16Sdavemq 	}
700059ac0c16Sdavemq 
7001321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
700259ac0c16Sdavemq }
7003d81011f0Ssbehera 
7004d81011f0Ssbehera static nxge_status_t
7005d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
7006d81011f0Ssbehera {
7007d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7008d81011f0Ssbehera 	uint8_t		xcvr_portn;
7009d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7010d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7011d81011f0Ssbehera 	int		status = NXGE_OK;
7012d81011f0Ssbehera 
7013d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
7014d81011f0Ssbehera 
7015d81011f0Ssbehera 	statsp = nxgep->statsp;
7016d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7017d81011f0Ssbehera 	mii_regs = NULL;
7018d81011f0Ssbehera 	mode.value = 0;
70196b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7020d81011f0Ssbehera #if defined(__i386)
7021d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7022d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7023d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7024d81011f0Ssbehera 		goto fail;
7025d81011f0Ssbehera #else
7026d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7027d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7028d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7029d81011f0Ssbehera 		goto fail;
7030d81011f0Ssbehera #endif
7031d81011f0Ssbehera 	}
7032d81011f0Ssbehera #if defined(__i386)
7033d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7034d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7035d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7036d81011f0Ssbehera 		goto fail;
7037d81011f0Ssbehera 	}
7038d81011f0Ssbehera #else
7039d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7040d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7041d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7042d81011f0Ssbehera 		goto fail;
7043d81011f0Ssbehera 	}
7044d81011f0Ssbehera #endif
7045d81011f0Ssbehera 
7046d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
7047d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
7048d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7049d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
7050d81011f0Ssbehera 	}
7051d81011f0Ssbehera 
7052d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7053d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
7054d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
70556b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
7056d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
7057d81011f0Ssbehera 
7058d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7059d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
7060d81011f0Ssbehera 	return (status);
7061d81011f0Ssbehera fail:
7062d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7063d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
7064d81011f0Ssbehera 	return (NXGE_ERROR);
7065d81011f0Ssbehera }
7066d81011f0Ssbehera 
70671bd6825cSml nxge_status_t
70681bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep)
70691bd6825cSml {
70701bd6825cSml 	npi_attr_t		ap;
70711bd6825cSml 	uint8_t			portn;
70721bd6825cSml 	npi_handle_t		handle;
70731bd6825cSml 	npi_status_t		rs = NPI_SUCCESS;
70741bd6825cSml 
70751bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
70761bd6825cSml 
70771bd6825cSml 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
70781bd6825cSml 	handle = nxgep->npi_handle;
70791bd6825cSml 
70801bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70811bd6825cSml 	    "==> nxge_mac_sec_framesize: port<%d> "
70821bd6825cSml 	    "min framesize %d max framesize %d ",
70831bd6825cSml 	    portn,
70841bd6825cSml 	    nxgep->mac.minframesize,
70851bd6825cSml 	    nxgep->mac.maxframesize));
70861bd6825cSml 
70871bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
70881bd6825cSml 	    MAC_PORT_FRAME_SIZE,
70891bd6825cSml 	    nxgep->mac.minframesize,
70901bd6825cSml 	    nxgep->mac.maxframesize,
70911bd6825cSml 	    rs);
70921bd6825cSml 	if (rs != NPI_SUCCESS) {
70931bd6825cSml 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70941bd6825cSml 		    "<== nxge_mac_set_framesize: failed to configure "
70951bd6825cSml 		    "max/min frame size port %d", portn));
70961bd6825cSml 
70971bd6825cSml 		return (NXGE_ERROR | rs);
70981bd6825cSml 	}
70991bd6825cSml 
71001bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71011bd6825cSml 	    "<== nxge_mac_set_framesize: port<%d>", portn));
71021bd6825cSml 
71031bd6825cSml 	return (NXGE_OK);
71041bd6825cSml }
71051bd6825cSml 
710600161856Syc static nxge_status_t
710700161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
710800161856Syc     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
710900161856Syc {
711000161856Syc 	uint8_t i;
711100161856Syc 
711200161856Syc 	for (i = 0; i < 4; i++) {
711300161856Syc 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
711400161856Syc 			return (NXGE_ERROR);
711500161856Syc 	}
711600161856Syc 
711700161856Syc 	*num_xaui = 0;
711800161856Syc 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
711900161856Syc 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
712000161856Syc 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
712100161856Syc 	    == TN1010_DEV_ID) &&
712200161856Syc 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
712300161856Syc 	    == TN1010_DEV_ID))) {
712400161856Syc 		(*num_xaui) ++;
712500161856Syc 	}
712600161856Syc 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
712700161856Syc 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
712800161856Syc 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
712900161856Syc 	    == TN1010_DEV_ID) &&
713000161856Syc 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
713100161856Syc 	    == TN1010_DEV_ID))) {
713200161856Syc 		(*num_xaui) ++;
713300161856Syc 	}
713400161856Syc 	return (NXGE_OK);
713500161856Syc }
713600161856Syc 
713700161856Syc /*
713800161856Syc  * Instruction from Teranetics:  Once you detect link is up, go
713900161856Syc  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
714000161856Syc  * may want to qualify it by first checking Register 30.1.7:6 and
714100161856Syc  * making sure it reads "01" (Auto-Neg Complete).
714200161856Syc  *
714300161856Syc  * If this function is called when the link is down or before auto-
714400161856Syc  * negotiation has completed, then the speed of the PHY is not certain.
714500161856Syc  * In such cases, this function returns 1G as the default speed with
714600161856Syc  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
714700161856Syc  * driver based on a default speed because this function will be called
714800161856Syc  * again when the link comes up.  Returning NXGE_ERROR, which may
714900161856Syc  * cause brutal chain reaction in caller functions, is not necessary.
715000161856Syc  */
715100161856Syc static nxge_status_t
715200161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
715300161856Syc {
715400161856Syc 	uint8_t		phy_port_addr, autoneg_stat, link_up;
715500161856Syc 	nxge_status_t	status = NXGE_OK;
715600161856Syc 	uint16_t	val;
715700161856Syc 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
715800161856Syc 
715900161856Syc 	/* Set default speed to 10G */
716000161856Syc 	*speed = TN1010_SPEED_10G;
716100161856Syc 
716200161856Syc 	/* Set Clause 45 */
716300161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
716400161856Syc 
716500161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
716600161856Syc 
716700161856Syc 	/* Check Device 1 Register 0xA bit0 for link up status */
716800161856Syc 	status = nxge_mdio_read(nxgep, phy_port_addr,
716900161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
717000161856Syc 	if (status != NXGE_OK)
717100161856Syc 		goto fail;
717200161856Syc 
717300161856Syc 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
717400161856Syc 	    ? B_TRUE : B_FALSE);
717500161856Syc 	if (link_up == B_FALSE) {
717600161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
717700161856Syc 		    "nxge_get_tn1010_speed: link is down"));
717800161856Syc 		goto nxge_get_tn1010_speed_exit;
717900161856Syc 	}
718000161856Syc 
718100161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
718200161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
718300161856Syc 	    &val)) != NXGE_OK) {
718400161856Syc 		goto fail;
718500161856Syc 	}
718600161856Syc 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
718700161856Syc 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
718800161856Syc 
718900161856Syc 	/*
719000161856Syc 	 * Return NXGE_OK even when we can not get a settled speed. In
719100161856Syc 	 * such case, the speed reported should not be trusted but that
719200161856Syc 	 * is OK, we will call this function periodically and will get
719300161856Syc 	 * the correct speed after the link is up.
719400161856Syc 	 */
719500161856Syc 	switch (autoneg_stat) {
719600161856Syc 	case TN1010_AN_IN_PROG:
719700161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
719800161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
719900161856Syc 		break;
720000161856Syc 	case TN1010_AN_COMPLETE:
720100161856Syc 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
720200161856Syc 		    TN1010_VENDOR_MMD1_DEV_ADDR,
720300161856Syc 		    TN1010_VENDOR_MMD1_STATUS_REG,
720400161856Syc 		    &val)) != NXGE_OK) {
720500161856Syc 			goto fail;
720600161856Syc 		}
720700161856Syc 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
720800161856Syc 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
720900161856Syc 		break;
721000161856Syc 	case TN1010_AN_RSVD:
721100161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
721200161856Syc 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
721300161856Syc 		break;
721400161856Syc 	case TN1010_AN_FAILED:
721500161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
721600161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
721700161856Syc 		break;
721800161856Syc 	default:
721900161856Syc 		break;
722000161856Syc 	}
722100161856Syc nxge_get_tn1010_speed_exit:
722200161856Syc 	return (NXGE_OK);
722300161856Syc fail:
722400161856Syc 	return (status);
722500161856Syc }
722600161856Syc 
722700161856Syc 
722800161856Syc /*
722900161856Syc  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
723000161856Syc  * figures out the speed of the PHY determined by the autonegotiation
723100161856Syc  * process and sets the following 3 parameters,
723200161856Syc  * 	nxgep->mac.portmode
723300161856Syc  *     	nxgep->statsp->mac_stats.link_speed
723400161856Syc  *	nxgep->statsp->mac_stats.xcvr_inuse
723500161856Syc  */
723600161856Syc static nxge_status_t
723700161856Syc nxge_set_tn1010_param(p_nxge_t nxgep)
723800161856Syc {
723900161856Syc 	uint16_t speed;
724000161856Syc 
724100161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
724200161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
724300161856Syc 		    "nxge_set_tn1010_param: "
724400161856Syc 		    "Failed to get TN1010 speed"));
724500161856Syc 		return (NXGE_ERROR);
724600161856Syc 	}
724700161856Syc 	if (speed == TN1010_SPEED_1G) {
724800161856Syc 		nxgep->mac.portmode = PORT_1G_TN1010;
724900161856Syc 		nxgep->statsp->mac_stats.link_speed = 1000;
725000161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
725100161856Syc 	} else {
725200161856Syc 		nxgep->mac.portmode = PORT_10G_TN1010;
725300161856Syc 		nxgep->statsp->mac_stats.link_speed = 10000;
725400161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
725500161856Syc 	}
725600161856Syc 	return (NXGE_OK);
725700161856Syc }
725800161856Syc 
7259d81011f0Ssbehera #ifdef NXGE_DEBUG
7260d81011f0Ssbehera static void
7261d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
7262d81011f0Ssbehera {
7263d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7264d81011f0Ssbehera 	uint8_t		xcvr_portn;
7265d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7266d81011f0Ssbehera 	mii_bmcr_t	bmcr;
7267d81011f0Ssbehera 	mii_bmsr_t	bmsr;
7268d81011f0Ssbehera 	mii_idr1_t	idr1;
7269d81011f0Ssbehera 	mii_idr2_t	idr2;
7270d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7271678453a8Sspeer 	p_nxge_param_t	param_arr;
7272d81011f0Ssbehera 
7273d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
7274d81011f0Ssbehera 
7275d81011f0Ssbehera 	statsp = nxgep->statsp;
7276d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7277d81011f0Ssbehera 
7278d81011f0Ssbehera 	mii_regs = NULL;
7279d81011f0Ssbehera 
7280d81011f0Ssbehera #if defined(__i386)
7281d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7282d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
7283d81011f0Ssbehera #else
7284d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7285d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
7286d81011f0Ssbehera #endif
7287d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7288d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
7289d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
7290d81011f0Ssbehera 
7291d81011f0Ssbehera #if defined(__i386)
7292d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7293d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7294d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
7295d81011f0Ssbehera #else
7296d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7297d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7298d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
7299d81011f0Ssbehera #endif
7300d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7301d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
7302d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
7303d81011f0Ssbehera 
7304d81011f0Ssbehera #if defined(__i386)
7305d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7306d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7307d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
7308d81011f0Ssbehera #else
7309d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7310d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7311d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
7312d81011f0Ssbehera #endif
7313d81011f0Ssbehera 
7314d81011f0Ssbehera 
7315d81011f0Ssbehera #if defined(__i386)
7316d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7317d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7318d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
7319d81011f0Ssbehera #else
7320d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7321d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7322d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
7323d81011f0Ssbehera #endif
7324d81011f0Ssbehera 
7325d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7326d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
7327d81011f0Ssbehera 	    xcvr_portn, idr1.value));
7328d81011f0Ssbehera 
7329d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7330d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
7331d81011f0Ssbehera 	    xcvr_portn, idr2.value));
7332d81011f0Ssbehera 
7333d81011f0Ssbehera 	mode.value = 0;
73346b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7335d81011f0Ssbehera 
7336d81011f0Ssbehera #if defined(__i386)
7337d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7338d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
7339d81011f0Ssbehera 
7340d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7341d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
7342d81011f0Ssbehera #else
7343d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7344d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
7345d81011f0Ssbehera 
7346d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7347d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
7348d81011f0Ssbehera #endif
7349d81011f0Ssbehera 
7350d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7351d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
7352d81011f0Ssbehera 	    xcvr_portn, mode.value));
7353d81011f0Ssbehera }
7354d81011f0Ssbehera #endif
7355