xref: /titanic_51/usr/src/uts/common/io/nxge/nxge_mac.c (revision 9d58797236c67ab2d8b5da36603dd896b1c6e153)
16f45ec7bSml29623 /*
26f45ec7bSml29623  * CDDL HEADER START
36f45ec7bSml29623  *
46f45ec7bSml29623  * The contents of this file are subject to the terms of the
56f45ec7bSml29623  * Common Development and Distribution License (the "License").
66f45ec7bSml29623  * You may not use this file except in compliance with the License.
76f45ec7bSml29623  *
86f45ec7bSml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96f45ec7bSml29623  * or http://www.opensolaris.org/os/licensing.
106f45ec7bSml29623  * See the License for the specific language governing permissions
116f45ec7bSml29623  * and limitations under the License.
126f45ec7bSml29623  *
136f45ec7bSml29623  * When distributing Covered Code, include this CDDL HEADER in each
146f45ec7bSml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156f45ec7bSml29623  * If applicable, add the following below this CDDL HEADER, with the
166f45ec7bSml29623  * fields enclosed by brackets "[]" replaced with your own identifying
176f45ec7bSml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
186f45ec7bSml29623  *
196f45ec7bSml29623  * CDDL HEADER END
206f45ec7bSml29623  */
216f45ec7bSml29623 /*
2289282175SSantwona Behera  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
236f45ec7bSml29623  */
246f45ec7bSml29623 
256f45ec7bSml29623 #include <sys/nxge/nxge_impl.h>
266f45ec7bSml29623 #include <sys/nxge/nxge_mac.h>
27678453a8Sspeer #include <sys/nxge/nxge_hio.h>
286f45ec7bSml29623 
2998ecde52Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3098ecde52Stm144005 #define	LM_WAIT_MULTIPLIER	8
3198ecde52Stm144005 
32321febdeSsbehera #define	SERDES_RDY_WT_INTERVAL	50
33321febdeSsbehera #define	MAX_SERDES_RDY_RETRIES	10
34321febdeSsbehera 
3500161856Syc148097 #define	TN1010_SPEED_1G		1
3600161856Syc148097 #define	TN1010_SPEED_10G	0
3700161856Syc148097 #define	TN1010_AN_IN_PROG	0	/* Auto negotiation in progress */
3800161856Syc148097 #define	TN1010_AN_COMPLETE	1
3900161856Syc148097 #define	TN1010_AN_RSVD		2
4000161856Syc148097 #define	TN1010_AN_FAILED	3
4100161856Syc148097 
426f45ec7bSml29623 extern uint32_t nxge_no_link_notify;
4359ac0c16Sdavemq extern boolean_t nxge_no_msg;
446f45ec7bSml29623 extern uint32_t nxge_lb_dbg;
454202ea4bSsbehera extern uint32_t nxge_jumbo_mtu;
466f45ec7bSml29623 
4798ecde52Stm144005 typedef enum {
4898ecde52Stm144005 	CHECK_LINK_RESCHEDULE,
4998ecde52Stm144005 	CHECK_LINK_STOP
5098ecde52Stm144005 } check_link_state_t;
5198ecde52Stm144005 
5298ecde52Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
5398ecde52Stm144005 
546f45ec7bSml29623 /*
556f45ec7bSml29623  * Ethernet broadcast address definition.
566f45ec7bSml29623  */
576f45ec7bSml29623 static ether_addr_st etherbroadcastaddr =
586f45ec7bSml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
5959ac0c16Sdavemq /*
6059ac0c16Sdavemq  * Ethernet zero address definition.
6159ac0c16Sdavemq  */
6256d930aeSspeer static ether_addr_st etherzeroaddr =
6356d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
6459ac0c16Sdavemq /*
6559ac0c16Sdavemq  * Supported chip types
6659ac0c16Sdavemq  */
6752cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = {
6852cdd236Ssbehera 	BCM8704_DEV_ID,
6952cdd236Ssbehera 	MARVELL_88X_201X_DEV_ID,
7000161856Syc148097 	BCM8706_DEV_ID,
7100161856Syc148097 	TN1010_DEV_ID
7252cdd236Ssbehera };
7352cdd236Ssbehera 
74b1000363Sml29623 static uint32_t nxge_supported_cl22_ids[] = {
75b1000363Sml29623     BCM5464R_PHY_ID,
76b1000363Sml29623     BCM5482_PHY_ID
77b1000363Sml29623 };
7859ac0c16Sdavemq 
7959ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
8059ac0c16Sdavemq 				sizeof (uint32_t))
8159ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
8259ac0c16Sdavemq 				sizeof (uint32_t))
8359ac0c16Sdavemq /*
8459ac0c16Sdavemq  * static functions
8559ac0c16Sdavemq  */
862e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
872e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
882e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
8959ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
9089282175SSantwona Behera static boolean_t nxge_hswap_phy_present(p_nxge_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);
934df55fdeSJanie Lu static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t);
9459ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
9559ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
9659ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
9759ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
9859ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
9959ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
10059ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
10159ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
10259ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
10359ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
10459ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1052d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1062d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
10759ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
10859ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
10900161856Syc148097 static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
11052cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
11189282175SSantwona Behera static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *);
11289282175SSantwona Behera static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t);
11389282175SSantwona Behera static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t,
11489282175SSantwona Behera 	    uint8_t *);
11589282175SSantwona Behera static boolean_t nxge_is_nlp2020_phy(p_nxge_t);
11689282175SSantwona Behera static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t);
11789282175SSantwona Behera static nxge_status_t nxge_set_nlp2020_param(p_nxge_t);
11800161856Syc148097 static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
11900161856Syc148097 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
12000161856Syc148097 static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
12100161856Syc148097 static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
12200161856Syc148097 static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
12300161856Syc148097 	nxge_link_state_t *link_up);
12400161856Syc148097 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
12500161856Syc148097 static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
12600161856Syc148097 
12700161856Syc148097 nxge_status_t nxge_mac_init(p_nxge_t);
12800161856Syc148097 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
12900161856Syc148097 
13000161856Syc148097 #ifdef NXGE_DEBUG
13100161856Syc148097 static void nxge_mii_dump(p_nxge_t);
13200161856Syc148097 static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
13300161856Syc148097 static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
13400161856Syc148097 #endif
13559ac0c16Sdavemq 
13659ac0c16Sdavemq /*
13759ac0c16Sdavemq  * xcvr tables for supported transceivers
13859ac0c16Sdavemq  */
13959ac0c16Sdavemq 
14000161856Syc148097 /*
14100161856Syc148097  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
14200161856Syc148097  * The Teranetics TN1010 based copper XAUI card can also be used
14300161856Syc148097  * on N2-NIU systems in 10G mode, but it uses its own table
14400161856Syc148097  * nxge_n2_10G_tn1010_table below.
14500161856Syc148097  */
1462e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
14759ac0c16Sdavemq 	nxge_n2_serdes_init,
14859ac0c16Sdavemq 	nxge_10G_xcvr_init,
14959ac0c16Sdavemq 	nxge_10G_link_intr_stop,
15059ac0c16Sdavemq 	nxge_10G_link_intr_start,
15159ac0c16Sdavemq 	nxge_check_10g_link,
1522d17280bSsbehera 	PCS_XCVR
15359ac0c16Sdavemq };
15459ac0c16Sdavemq 
15500161856Syc148097 /*
15600161856Syc148097  * For the Teranetics TN1010 based copper XAUI card
15700161856Syc148097  */
15800161856Syc148097 static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
15900161856Syc148097 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
16000161856Syc148097 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
16100161856Syc148097 	nxge_10G_link_intr_stop,
16200161856Syc148097 	nxge_10G_link_intr_start,
16300161856Syc148097 	nxge_check_tn1010_link,		/* Will figure out speed */
16400161856Syc148097 	XPCS_XCVR
16500161856Syc148097 };
16600161856Syc148097 
1672e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1682e59129aSraghus 	nxge_n2_serdes_init,
1692e59129aSraghus 	nxge_1G_xcvr_init,
1702e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1712e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1722e59129aSraghus 	nxge_check_mii_link,
1732d17280bSsbehera 	PCS_XCVR
1742e59129aSraghus };
1752e59129aSraghus 
17600161856Syc148097 static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
17700161856Syc148097 	nxge_n2_serdes_init,
17800161856Syc148097 	nxge_tn1010_xcvr_init,
17900161856Syc148097 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
18000161856Syc148097 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
18100161856Syc148097 	nxge_check_tn1010_link,
18200161856Syc148097 	PCS_XCVR
18300161856Syc148097 };
18400161856Syc148097 
18500161856Syc148097 static nxge_xcvr_table_t nxge_10G_tn1010_table = {
18600161856Syc148097 	nxge_neptune_10G_serdes_init,
18700161856Syc148097 	nxge_tn1010_xcvr_init,
18800161856Syc148097 	nxge_10G_link_intr_stop,
18900161856Syc148097 	nxge_10G_link_intr_start,
19000161856Syc148097 	nxge_check_tn1010_link,
19100161856Syc148097 	XPCS_XCVR
19200161856Syc148097 };
19300161856Syc148097 
19400161856Syc148097 static nxge_xcvr_table_t nxge_1G_tn1010_table = {
19500161856Syc148097 	nxge_1G_serdes_init,
19600161856Syc148097 	nxge_tn1010_xcvr_init,
19700161856Syc148097 	nxge_1G_fiber_link_intr_stop,
19800161856Syc148097 	nxge_1G_fiber_link_intr_start,
19900161856Syc148097 	nxge_check_tn1010_link,
20000161856Syc148097 	PCS_XCVR
20100161856Syc148097 };
20200161856Syc148097 
20359ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
20459ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
20559ac0c16Sdavemq 	nxge_10G_xcvr_init,
20659ac0c16Sdavemq 	nxge_10G_link_intr_stop,
20759ac0c16Sdavemq 	nxge_10G_link_intr_start,
20859ac0c16Sdavemq 	nxge_check_10g_link,
2092d17280bSsbehera 	PCS_XCVR
21059ac0c16Sdavemq };
21159ac0c16Sdavemq 
21259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
21359ac0c16Sdavemq 	NULL,
21459ac0c16Sdavemq 	nxge_1G_xcvr_init,
21559ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
21659ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
21759ac0c16Sdavemq 	nxge_check_mii_link,
2182d17280bSsbehera 	INT_MII_XCVR
21959ac0c16Sdavemq };
22059ac0c16Sdavemq 
22100161856Syc148097 /* This table is for Neptune portmode == PORT_1G_SERDES cases */
22259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
22359ac0c16Sdavemq 	nxge_1G_serdes_init,
22459ac0c16Sdavemq 	nxge_1G_xcvr_init,
22559ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
22659ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
22759ac0c16Sdavemq 	nxge_check_mii_link,
2282d17280bSsbehera 	PCS_XCVR
22959ac0c16Sdavemq };
23059ac0c16Sdavemq 
23159ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
23259ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
23359ac0c16Sdavemq 	NULL,
23459ac0c16Sdavemq 	NULL,
23559ac0c16Sdavemq 	NULL,
2362e59129aSraghus 	NULL,
2372d17280bSsbehera 	PCS_XCVR
23859ac0c16Sdavemq };
2396f45ec7bSml29623 
24000161856Syc148097 /*
24100161856Syc148097  * NXGE_PORT_TN1010 is defined as,
24200161856Syc148097  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
24300161856Syc148097  *	= 0 | 5 << 16 = 0x50000
24400161856Syc148097  *
24500161856Syc148097  * So NEPTUNE_2_TN1010 =
24600161856Syc148097  *      (NXGE_PORT_TN1010 |
24700161856Syc148097  *      (NXGE_PORT_TN1010 << 4) |
24800161856Syc148097  *      (NXGE_PORT_NONE << 8) |
24900161856Syc148097  *      (NXGE_PORT_NONE << 12)),
25000161856Syc148097  *      = 0x50000 | (0x50000 << 4)
25100161856Syc148097  *	= 0x550000
25200161856Syc148097  *
25300161856Syc148097  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
25400161856Syc148097  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
25500161856Syc148097  * = 0x50000
25600161856Syc148097  */
25700161856Syc148097 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
25800161856Syc148097 {
25900161856Syc148097 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2606f45ec7bSml29623 
26100161856Syc148097 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
26200161856Syc148097 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
26300161856Syc148097 		return (B_TRUE);
26400161856Syc148097 	} else {
26500161856Syc148097 		return (B_FALSE);
26600161856Syc148097 	}
26700161856Syc148097 }
268d81011f0Ssbehera 
26900161856Syc148097 
27000161856Syc148097 /*
27100161856Syc148097  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
27200161856Syc148097  * serial EEPROM or VPD if possible.  Note that not all systems could get
27300161856Syc148097  * the portmode information by calling this function.  For example, the
27400161856Syc148097  * Maramba system figures out the portmode information by calling function
27500161856Syc148097  * nxge_setup_xcvr_table.
27600161856Syc148097  */
2772e59129aSraghus nxge_status_t
2782e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
2792e59129aSraghus {
2802e59129aSraghus 	nxge_status_t status = NXGE_OK;
2812e59129aSraghus 	char *phy_type;
2822e59129aSraghus 	char *prop_val;
28300161856Syc148097 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2841c7408c9Stc99174@train 	uint32_t	val;
2851c7408c9Stc99174@train 	npi_status_t	rs;
2861c7408c9Stc99174@train 
2871c7408c9Stc99174@train 	/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
2881c7408c9Stc99174@train 	if (nxgep->mac.portmode == PORT_10G_SERDES &&
2891c7408c9Stc99174@train 	    nxgep->statsp->mac_stats.link_up) {
2901c7408c9Stc99174@train 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
2911c7408c9Stc99174@train 		return (status);
2921c7408c9Stc99174@train 	}
2932e59129aSraghus 
2942e59129aSraghus 	nxgep->mac.portmode = 0;
2952d17280bSsbehera 	nxgep->xcvr_addr = 0;
2962e59129aSraghus 
2972d17280bSsbehera 	/*
2982d17280bSsbehera 	 * First check for hot swappable phy property.
2992d17280bSsbehera 	 */
3002d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
3012d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3022d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3032d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
3042d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
3052d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3062d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3072d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3082d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3092d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
3102d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
3112d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
3122d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3132d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3142d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3152d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3162d17280bSsbehera 	}
3172d17280bSsbehera 
3182d17280bSsbehera 	/*
3192d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3202d17280bSsbehera 	 */
3212d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3222d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
323ef523517SMichael Speer 		if (portn > 1) {
324ef523517SMichael Speer 			return (NXGE_ERROR);
325ef523517SMichael Speer 		}
326ef523517SMichael Speer 
32789282175SSantwona Behera 		if (nxge_hswap_phy_present(nxgep, portn))
3282d17280bSsbehera 			goto found_phy;
3292d17280bSsbehera 
3302d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
3311c7408c9Stc99174@train 
3321c7408c9Stc99174@train 		/* Check Serdes link to detect Opus NEM */
3331c7408c9Stc99174@train 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
3341c7408c9Stc99174@train 		    XPCS_REG_STATUS, &val);
3351c7408c9Stc99174@train 
3361c7408c9Stc99174@train 		if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
3371c7408c9Stc99174@train 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3381c7408c9Stc99174@train 			nxgep->mac.portmode = PORT_10G_SERDES;
3391c7408c9Stc99174@train 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3401c7408c9Stc99174@train 			    "HSP 10G Serdes FOUND!!"));
3411c7408c9Stc99174@train 		}
3422d17280bSsbehera 		goto check_phy_done;
3432d17280bSsbehera found_phy:
3442d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3452d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3462d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
3472d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3482d17280bSsbehera 		    "found for hot swappable phy"));
3492d17280bSsbehera check_phy_done:
3502d17280bSsbehera 		return (status);
3512d17280bSsbehera 	}
3522d17280bSsbehera 
35300161856Syc148097 	/* Get phy-type property (May have been set by nxge.conf) */
3542e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3552e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3562e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3572e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3582e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
3592e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
3602e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3612e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3622e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3632e59129aSraghus 			    "found: 10G Serdes"));
3642e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3652e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3662e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3672e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3682e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
3692e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3702e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3712e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3722e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3732e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3742e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3752e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
376321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
37700161856Syc148097 			/*
37800161856Syc148097 			 * Before OBP supports new phy-type property
37900161856Syc148097 			 * value "xgc", the 10G copper XAUI may carry
38000161856Syc148097 			 * "xgf" instead of "xgc". If the OBP is
38100161856Syc148097 			 * upgraded to a newer version which supports
38200161856Syc148097 			 * "xgc", then the TN1010 related code in this
38300161856Syc148097 			 * "xgf" case will not be used anymore.
38400161856Syc148097 			 */
38500161856Syc148097 			if (nxge_is_tn1010_phy(nxgep)) {
38600161856Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
38700161856Syc148097 				    != NXGE_OK) {
38800161856Syc148097 					return (status);
38900161856Syc148097 				}
39000161856Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
39100161856Syc148097 			} else {  /* For Fiber XAUI */
392321febdeSsbehera 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
393321febdeSsbehera 				nxgep->mac.portmode = PORT_10G_FIBER;
39400161856Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39500161856Syc148097 				    "10G Fiber Xcvr"));
39600161856Syc148097 			}
39700161856Syc148097 		} else if (strcmp("xgc", prop_val) == 0) {
39800161856Syc148097 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
39900161856Syc148097 				return (status);
40000161856Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4012e59129aSraghus 		}
4022e59129aSraghus 
4032e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
4042e59129aSraghus 		    "phy-type", prop_val);
4052e59129aSraghus 		ddi_prop_free(prop_val);
4062e59129aSraghus 
4072e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4082e59129aSraghus 		    "Got phy type [0x%x] from conf file",
4092e59129aSraghus 		    nxgep->mac.portmode));
4102e59129aSraghus 
4112e59129aSraghus 		return (NXGE_OK);
4122e59129aSraghus 	}
4132d17280bSsbehera 
4142d17280bSsbehera 	/* Get phy-type property from OBP */
4152e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
4162e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4172e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4182e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
41900161856Syc148097 				/*
42000161856Syc148097 				 * Before OBP supports new phy-type property
42100161856Syc148097 				 * value "xgc", the 10G copper XAUI may carry
42200161856Syc148097 				 * "xgf" instead of "xgc". If the OBP is
42300161856Syc148097 				 * upgraded to a newer version which supports
42400161856Syc148097 				 * "xgc", then the TN1010 related code in this
42500161856Syc148097 				 * "xgf" case will not be used anymore.
42600161856Syc148097 				 */
42700161856Syc148097 				if (nxge_is_tn1010_phy(nxgep)) {
42800161856Syc148097 					if ((status =
42900161856Syc148097 					    nxge_set_tn1010_param(nxgep))
43000161856Syc148097 					    != NXGE_OK) {
43100161856Syc148097 						return (status);
43200161856Syc148097 					}
43300161856Syc148097 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43400161856Syc148097 					    "TN1010 Xcvr"));
43589282175SSantwona Behera 				} else if (nxge_is_nlp2020_phy(nxgep)) {
43689282175SSantwona Behera 					if ((status =
43789282175SSantwona Behera 					    nxge_set_nlp2020_param(nxgep))
43889282175SSantwona Behera 					    != NXGE_OK) {
43989282175SSantwona Behera 						return (status);
44089282175SSantwona Behera 					}
44189282175SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44289282175SSantwona Behera 					    "NLP2020 Xcvr"));
44300161856Syc148097 				} else { /* For Fiber XAUI */
44400161856Syc148097 					nxgep->statsp->mac_stats.xcvr_inuse
44500161856Syc148097 					    = XPCS_XCVR;
4462e59129aSraghus 					nxgep->mac.portmode = PORT_10G_FIBER;
4472e59129aSraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4482e59129aSraghus 					    "10G Fiber Xcvr"));
44900161856Syc148097 				}
4502e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
4512e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4522e59129aSraghus 				    INT_MII_XCVR;
4532e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4542e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4552e59129aSraghus 				    "1G Copper Xcvr"));
4562e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4572e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4582e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4592e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4602e59129aSraghus 				    "1G Fiber Xcvr"));
4612e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
46200161856Syc148097 				status = nxge_set_tn1010_param(nxgep);
46300161856Syc148097 				if (status != NXGE_OK)
46400161856Syc148097 					return (status);
46500161856Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4662e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4672e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4682e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4692e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4702e59129aSraghus 				    "OBP: 10G Serdes"));
4712e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4722e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4732e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4742e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4752e59129aSraghus 				    "OBP: 1G Serdes"));
4762e59129aSraghus 			} else {
4772e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4782e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
4792e59129aSraghus 				ddi_prop_free(prop_val);
4802e59129aSraghus 				return (NXGE_ERROR);
4812e59129aSraghus 			}
4822e59129aSraghus 			status = NXGE_OK;
4832e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4842e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
4852e59129aSraghus 			ddi_prop_free(prop_val);
4862e59129aSraghus 
4872e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4882e59129aSraghus 			    "Got phy type [0x%x] from OBP",
4892e59129aSraghus 			    nxgep->mac.portmode));
4902e59129aSraghus 
4912e59129aSraghus 			return (status);
4922e59129aSraghus 		} else {
4932e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4942e59129aSraghus 			    "Exiting...phy-type property not found"));
4952e59129aSraghus 			return (NXGE_ERROR);
4962e59129aSraghus 		}
4972e59129aSraghus 	}
4982e59129aSraghus 
4992e59129aSraghus 
5002e59129aSraghus 	if (!nxgep->vpd_info.present) {
5012e59129aSraghus 		return (NXGE_OK);
5022e59129aSraghus 	}
5032e59129aSraghus 
5042e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
5052e59129aSraghus 		goto read_seeprom;
5062e59129aSraghus 	}
5072e59129aSraghus 
5082e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5092e59129aSraghus 	    "Reading phy type from expansion ROM"));
5102e59129aSraghus 	/*
5112e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
5122e59129aSraghus 	 * expansion ROM.
5132e59129aSraghus 	 */
5142e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
5152e59129aSraghus 
516d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
5172e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
5182e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
519d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5202e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5212e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
522d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5232e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5242e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
525d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
52600161856Syc148097 		status = nxge_set_tn1010_param(nxgep);
52700161856Syc148097 		if (status != NXGE_OK) {
52800161856Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
52900161856Syc148097 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
53000161856Syc148097 			goto read_seeprom;
53100161856Syc148097 		}
532d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
533d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
534d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
535d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
536d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
537d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5382e59129aSraghus 	} else {
539d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5402e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5412e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5422e59129aSraghus 		goto read_seeprom;
5432e59129aSraghus 	}
5442e59129aSraghus 
5452e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5462e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5472e59129aSraghus 
5482e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5492e59129aSraghus 	return (status);
5502e59129aSraghus 
5512e59129aSraghus read_seeprom:
5522e59129aSraghus 	/*
5532e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
5542e59129aSraghus 	 */
5552e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
5562e59129aSraghus 	if (status != NXGE_OK) {
5572e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5582e59129aSraghus 		    "Failed to get phy type"));
5592e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5602e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5612e59129aSraghus 	}
5622e59129aSraghus 
5632e59129aSraghus 	return (status);
5642e59129aSraghus 
5652e59129aSraghus }
5662e59129aSraghus 
56759ac0c16Sdavemq /* Set up the PHY specific values. */
56859ac0c16Sdavemq 
56959ac0c16Sdavemq nxge_status_t
57059ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
57159ac0c16Sdavemq {
57259ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
57359ac0c16Sdavemq 	uint32_t	port_type;
57459ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5752e59129aSraghus 	uint32_t	pcs_id = 0;
5762e59129aSraghus 	uint32_t	pma_pmd_id = 0;
5772e59129aSraghus 	uint32_t	phy_id = 0;
5782d17280bSsbehera 	uint16_t	chip_id = 0;
57959ac0c16Sdavemq 
58059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
58159ac0c16Sdavemq 	    portn));
58259ac0c16Sdavemq 
5832e59129aSraghus 	switch (nxgep->niu_type) {
5842e59129aSraghus 	case N2_NIU:
5852e59129aSraghus 		switch (nxgep->mac.portmode) {
5862e59129aSraghus 		case PORT_1G_FIBER:
5872e59129aSraghus 		case PORT_1G_SERDES:
5882e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
5892d17280bSsbehera 			nxgep->xcvr_addr = portn;
5902e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5912e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5922e59129aSraghus 			    "Serdes"));
5932e59129aSraghus 			break;
5942e59129aSraghus 		case PORT_10G_FIBER:
59589282175SSantwona Behera 		case PORT_10G_COPPER:
5962e59129aSraghus 		case PORT_10G_SERDES:
5972e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
5982d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5992d17280bSsbehera 				nxgep->xcvr_addr =
6002d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
6012d17280bSsbehera 			}
6022e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
6032e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
60489282175SSantwona Behera 			    ((nxgep->mac.portmode == PORT_10G_COPPER) ?
60589282175SSantwona Behera 			    "Copper" : "Serdes")));
6062e59129aSraghus 			break;
60700161856Syc148097 		case PORT_1G_TN1010:
60800161856Syc148097 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
60900161856Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61000161856Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61100161856Syc148097 			    "TN1010 Copper Xcvr in 1G"));
61200161856Syc148097 			break;
61300161856Syc148097 		case PORT_10G_TN1010:
61400161856Syc148097 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
61500161856Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
61600161856Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61700161856Syc148097 			    "TN1010 Copper Xcvr in 10G"));
61800161856Syc148097 			break;
6192d17280bSsbehera 		case PORT_HSP_MODE:
6202d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
6212d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6222d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6232d17280bSsbehera 			    "Swappable Xcvr (not present)"));
6242d17280bSsbehera 			break;
6252e59129aSraghus 		default:
6262e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6272e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
6282e59129aSraghus 			    "Unable to determine NIU portmode"));
6292e59129aSraghus 			return (NXGE_ERROR);
6302e59129aSraghus 		}
6312e59129aSraghus 		break;
6322e59129aSraghus 	default:
6332e59129aSraghus 		if (nxgep->mac.portmode == 0) {
6342e59129aSraghus 			/*
6352e59129aSraghus 			 * Would be the case for platforms like Maramba
6362e59129aSraghus 			 * in which the phy type could not be got from conf
6372e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
6382e59129aSraghus 			 */
6392e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6402e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6412e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
6422e59129aSraghus 				    " Invalid Neptune type [0x%x]",
6432e59129aSraghus 				    nxgep->niu_type));
6442e59129aSraghus 				return (NXGE_ERROR);
6452e59129aSraghus 			}
6462e59129aSraghus 
6472e59129aSraghus 			port_type = nxgep->niu_type >>
6482e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
64959ac0c16Sdavemq 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6502e59129aSraghus 
65159ac0c16Sdavemq 			switch (port_type) {
6522e59129aSraghus 
65359ac0c16Sdavemq 			case NXGE_PORT_1G_COPPER:
65459ac0c16Sdavemq 				nxgep->mac.portmode = PORT_1G_COPPER;
6552e59129aSraghus 				break;
6562e59129aSraghus 			case NXGE_PORT_10G_COPPER:
6572e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6582e59129aSraghus 				break;
6592e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
6602e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6612e59129aSraghus 				break;
6622e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
6632e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6642e59129aSraghus 				break;
6652e59129aSraghus 			case NXGE_PORT_1G_SERDES:
6662e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6672e59129aSraghus 				break;
6682e59129aSraghus 			case NXGE_PORT_10G_SERDES:
6692e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6702e59129aSraghus 				break;
67100161856Syc148097 			/* Ports 2 and 3 of Alonso or ARTM */
6722e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6732e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6742e59129aSraghus 				break;
67500161856Syc148097 			case NXGE_PORT_TN1010:
67600161856Syc148097 				/*
67700161856Syc148097 				 * If this port uses the TN1010 copper
67800161856Syc148097 				 * PHY, then its speed is not known yet
67900161856Syc148097 				 * because nxge_scan_ports_phy could only
68000161856Syc148097 				 * figure out the vendor of the PHY but
68100161856Syc148097 				 * not its speed. nxge_set_tn1010_param
68200161856Syc148097 				 * will read the PHY speed and set
68300161856Syc148097 				 * portmode accordingly.
68400161856Syc148097 				 */
68500161856Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
68600161856Syc148097 				    != NXGE_OK) {
68700161856Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68800161856Syc148097 					    "nxge_set_tn1010_param failed"));
68900161856Syc148097 					return (status);
69000161856Syc148097 				}
69100161856Syc148097 				break;
6922e59129aSraghus 			default:
6932e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6942e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
6952e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
6962e59129aSraghus 				return (NXGE_ERROR);
6972e59129aSraghus 			}
6982e59129aSraghus 		}
6992e59129aSraghus 
70000161856Syc148097 		/*
70100161856Syc148097 		 * Above switch has figured out nxge->mac.portmode, now set
70200161856Syc148097 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
70300161856Syc148097 		 * to portmode.
70400161856Syc148097 		 */
7052e59129aSraghus 		switch (nxgep->mac.portmode) {
7062e59129aSraghus 		case PORT_1G_COPPER:
7072e59129aSraghus 		case PORT_1G_RGMII_FIBER:
70859ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
7092d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
71059ac0c16Sdavemq 			/*
71159ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
71259ac0c16Sdavemq 			 * swapped with ethernet port number. This is
7132e59129aSraghus 			 * designed for better signal integrity in
7142e59129aSraghus 			 * routing. This is also the case for the
7152e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
7162e59129aSraghus 			 * platform.
71759ac0c16Sdavemq 			 */
7182e59129aSraghus 			switch (nxgep->platform_type) {
7192e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
7202e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7212e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
72259ac0c16Sdavemq 				switch (portn) {
72359ac0c16Sdavemq 				case 0:
7242d17280bSsbehera 					nxgep->xcvr_addr += 3;
72559ac0c16Sdavemq 					break;
72659ac0c16Sdavemq 				case 1:
7272d17280bSsbehera 					nxgep->xcvr_addr += 1;
72859ac0c16Sdavemq 					break;
72959ac0c16Sdavemq 				case 2:
7302d17280bSsbehera 					nxgep->xcvr_addr -= 1;
73159ac0c16Sdavemq 					break;
73259ac0c16Sdavemq 				case 3:
7332d17280bSsbehera 					nxgep->xcvr_addr -= 3;
73459ac0c16Sdavemq 					break;
73559ac0c16Sdavemq 				default:
73659ac0c16Sdavemq 					return (NXGE_ERROR);
73759ac0c16Sdavemq 				}
73859ac0c16Sdavemq 				break;
7392e59129aSraghus 			default:
7402e59129aSraghus 				break;
7412e59129aSraghus 			}
742d81011f0Ssbehera 
7432e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7442e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7452e59129aSraghus 			    "Copper" : "RGMII Fiber"));
7462e59129aSraghus 			break;
74700161856Syc148097 
7482e59129aSraghus 		case PORT_10G_COPPER:
74959ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
75059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
75159ac0c16Sdavemq 			break;
75200161856Syc148097 
75300161856Syc148097 		case PORT_1G_TN1010:
75400161856Syc148097 			nxgep->xcvr = nxge_1G_tn1010_table;
75500161856Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
75600161856Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75700161856Syc148097 			    "1G TN1010 copper Xcvr"));
75800161856Syc148097 			break;
75900161856Syc148097 
76000161856Syc148097 		case PORT_10G_TN1010:
76100161856Syc148097 			nxgep->xcvr = nxge_10G_tn1010_table;
76200161856Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
76300161856Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
76400161856Syc148097 			    "10G TN1010 copper Xcvr"));
76500161856Syc148097 			break;
76600161856Syc148097 
7672e59129aSraghus 		case PORT_1G_FIBER:
7682e59129aSraghus 		case PORT_1G_SERDES:
76959ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7702d17280bSsbehera 			nxgep->xcvr_addr = portn;
7712e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7722e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7732e59129aSraghus 			    "Fiber" : "Serdes"));
77459ac0c16Sdavemq 			break;
7752e59129aSraghus 		case PORT_10G_FIBER:
7762e59129aSraghus 		case PORT_10G_SERDES:
77759ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7782d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7792d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7802d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
7812d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7822d17280bSsbehera 			    nxgep->xcvr_addr));
7832d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7842d17280bSsbehera 				nxgep->xcvr_addr =
7852d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7862d17280bSsbehera 			}
7872e59129aSraghus 			switch (nxgep->platform_type) {
7882e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7892e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
79059ac0c16Sdavemq 				/*
79159ac0c16Sdavemq 				 * Switch off LED for corresponding copper
79259ac0c16Sdavemq 				 * port
79359ac0c16Sdavemq 				 */
79459ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7952e59129aSraghus 				break;
7962e59129aSraghus 			default:
7972e59129aSraghus 				break;
79859ac0c16Sdavemq 			}
7992e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
8002e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
8012e59129aSraghus 			    "Fiber" : "Serdes"));
80259ac0c16Sdavemq 			break;
8032d17280bSsbehera 
8042d17280bSsbehera 		case PORT_HSP_MODE:
8052d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
8062d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
8072d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
8082d17280bSsbehera 			    "Swappable Xcvr (not present)"));
8092d17280bSsbehera 			break;
81059ac0c16Sdavemq 		default:
81159ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
81259ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
81359ac0c16Sdavemq 			return (NXGE_ERROR);
81459ac0c16Sdavemq 		}
81559ac0c16Sdavemq 	}
81659ac0c16Sdavemq 
81789282175SSantwona Behera 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
81889282175SSantwona Behera 	    nxgep->mac.portmode == PORT_10G_COPPER) {
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));
82789282175SSantwona Behera 		} else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) ==
82889282175SSantwona Behera 		    NLP2020_DEV_ID) {
82989282175SSantwona Behera 			chip_id = NLP2020_CHIP_ID;
83089282175SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
83189282175SSantwona Behera 			    "nxge_setup_xcvr_table: "
83289282175SSantwona Behera 			    "Chip ID  AEL2020 [0x%x] for 10G xcvr", chip_id));
83352cdd236Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8342d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8352d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
8362d17280bSsbehera 
8372d17280bSsbehera 			switch (chip_id) {
8382d17280bSsbehera 			case BCM8704_CHIP_ID:
8392d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8402d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8412d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8422d17280bSsbehera 				    chip_id));
8432d17280bSsbehera 				break;
8442d17280bSsbehera 			case BCM8706_CHIP_ID:
8452d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8462d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8472d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8482d17280bSsbehera 				    chip_id));
8492d17280bSsbehera 				break;
8502d17280bSsbehera 			default:
8512d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8522d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8532d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8542d17280bSsbehera 				    chip_id));
8552d17280bSsbehera 				break;
8562d17280bSsbehera 			}
8572d17280bSsbehera 		}
8582d17280bSsbehera 	}
8592d17280bSsbehera 
86059ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8612d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8622d17280bSsbehera 	nxgep->chip_id = chip_id;
8632e59129aSraghus 
8642e59129aSraghus 	/*
8652e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
8662e59129aSraghus 	 */
8672e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8682e59129aSraghus 
8692d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8702e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8712e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8722e59129aSraghus 	} else {
8732d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8742e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8752e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8762e59129aSraghus 		} else {
8772e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8782d17280bSsbehera 			    nxgep->xcvr_addr);
8792e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8802e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8812e59129aSraghus 			}
8822e59129aSraghus 		}
8832e59129aSraghus 	}
8842e59129aSraghus 
88559ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
88659ac0c16Sdavemq 
8872e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
88823b952a3SSantwona Behera 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
8892d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8902e59129aSraghus 
89159ac0c16Sdavemq 	return (status);
89259ac0c16Sdavemq }
89359ac0c16Sdavemq 
8946f45ec7bSml29623 /* Initialize the entire MAC and physical layer */
8956f45ec7bSml29623 
8966f45ec7bSml29623 nxge_status_t
8976f45ec7bSml29623 nxge_mac_init(p_nxge_t nxgep)
8986f45ec7bSml29623 {
8996f45ec7bSml29623 	uint8_t			portn;
9006f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
9016f45ec7bSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
9026f45ec7bSml29623 
9036f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
9046f45ec7bSml29623 
9056f45ec7bSml29623 	nxgep->mac.portnum = portn;
9066f45ec7bSml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
9076f45ec7bSml29623 
9086f45ec7bSml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
9096f45ec7bSml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
9106f45ec7bSml29623 
91100161856Syc148097 
9126f45ec7bSml29623 	/* Initialize XIF to configure a network mode */
9136f45ec7bSml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
9146f45ec7bSml29623 		goto fail;
9156f45ec7bSml29623 	}
9166f45ec7bSml29623 
9176f45ec7bSml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
9186f45ec7bSml29623 		goto fail;
9196f45ec7bSml29623 	}
9206f45ec7bSml29623 
9216f45ec7bSml29623 	/* Initialize TX and RX MACs */
9226f45ec7bSml29623 	/*
9236f45ec7bSml29623 	 * Always perform XIF init first, before TX and RX MAC init
9246f45ec7bSml29623 	 */
9256f45ec7bSml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
9266f45ec7bSml29623 		goto fail;
9276f45ec7bSml29623 
9286f45ec7bSml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
9296f45ec7bSml29623 		goto fail;
9306f45ec7bSml29623 
9316f45ec7bSml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
9326f45ec7bSml29623 		goto fail;
9336f45ec7bSml29623 
9346f45ec7bSml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
9356f45ec7bSml29623 		goto fail;
9366f45ec7bSml29623 
9376f45ec7bSml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
9386f45ec7bSml29623 		goto fail;
9396f45ec7bSml29623 
940e759c33aSMichael Speer 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
9416f45ec7bSml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
9426f45ec7bSml29623 			goto fail;
943e759c33aSMichael Speer 	}
9446f45ec7bSml29623 
945cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
946cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
947cb9d3ae6Smisaki 		goto fail;
948cb9d3ae6Smisaki 	}
949cb9d3ae6Smisaki 
9506f45ec7bSml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
9516f45ec7bSml29623 
952d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
953d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
954d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
95500161856Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
956d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
957d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
958d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
959d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
960d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
961d81011f0Ssbehera 			goto fail;
962d81011f0Ssbehera 		}
963d81011f0Ssbehera 	}
964d81011f0Ssbehera 
9652e59129aSraghus 
9666f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
9676f45ec7bSml29623 
9686f45ec7bSml29623 	return (NXGE_OK);
9696f45ec7bSml29623 fail:
9706f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
97152ccf843Smisaki 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
9726f45ec7bSml29623 	return (status);
9736f45ec7bSml29623 }
9746f45ec7bSml29623 
9756f45ec7bSml29623 /* Initialize the Ethernet Link */
9766f45ec7bSml29623 
9776f45ec7bSml29623 nxge_status_t
9786f45ec7bSml29623 nxge_link_init(p_nxge_t nxgep)
9796f45ec7bSml29623 {
9806f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
9812e59129aSraghus 	nxge_port_mode_t	portmode;
9826f45ec7bSml29623 #ifdef	NXGE_DEBUG
9836f45ec7bSml29623 	uint8_t			portn;
9846f45ec7bSml29623 
9856f45ec7bSml29623 	portn = nxgep->mac.portnum;
9866f45ec7bSml29623 
9876f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
9886f45ec7bSml29623 #endif
9891c7408c9Stc99174@train 	/* For Opus NEM, Serdes always needs to be initialized */
9906f45ec7bSml29623 
9912e59129aSraghus 	portmode = nxgep->mac.portmode;
9922d17280bSsbehera 
99300161856Syc148097 	/*
99400161856Syc148097 	 * Workaround to get link up in both NIU ports. Some portmodes require
99500161856Syc148097 	 * that the xcvr be initialized twice, the first time before calling
99600161856Syc148097 	 * nxge_serdes_init.
99700161856Syc148097 	 */
9982e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
99900161856Syc148097 	    (portmode != PORT_10G_TN1010) &&
100000161856Syc148097 	    (portmode != PORT_1G_TN1010) &&
10012e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
10022e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
10036f45ec7bSml29623 			goto fail;
10046f45ec7bSml29623 		}
10052e59129aSraghus 	}
100600161856Syc148097 
10076f45ec7bSml29623 	NXGE_DELAY(200000);
10086f45ec7bSml29623 	/* Initialize internal serdes */
10096f45ec7bSml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
10106f45ec7bSml29623 		goto fail;
10116f45ec7bSml29623 	NXGE_DELAY(200000);
10126f45ec7bSml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
10136f45ec7bSml29623 		goto fail;
10146f45ec7bSml29623 
10156f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
10166f45ec7bSml29623 
10176f45ec7bSml29623 	return (NXGE_OK);
10186f45ec7bSml29623 
10196f45ec7bSml29623 fail:
102052ccf843Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
102152ccf843Smisaki 	    "failed to initialize Ethernet link on port<%d>", portn));
10226f45ec7bSml29623 
10236f45ec7bSml29623 	return (status);
10246f45ec7bSml29623 }
10256f45ec7bSml29623 
10266f45ec7bSml29623 
10276f45ec7bSml29623 /* Initialize the XIF sub-block within the MAC */
10286f45ec7bSml29623 
10296f45ec7bSml29623 nxge_status_t
10306f45ec7bSml29623 nxge_xif_init(p_nxge_t nxgep)
10316f45ec7bSml29623 {
10326f45ec7bSml29623 	uint32_t		xif_cfg = 0;
10336f45ec7bSml29623 	npi_attr_t		ap;
10346f45ec7bSml29623 	uint8_t			portn;
10356f45ec7bSml29623 	nxge_port_t		portt;
10366f45ec7bSml29623 	nxge_port_mode_t	portmode;
10376f45ec7bSml29623 	p_nxge_stats_t		statsp;
10386f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
10396f45ec7bSml29623 	npi_handle_t		handle;
10406f45ec7bSml29623 
10416f45ec7bSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
10426f45ec7bSml29623 
10436f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
10446f45ec7bSml29623 
10456f45ec7bSml29623 	handle = nxgep->npi_handle;
10466f45ec7bSml29623 	portmode = nxgep->mac.portmode;
10476f45ec7bSml29623 	portt = nxgep->mac.porttype;
10486f45ec7bSml29623 	statsp = nxgep->statsp;
10496f45ec7bSml29623 
1050d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1051d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
105200161856Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
1053d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1054d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
1055d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1056d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
1057d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1058d81011f0Ssbehera 	}
1059d81011f0Ssbehera 
10606f45ec7bSml29623 	if (portt == PORT_TYPE_XMAC) {
10616f45ec7bSml29623 
10626f45ec7bSml29623 		/* Setup XIF Configuration for XMAC */
10636f45ec7bSml29623 
10646f45ec7bSml29623 		if ((portmode == PORT_10G_FIBER) ||
10652e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
106600161856Syc148097 		    (portmode == PORT_10G_TN1010) ||
10671c7408c9Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
10682e59129aSraghus 		    (portmode == PORT_10G_SERDES))
10696f45ec7bSml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
10706f45ec7bSml29623 
107100161856Syc148097 		/* Bypass PCS so that RGMII will be used */
10726f45ec7bSml29623 		if (portmode == PORT_1G_COPPER) {
10736f45ec7bSml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
10746f45ec7bSml29623 		}
10756f45ec7bSml29623 
10766f45ec7bSml29623 		/* Set MAC Internal Loopback if necessary */
10776f45ec7bSml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
10786f45ec7bSml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
10796f45ec7bSml29623 
10806f45ec7bSml29623 		if (statsp->mac_stats.link_speed == 100)
10816f45ec7bSml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
10826f45ec7bSml29623 
10836f45ec7bSml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
10846f45ec7bSml29623 
10852e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
108689282175SSantwona Behera 		    (portmode == PORT_10G_COPPER) ||
108700161856Syc148097 		    (portmode == PORT_10G_TN1010) ||
108800161856Syc148097 		    (portmode == PORT_1G_TN1010) ||
10891c7408c9Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
10902e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
109100161856Syc148097 			/* Assume LED same for 1G and 10G */
10926f45ec7bSml29623 			if (statsp->mac_stats.link_up) {
10936f45ec7bSml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
10946f45ec7bSml29623 			} else {
10956f45ec7bSml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
10966f45ec7bSml29623 			}
10976f45ec7bSml29623 		}
10986f45ec7bSml29623 
10996f45ec7bSml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
11006f45ec7bSml29623 		if (rs != NPI_SUCCESS)
11016f45ec7bSml29623 			goto fail;
11026f45ec7bSml29623 
11036f45ec7bSml29623 		nxgep->mac.xif_config = xif_cfg;
11046f45ec7bSml29623 
11056f45ec7bSml29623 		/* Set Port Mode */
11066f45ec7bSml29623 		if ((portmode == PORT_10G_FIBER) ||
11072e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
110800161856Syc148097 		    (portmode == PORT_10G_TN1010) ||
11091c7408c9Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
11102e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
11116f45ec7bSml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11126f45ec7bSml29623 			    MAC_XGMII_MODE, rs);
11136f45ec7bSml29623 			if (rs != NPI_SUCCESS)
11146f45ec7bSml29623 				goto fail;
11156f45ec7bSml29623 			if (statsp->mac_stats.link_up) {
11166f45ec7bSml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
11176f45ec7bSml29623 					goto fail;
11186f45ec7bSml29623 			} else {
11196f45ec7bSml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
11206f45ec7bSml29623 					goto fail;
11216f45ec7bSml29623 			}
11226f45ec7bSml29623 		} else if ((portmode == PORT_1G_FIBER) ||
11232e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
1124d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
112500161856Syc148097 		    (portmode == PORT_1G_TN1010) ||
1126d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
1127d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1128d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1129d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
11306f45ec7bSml29623 			if (statsp->mac_stats.link_speed == 1000) {
11316f45ec7bSml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11326f45ec7bSml29623 				    MAC_GMII_MODE, rs);
11336f45ec7bSml29623 			} else {
11346f45ec7bSml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11356f45ec7bSml29623 				    MAC_MII_MODE, rs);
11366f45ec7bSml29623 			}
11376f45ec7bSml29623 			if (rs != NPI_SUCCESS)
11386f45ec7bSml29623 				goto fail;
11396f45ec7bSml29623 		} else {
11406f45ec7bSml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11416f45ec7bSml29623 			    "nxge_xif_init: Unknown port mode (%d)"
11426f45ec7bSml29623 			    " for port<%d>", portmode, portn));
11436f45ec7bSml29623 			goto fail;
11446f45ec7bSml29623 		}
11456f45ec7bSml29623 
1146d81011f0Ssbehera 		/* Enable ATCA mode */
1147d81011f0Ssbehera 
11486f45ec7bSml29623 	} else if (portt == PORT_TYPE_BMAC) {
11496f45ec7bSml29623 
11506f45ec7bSml29623 		/* Setup XIF Configuration for BMAC */
11516f45ec7bSml29623 
1152d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
1153d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
11546f45ec7bSml29623 			if (statsp->mac_stats.link_speed == 100)
11556f45ec7bSml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
11566f45ec7bSml29623 		}
11576f45ec7bSml29623 
11586f45ec7bSml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
11596f45ec7bSml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
11606f45ec7bSml29623 
11616f45ec7bSml29623 		if (statsp->mac_stats.link_speed == 1000)
11626f45ec7bSml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
11636f45ec7bSml29623 
11646f45ec7bSml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
11656f45ec7bSml29623 
11666f45ec7bSml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
11676f45ec7bSml29623 		if (rs != NPI_SUCCESS)
11686f45ec7bSml29623 			goto fail;
11696f45ec7bSml29623 		nxgep->mac.xif_config = xif_cfg;
11706f45ec7bSml29623 	}
11716f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
11726f45ec7bSml29623 	return (NXGE_OK);
11736f45ec7bSml29623 fail:
11746f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
117552ccf843Smisaki 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
11766f45ec7bSml29623 	return (NXGE_ERROR | rs);
11776f45ec7bSml29623 }
11786f45ec7bSml29623 
11796f45ec7bSml29623 
118000161856Syc148097 /*
118100161856Syc148097  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
118200161856Syc148097  * support loopback like XPCS.
118300161856Syc148097  */
11846f45ec7bSml29623 nxge_status_t
11856f45ec7bSml29623 nxge_pcs_init(p_nxge_t nxgep)
11866f45ec7bSml29623 {
11876f45ec7bSml29623 	pcs_cfg_t		pcs_cfg;
11886f45ec7bSml29623 	uint32_t		val;
11896f45ec7bSml29623 	uint8_t			portn;
11906f45ec7bSml29623 	nxge_port_mode_t	portmode;
11916f45ec7bSml29623 	npi_handle_t		handle;
11926f45ec7bSml29623 	p_nxge_stats_t		statsp;
119300161856Syc148097 	pcs_ctrl_t		pcs_ctrl;
11946f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
119500161856Syc148097 	uint8_t i;
11966f45ec7bSml29623 
11976f45ec7bSml29623 	handle = nxgep->npi_handle;
11986f45ec7bSml29623 	portmode = nxgep->mac.portmode;
11996f45ec7bSml29623 	portn = nxgep->mac.portnum;
12006f45ec7bSml29623 	statsp = nxgep->statsp;
12016f45ec7bSml29623 
12026f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
12036f45ec7bSml29623 
120400161856Syc148097 	if (portmode == PORT_1G_FIBER ||
120500161856Syc148097 	    portmode == PORT_1G_TN1010 ||
120600161856Syc148097 	    portmode == PORT_1G_SERDES) {
120700161856Syc148097 		if (portmode == PORT_1G_TN1010) {
120800161856Syc148097 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
120900161856Syc148097 			for (i = 0; i < 6; i ++) {
121000161856Syc148097 				if ((rs = npi_mac_pcs_reset(handle, portn))
121100161856Syc148097 				    != NPI_SUCCESS) {
121200161856Syc148097 					goto fail;
121300161856Syc148097 				}
121400161856Syc148097 			}
121500161856Syc148097 		} else {
121600161856Syc148097 			if ((rs = npi_mac_pcs_reset(handle, portn))
121700161856Syc148097 			    != NPI_SUCCESS)
12182e59129aSraghus 				goto fail;
12192e59129aSraghus 		}
12202e59129aSraghus 
12216f45ec7bSml29623 		/* Initialize port's PCS */
12226f45ec7bSml29623 		pcs_cfg.value = 0;
12236f45ec7bSml29623 		pcs_cfg.bits.w0.enable = 1;
12246f45ec7bSml29623 		pcs_cfg.bits.w0.mask = 1;
12256f45ec7bSml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
12266f45ec7bSml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
12276f45ec7bSml29623 
12282e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12292e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12302e59129aSraghus 		    portn, pcs_cfg.value));
123100161856Syc148097 
123200161856Syc148097 		if (portmode == PORT_1G_TN1010) {
123300161856Syc148097 			/*
123400161856Syc148097 			 * Must disable PCS auto-negotiation when the the driver
123500161856Syc148097 			 * is driving the TN1010 based XAUI card  Otherwise the
123600161856Syc148097 			 * autonegotiation between the PCS and the TN1010 PCS
123700161856Syc148097 			 * will never complete and the Neptune/NIU will not work
123800161856Syc148097 			 */
123900161856Syc148097 			pcs_ctrl.value = 0;
124000161856Syc148097 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
124100161856Syc148097 			    pcs_ctrl.value);
124200161856Syc148097 		}
124300161856Syc148097 	} else if (portmode == PORT_10G_FIBER ||
124400161856Syc148097 	    portmode == PORT_10G_COPPER ||
124500161856Syc148097 	    portmode == PORT_10G_TN1010 ||
12461c7408c9Stc99174@train 	    portmode == PORT_HSP_MODE ||
124700161856Syc148097 	    portmode == PORT_10G_SERDES) {
12486f45ec7bSml29623 		/* Use internal XPCS, bypass 1G PCS */
12496f45ec7bSml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
12506f45ec7bSml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
12516f45ec7bSml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
12526f45ec7bSml29623 
12536f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
12546f45ec7bSml29623 			goto fail;
12556f45ec7bSml29623 
12566f45ec7bSml29623 		/* Set XPCS Internal Loopback if necessary */
12576f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
125852ccf843Smisaki 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
12596f45ec7bSml29623 			goto fail;
126000161856Syc148097 
12616f45ec7bSml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
12626f45ec7bSml29623 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
12636f45ec7bSml29623 			val |= XPCS_CTRL1_LOOPBK;
12646f45ec7bSml29623 		else
12656f45ec7bSml29623 			val &= ~XPCS_CTRL1_LOOPBK;
12666f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
126752ccf843Smisaki 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
12686f45ec7bSml29623 			goto fail;
12696f45ec7bSml29623 
12706f45ec7bSml29623 		/* Clear descw errors */
12716f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
127252ccf843Smisaki 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
12736f45ec7bSml29623 			goto fail;
12746f45ec7bSml29623 		/* Clear symbol errors */
12756f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
127652ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
12776f45ec7bSml29623 			goto fail;
12786f45ec7bSml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
127952ccf843Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
12806f45ec7bSml29623 			goto fail;
12816f45ec7bSml29623 
1282d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1283d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1284d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1285d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
12866f45ec7bSml29623 		if (portn < 4) {
12876f45ec7bSml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
12886f45ec7bSml29623 			    PCS_DATAPATH_MODE_MII);
12896f45ec7bSml29623 		}
12906f45ec7bSml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
12916f45ec7bSml29623 			goto fail;
12926f45ec7bSml29623 
12936f45ec7bSml29623 	} else {
12946f45ec7bSml29623 		goto fail;
12956f45ec7bSml29623 	}
12966f45ec7bSml29623 pass:
12976f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
12986f45ec7bSml29623 	return (NXGE_OK);
12996f45ec7bSml29623 fail:
13006f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
130152ccf843Smisaki 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
13026f45ec7bSml29623 	return (NXGE_ERROR | rs);
13036f45ec7bSml29623 }
13046f45ec7bSml29623 
1305cb9d3ae6Smisaki /*
1306cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1307cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1308cb9d3ae6Smisaki  */
1309cb9d3ae6Smisaki nxge_status_t
1310cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1311cb9d3ae6Smisaki {
1312cb9d3ae6Smisaki 	uint8_t			portn;
1313cb9d3ae6Smisaki 	nxge_port_t		portt;
1314cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1315cb9d3ae6Smisaki 	npi_handle_t		handle;
1316cb9d3ae6Smisaki 	uint32_t		val;
1317cb9d3ae6Smisaki 
1318cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1319cb9d3ae6Smisaki 
1320cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1321cb9d3ae6Smisaki 	    portn));
1322cb9d3ae6Smisaki 
1323cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1324cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1325cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1326cb9d3ae6Smisaki 
1327cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
132800161856Syc148097 		/* Reading the current XMAC Config Register for XMAC */
1329cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1330cb9d3ae6Smisaki 
1331cb9d3ae6Smisaki 		/*
1332cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1333cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1334cb9d3ae6Smisaki 		 */
1335cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1336cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1337cb9d3ae6Smisaki 				/*
1338cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1339cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1340cb9d3ae6Smisaki 				 */
1341cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1342cb9d3ae6Smisaki 			} else {
1343cb9d3ae6Smisaki 				/*
1344cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1345cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1346cb9d3ae6Smisaki 				 * not supported.
1347cb9d3ae6Smisaki 				 */
1348cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1349cb9d3ae6Smisaki 			}
1350cb9d3ae6Smisaki 		} else {
13511bd6825cSml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13521bd6825cSml29623 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13531bd6825cSml29623 			    portn));
1354cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13551bd6825cSml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13561bd6825cSml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13571bd6825cSml29623 				    "enable pause", portn));
1358cb9d3ae6Smisaki 				/*
1359cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1360cb9d3ae6Smisaki 				 * is 1, enable receive pause.
1361cb9d3ae6Smisaki 				 */
1362cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1363cb9d3ae6Smisaki 			} else {
1364cb9d3ae6Smisaki 				/*
1365cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1366cb9d3ae6Smisaki 				 * is 0, disable receive pause. Send pause is
1367cb9d3ae6Smisaki 				 * not supported
1368cb9d3ae6Smisaki 				 */
13691bd6825cSml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13701bd6825cSml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13711bd6825cSml29623 				    "disable pause", portn));
1372cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1373cb9d3ae6Smisaki 			}
1374cb9d3ae6Smisaki 		}
1375cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1376cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
137700161856Syc148097 		/* Reading the current MAC CTRL Config Register for BMAC */
1378cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1379cb9d3ae6Smisaki 
1380cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1381cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1382cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1383cb9d3ae6Smisaki 				/*
1384cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1385cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1386cb9d3ae6Smisaki 				 * is not supported
1387cb9d3ae6Smisaki 				 */
1388cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1389cb9d3ae6Smisaki 			} else {
1390cb9d3ae6Smisaki 				/*
1391cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1392cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1393cb9d3ae6Smisaki 				 * send pause.
1394cb9d3ae6Smisaki 				 */
1395cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1396cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1397cb9d3ae6Smisaki 			}
1398cb9d3ae6Smisaki 		} else {
1399cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1400cb9d3ae6Smisaki 				/*
1401cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1402cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1403cb9d3ae6Smisaki 				 * not supported.
1404cb9d3ae6Smisaki 				 */
1405cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1406cb9d3ae6Smisaki 			} else {
1407cb9d3ae6Smisaki 				/*
1408cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1409cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1410cb9d3ae6Smisaki 				 * either direction.
1411cb9d3ae6Smisaki 				 */
1412cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1413cb9d3ae6Smisaki 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
1414cb9d3ae6Smisaki 			}
1415cb9d3ae6Smisaki 		}
1416cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1417cb9d3ae6Smisaki 	}
1418cb9d3ae6Smisaki 
1419cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1420cb9d3ae6Smisaki 	    portn));
1421cb9d3ae6Smisaki 
1422cb9d3ae6Smisaki 	return (NXGE_OK);
1423cb9d3ae6Smisaki }
1424cb9d3ae6Smisaki 
14256f45ec7bSml29623 /* Initialize the Internal Serdes */
14266f45ec7bSml29623 
14276f45ec7bSml29623 nxge_status_t
14286f45ec7bSml29623 nxge_serdes_init(p_nxge_t nxgep)
14296f45ec7bSml29623 {
14306f45ec7bSml29623 	p_nxge_stats_t		statsp;
14316f45ec7bSml29623 #ifdef	NXGE_DEBUG
14326f45ec7bSml29623 	uint8_t			portn;
14336f45ec7bSml29623 #endif
14346f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
14356f45ec7bSml29623 
14366f45ec7bSml29623 #ifdef	NXGE_DEBUG
14376f45ec7bSml29623 	portn = nxgep->mac.portnum;
14386f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14396f45ec7bSml29623 	    "==> nxge_serdes_init port<%d>", portn));
14406f45ec7bSml29623 #endif
14416f45ec7bSml29623 
144259ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
14436f45ec7bSml29623 		statsp = nxgep->statsp;
144459ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
144559ac0c16Sdavemq 		if (status != NXGE_OK)
14466f45ec7bSml29623 			goto fail;
14476f45ec7bSml29623 		statsp->mac_stats.serdes_inits++;
144859ac0c16Sdavemq 	}
14496f45ec7bSml29623 
14506f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
14516f45ec7bSml29623 	    portn));
14526f45ec7bSml29623 
14536f45ec7bSml29623 	return (NXGE_OK);
14546f45ec7bSml29623 
14556f45ec7bSml29623 fail:
14566f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14576f45ec7bSml29623 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
14586f45ec7bSml29623 	    portn));
14596f45ec7bSml29623 
14606f45ec7bSml29623 	return (status);
14616f45ec7bSml29623 }
14626f45ec7bSml29623 
14636f45ec7bSml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
14646f45ec7bSml29623 
146559ac0c16Sdavemq static nxge_status_t
14666f45ec7bSml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
14676f45ec7bSml29623 {
14686f45ec7bSml29623 	uint8_t portn;
14696f45ec7bSml29623 	int chan;
14706f45ec7bSml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
14712e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
14726f45ec7bSml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
14736f45ec7bSml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
14746f45ec7bSml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
14756f45ec7bSml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
14762e59129aSraghus #ifdef NXGE_DEBUG
14772e59129aSraghus 	esr_ti_testcfg_t cfg;
14782e59129aSraghus #endif
14796f45ec7bSml29623 	esr_ti_testcfg_t test_cfg;
14806f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
14816f45ec7bSml29623 
14826f45ec7bSml29623 	portn = nxgep->mac.portnum;
14836f45ec7bSml29623 
14846f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
14856f45ec7bSml29623 	    portn));
14864df55fdeSJanie Lu 	if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) {
14874df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14884df55fdeSJanie Lu 		    "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
14894df55fdeSJanie Lu 		return (nxge_n2_kt_serdes_init(nxgep));
14904df55fdeSJanie Lu 	}
14916f45ec7bSml29623 
14926f45ec7bSml29623 	tx_cfg_l.value = 0;
14936f45ec7bSml29623 	tx_cfg_h.value = 0;
14946f45ec7bSml29623 	rx_cfg_l.value = 0;
14956f45ec7bSml29623 	rx_cfg_h.value = 0;
14966f45ec7bSml29623 	pll_cfg_l.value = 0;
14972e59129aSraghus 	pll_sts_l.value = 0;
14986f45ec7bSml29623 	test_cfg.value = 0;
14996f45ec7bSml29623 
150000161856Syc148097 	/*
150100161856Syc148097 	 * If the nxge driver has been plumbed without a link, then it will
150200161856Syc148097 	 * detect a link up when a cable connecting to an anto-negotiation
150300161856Syc148097 	 * partner is plugged into the port. Because the TN1010 PHY supports
150400161856Syc148097 	 * both 1G and 10G speeds, the driver must re-configure the
150500161856Syc148097 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
150600161856Syc148097 	 * is called at the post-link-up reconfiguration time. Here it calls
150700161856Syc148097 	 * nxge_set_tn1010_param to set portmode before re-initializing
150800161856Syc148097 	 * the serdes.
150900161856Syc148097 	 */
151000161856Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
151100161856Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
151200161856Syc148097 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
151300161856Syc148097 			goto fail;
151400161856Syc148097 		}
151500161856Syc148097 	}
151600161856Syc148097 
151700161856Syc148097 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
151889282175SSantwona Behera 	    nxgep->mac.portmode == PORT_10G_COPPER ||
151900161856Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
15201c7408c9Stc99174@train 	    nxgep->mac.portmode == PORT_HSP_MODE ||
152100161856Syc148097 	    nxgep->mac.portmode == PORT_10G_SERDES) {
15226f45ec7bSml29623 		/* 0x0E01 */
15236f45ec7bSml29623 		tx_cfg_l.bits.entx = 1;
15246f45ec7bSml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
15256f45ec7bSml29623 
15266f45ec7bSml29623 		/* 0x9101 */
15276f45ec7bSml29623 		rx_cfg_l.bits.enrx = 1;
15286f45ec7bSml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
15296f45ec7bSml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
15306f45ec7bSml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
15316f45ec7bSml29623 
15326f45ec7bSml29623 		/* 0x0008 */
15336f45ec7bSml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15346f45ec7bSml29623 
15356f45ec7bSml29623 		/* Set loopback mode if necessary */
15366f45ec7bSml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
15376f45ec7bSml29623 			tx_cfg_l.bits.entest = 1;
15386f45ec7bSml29623 			rx_cfg_l.bits.entest = 1;
15396f45ec7bSml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
15406f45ec7bSml29623 			if ((status = nxge_mdio_write(nxgep, portn,
15416f45ec7bSml29623 			    ESR_N2_DEV_ADDR,
154252ccf843Smisaki 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
15436f45ec7bSml29623 			goto fail;
15446f45ec7bSml29623 		}
15456f45ec7bSml29623 
154600161856Syc148097 		/* Initialize PLL for 10G */
154700161856Syc148097 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
154800161856Syc148097 		pll_cfg_l.bits.enpll = 1;
154900161856Syc148097 		pll_sts_l.bits.enpll = 1;
155000161856Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
155100161856Syc148097 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
155200161856Syc148097 			goto fail;
15536f45ec7bSml29623 
155400161856Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
155500161856Syc148097 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
155600161856Syc148097 			goto fail;
15576f45ec7bSml29623 
155800161856Syc148097 #ifdef  NXGE_DEBUG
155900161856Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
156000161856Syc148097 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
156100161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
156200161856Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
156300161856Syc148097 		    portn, pll_cfg_l.value, cfg.value));
156400161856Syc148097 
156500161856Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
156600161856Syc148097 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
156700161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
156800161856Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
156900161856Syc148097 		    portn, pll_sts_l.value, cfg.value));
157000161856Syc148097 #endif
157100161856Syc148097 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
157200161856Syc148097 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
157300161856Syc148097 	    nxgep->mac.portmode == PORT_1G_SERDES) {
15746f45ec7bSml29623 		/* 0x0E21 */
15756f45ec7bSml29623 		tx_cfg_l.bits.entx = 1;
15766f45ec7bSml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
15776f45ec7bSml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
15786f45ec7bSml29623 
15796f45ec7bSml29623 		/* 0x9121 */
15806f45ec7bSml29623 		rx_cfg_l.bits.enrx = 1;
15816f45ec7bSml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
15826f45ec7bSml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
15836f45ec7bSml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
15846f45ec7bSml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
15856f45ec7bSml29623 
15862e59129aSraghus 		if (portn == 0) {
15876f45ec7bSml29623 			/* 0x8 */
15886f45ec7bSml29623 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15892e59129aSraghus 		}
15906f45ec7bSml29623 
159100161856Syc148097 		/* Initialize PLL for 1G */
15926f45ec7bSml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
15936f45ec7bSml29623 		pll_cfg_l.bits.enpll = 1;
15942e59129aSraghus 		pll_sts_l.bits.enpll = 1;
15956f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
159652ccf843Smisaki 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
15976f45ec7bSml29623 			goto fail;
15982e59129aSraghus 
15992e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16002e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
16012e59129aSraghus 			goto fail;
16022e59129aSraghus 
16032e59129aSraghus #ifdef  NXGE_DEBUG
16042e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
16052e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
16062e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16072e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
16082e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
16092e59129aSraghus 
16102e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
16112e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
16122e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16132e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
16142e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
16152e59129aSraghus #endif
16162e59129aSraghus 
16172e59129aSraghus 		/* Set loopback mode if necessary */
16182e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16192e59129aSraghus 			tx_cfg_l.bits.entest = 1;
16202e59129aSraghus 			rx_cfg_l.bits.entest = 1;
16212e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
16222e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16232e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
16242e59129aSraghus 			    portn, test_cfg.value));
16252e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
16262e59129aSraghus 			    ESR_N2_DEV_ADDR,
16272e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
16282e59129aSraghus 				goto fail;
16292e59129aSraghus 			}
16302e59129aSraghus 		}
16316f45ec7bSml29623 	} else {
16326f45ec7bSml29623 		goto fail;
16336f45ec7bSml29623 	}
16346f45ec7bSml29623 
16356f45ec7bSml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
16366f45ec7bSml29623 
16376f45ec7bSml29623 	NXGE_DELAY(20);
16386f45ec7bSml29623 
16396f45ec7bSml29623 	/* init TX channels */
16406f45ec7bSml29623 	for (chan = 0; chan < 4; chan++) {
16416f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
164252ccf843Smisaki 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
16436f45ec7bSml29623 			goto fail;
16446f45ec7bSml29623 
16456f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
164652ccf843Smisaki 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
16476f45ec7bSml29623 			goto fail;
16482e59129aSraghus 
16492e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16502e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16512e59129aSraghus 		    portn, chan, tx_cfg_l.value));
16522e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16532e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16542e59129aSraghus 		    portn, chan, tx_cfg_h.value));
16556f45ec7bSml29623 	}
16566f45ec7bSml29623 
16576f45ec7bSml29623 	/* init RX channels */
16586f45ec7bSml29623 	for (chan = 0; chan < 4; chan++) {
16596f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
166052ccf843Smisaki 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
16616f45ec7bSml29623 			goto fail;
16626f45ec7bSml29623 
16636f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
166452ccf843Smisaki 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
16656f45ec7bSml29623 			goto fail;
16662e59129aSraghus 
16672e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16682e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16692e59129aSraghus 		    portn, chan, rx_cfg_l.value));
167000161856Syc148097 
16712e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16722e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16732e59129aSraghus 		    portn, chan, rx_cfg_h.value));
16746f45ec7bSml29623 	}
16756f45ec7bSml29623 
16766f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
16776f45ec7bSml29623 	    portn));
16786f45ec7bSml29623 
16796f45ec7bSml29623 	return (NXGE_OK);
16806f45ec7bSml29623 fail:
16812d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16826f45ec7bSml29623 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16836f45ec7bSml29623 	    portn));
16846f45ec7bSml29623 
16856f45ec7bSml29623 	return (status);
16864df55fdeSJanie Lu 
16874df55fdeSJanie Lu }
16884df55fdeSJanie Lu 
16894df55fdeSJanie Lu /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */
16904df55fdeSJanie Lu 
16914df55fdeSJanie Lu static nxge_status_t
16924df55fdeSJanie Lu nxge_n2_kt_serdes_init(p_nxge_t nxgep)
16934df55fdeSJanie Lu {
16944df55fdeSJanie Lu 	uint8_t portn;
169589282175SSantwona Behera 	int chan, i;
16964df55fdeSJanie Lu 	k_esr_ti_cfgpll_l_t pll_cfg_l;
16974df55fdeSJanie Lu 	k_esr_ti_cfgrx_l_t rx_cfg_l;
16984df55fdeSJanie Lu 	k_esr_ti_cfgrx_h_t rx_cfg_h;
16994df55fdeSJanie Lu 	k_esr_ti_cfgtx_l_t tx_cfg_l;
17004df55fdeSJanie Lu 	k_esr_ti_cfgtx_h_t tx_cfg_h;
17014df55fdeSJanie Lu #ifdef NXGE_DEBUG
17024df55fdeSJanie Lu 	k_esr_ti_testcfg_t cfg;
17034df55fdeSJanie Lu #endif
17044df55fdeSJanie Lu 	k_esr_ti_testcfg_t test_cfg;
17054df55fdeSJanie Lu 	nxge_status_t status = NXGE_OK;
17064df55fdeSJanie Lu 	boolean_t mode_1g = B_FALSE;
170789282175SSantwona Behera 	uint64_t val;
170889282175SSantwona Behera 	npi_handle_t handle;
17094df55fdeSJanie Lu 
17104df55fdeSJanie Lu 	portn = nxgep->mac.portnum;
17114df55fdeSJanie Lu 
17124df55fdeSJanie Lu 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17134df55fdeSJanie Lu 	    "==> nxge_n2_kt_serdes_init port<%d>", portn));
171489282175SSantwona Behera 	handle = nxgep->npi_handle;
17154df55fdeSJanie Lu 
17164df55fdeSJanie Lu 	tx_cfg_l.value = 0;
17174df55fdeSJanie Lu 	tx_cfg_h.value = 0;
17184df55fdeSJanie Lu 	rx_cfg_l.value = 0;
17194df55fdeSJanie Lu 	rx_cfg_h.value = 0;
17204df55fdeSJanie Lu 	pll_cfg_l.value = 0;
17214df55fdeSJanie Lu 	test_cfg.value = 0;
17224df55fdeSJanie Lu 
17234df55fdeSJanie Lu 	/*
17244df55fdeSJanie Lu 	 * The following setting assumes the reference clock frquency
17254df55fdeSJanie Lu 	 * is 156.25 MHz.
17264df55fdeSJanie Lu 	 */
17274df55fdeSJanie Lu 	/*
17284df55fdeSJanie Lu 	 * If the nxge driver has been plumbed without a link, then it will
17294df55fdeSJanie Lu 	 * detect a link up when a cable connecting to an anto-negotiation
17304df55fdeSJanie Lu 	 * partner is plugged into the port. Because the TN1010 PHY supports
17314df55fdeSJanie Lu 	 * both 1G and 10G speeds, the driver must re-configure the
17324df55fdeSJanie Lu 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
17334df55fdeSJanie Lu 	 * is called at the post-link-up reconfiguration time. Here it calls
17344df55fdeSJanie Lu 	 * nxge_set_tn1010_param to set portmode before re-initializing
17354df55fdeSJanie Lu 	 * the serdes.
17364df55fdeSJanie Lu 	 */
17374df55fdeSJanie Lu 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
17384df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_TN1010) {
17394df55fdeSJanie Lu 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
17404df55fdeSJanie Lu 			goto fail;
17414df55fdeSJanie Lu 		}
17424df55fdeSJanie Lu 	}
17434df55fdeSJanie Lu 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
174489282175SSantwona Behera 	    nxgep->mac.portmode == PORT_10G_COPPER ||
17454df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
17464df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_10G_SERDES) {
1747*9d587972SSantwona Behera 
1748*9d587972SSantwona Behera 		/* Take tunables from OBP if present, otherwise use defaults */
1749*9d587972SSantwona Behera 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGL) {
1750*9d587972SSantwona Behera 			tx_cfg_l.value = nxgep->srds_prop.tx_cfg_l;
1751*9d587972SSantwona Behera 		} else {
17524df55fdeSJanie Lu 			tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX;
17534df55fdeSJanie Lu 			/* 0x1e21 */
17544df55fdeSJanie Lu 			tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
17554df55fdeSJanie Lu 			tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
1756*9d587972SSantwona Behera 		}
17574df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17584df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
17594df55fdeSJanie Lu 		    portn, tx_cfg_l.value));
17604df55fdeSJanie Lu 
1761*9d587972SSantwona Behera 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGH) {
1762*9d587972SSantwona Behera 			tx_cfg_h.value = nxgep->srds_prop.tx_cfg_h;
1763*9d587972SSantwona Behera 		} else {
17644df55fdeSJanie Lu 			/* channel 0: enable syn. master */
17654df55fdeSJanie Lu 			/* 0x40 */
17664df55fdeSJanie Lu 			tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
1767*9d587972SSantwona Behera 		}
17684df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17694df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
17704df55fdeSJanie Lu 		    portn, tx_cfg_h.value));
1771*9d587972SSantwona Behera 
1772*9d587972SSantwona Behera 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGL) {
1773*9d587972SSantwona Behera 			rx_cfg_l.value = nxgep->srds_prop.rx_cfg_l;
1774*9d587972SSantwona Behera 		} else {
17754df55fdeSJanie Lu 			/* 0x4821 */
17764df55fdeSJanie Lu 			rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX;
17774df55fdeSJanie Lu 			rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
17784df55fdeSJanie Lu 			rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
17794df55fdeSJanie Lu 			rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
1780*9d587972SSantwona Behera 		}
17814df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17824df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
17834df55fdeSJanie Lu 		    portn, rx_cfg_l.value));
17844df55fdeSJanie Lu 
1785*9d587972SSantwona Behera 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGH) {
1786*9d587972SSantwona Behera 			rx_cfg_h.value = nxgep->srds_prop.rx_cfg_h;
1787*9d587972SSantwona Behera 		} else {
17884df55fdeSJanie Lu 			/* 0x0008 */
17894df55fdeSJanie Lu 			rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE;
1790*9d587972SSantwona Behera 		}
17914df55fdeSJanie Lu 
17924df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
17934df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
17944df55fdeSJanie Lu 		    portn, rx_cfg_h.value));
17954df55fdeSJanie Lu 
1796*9d587972SSantwona Behera 		if (nxgep->srds_prop.prop_set & NXGE_SRDS_PLLCFGL) {
1797*9d587972SSantwona Behera 			pll_cfg_l.value = nxgep->srds_prop.pll_cfg_l;
1798*9d587972SSantwona Behera 		} else {
17994df55fdeSJanie Lu 			/* 0xa1: Initialize PLL for 10G */
18004df55fdeSJanie Lu 			pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
18014df55fdeSJanie Lu 			pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
1802*9d587972SSantwona Behera 		}
18034df55fdeSJanie Lu 
18044df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18054df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
18064df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
18074df55fdeSJanie Lu 
18084df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
18094df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
18104df55fdeSJanie Lu 			goto fail;
18114df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18124df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
18134df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
1814*9d587972SSantwona Behera 
1815*9d587972SSantwona Behera 		/* Set loopback mode if necessary */
1816*9d587972SSantwona Behera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
1817*9d587972SSantwona Behera 			tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1818*9d587972SSantwona Behera 			rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
1819*9d587972SSantwona Behera 			rx_cfg_l.bits.los = 0;
1820*9d587972SSantwona Behera 
1821*9d587972SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1822*9d587972SSantwona Behera 			    "==> nxge_n2_kt_serdes_init port<%d>: "
1823*9d587972SSantwona Behera 			    "loopback 0x%x", portn, tx_cfg_h.value));
1824*9d587972SSantwona Behera 		}
18254df55fdeSJanie Lu #ifdef  NXGE_DEBUG
18264df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
18274df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
18284df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18294df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
18304df55fdeSJanie Lu 		    "PLL cfg.l 0x%x (0x%x)",
18314df55fdeSJanie Lu 		    portn, pll_cfg_l.value, cfg.value));
18324df55fdeSJanie Lu 
18334df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
18344df55fdeSJanie Lu 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
18354df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18364df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
18374df55fdeSJanie Lu 		    portn, cfg.value));
18384df55fdeSJanie Lu #endif
18394df55fdeSJanie Lu 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
18404df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
18414df55fdeSJanie Lu 	    nxgep->mac.portmode == PORT_1G_SERDES) {
18424df55fdeSJanie Lu 		mode_1g = B_TRUE;
18434df55fdeSJanie Lu 		/* 0x1e41 */
18444df55fdeSJanie Lu 		tx_cfg_l.bits.entx = 1;
18454df55fdeSJanie Lu 		tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
18464df55fdeSJanie Lu 		tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
18474df55fdeSJanie Lu 
18484df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18494df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
18504df55fdeSJanie Lu 		    portn, tx_cfg_l.value));
18514df55fdeSJanie Lu 
18524df55fdeSJanie Lu 
18534df55fdeSJanie Lu 		/* channel 0: enable syn. master */
18544df55fdeSJanie Lu 		tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
18554df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18564df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
18574df55fdeSJanie Lu 		    portn, tx_cfg_h.value));
18584df55fdeSJanie Lu 
18594df55fdeSJanie Lu 
18604df55fdeSJanie Lu 		/* 0x4841 */
18614df55fdeSJanie Lu 		rx_cfg_l.bits.enrx = 1;
18624df55fdeSJanie Lu 		rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
18634df55fdeSJanie Lu 		rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
18644df55fdeSJanie Lu 		rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
18654df55fdeSJanie Lu 
18664df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18674df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
18684df55fdeSJanie Lu 		    portn, rx_cfg_l.value));
18694df55fdeSJanie Lu 
18704df55fdeSJanie Lu 		/* 0x0008 */
18714df55fdeSJanie Lu 		rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF;
18724df55fdeSJanie Lu 
18734df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18744df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
18754df55fdeSJanie Lu 		    portn, rx_cfg_h.value));
18764df55fdeSJanie Lu 
18774df55fdeSJanie Lu 		/* 0xa1: Initialize PLL for 1G */
18784df55fdeSJanie Lu 		pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
18794df55fdeSJanie Lu 		pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
18804df55fdeSJanie Lu 
18814df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18824df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
18834df55fdeSJanie Lu 		    portn, pll_cfg_l.value));
18844df55fdeSJanie Lu 
18854df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
18864df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
18874df55fdeSJanie Lu 		    != NXGE_OK)
18884df55fdeSJanie Lu 			goto fail;
18894df55fdeSJanie Lu 
18904df55fdeSJanie Lu 
18914df55fdeSJanie Lu #ifdef  NXGE_DEBUG
18924df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
18934df55fdeSJanie Lu 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
18944df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18954df55fdeSJanie Lu 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
18964df55fdeSJanie Lu 		    portn, pll_cfg_l.value, cfg.value));
18974df55fdeSJanie Lu 
18984df55fdeSJanie Lu 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
18994df55fdeSJanie Lu 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
19004df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19014df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
19024df55fdeSJanie Lu 		    portn, cfg.value));
19034df55fdeSJanie Lu #endif
19044df55fdeSJanie Lu 
19054df55fdeSJanie Lu 		/* Set loopback mode if necessary */
19064df55fdeSJanie Lu 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
19074df55fdeSJanie Lu 			tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
19084df55fdeSJanie Lu 
19094df55fdeSJanie Lu 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19104df55fdeSJanie Lu 			    "==> nxge_n2_kt_serdes_init port<%d>: "
19114df55fdeSJanie Lu 			    "loopback 0x%x", portn, test_cfg.value));
19124df55fdeSJanie Lu 			if ((status = nxge_mdio_write(nxgep, portn,
19134df55fdeSJanie Lu 			    ESR_N2_DEV_ADDR,
19144df55fdeSJanie Lu 			    ESR_N2_TX_CFG_L_REG_ADDR(0),
19154df55fdeSJanie Lu 			    tx_cfg_h.value)) != NXGE_OK) {
19164df55fdeSJanie Lu 				goto fail;
19174df55fdeSJanie Lu 			}
19184df55fdeSJanie Lu 		}
19194df55fdeSJanie Lu 	} else {
19204df55fdeSJanie Lu 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19214df55fdeSJanie Lu 		    "nxge_n2_kt_serdes_init:port<%d> - "
19224df55fdeSJanie Lu 		    "unsupported port mode %d",
19234df55fdeSJanie Lu 		    portn, nxgep->mac.portmode));
19244df55fdeSJanie Lu 		goto fail;
19254df55fdeSJanie Lu 	}
19264df55fdeSJanie Lu 
19274df55fdeSJanie Lu 	NXGE_DELAY(20);
19284df55fdeSJanie Lu 	/* Clear the test register (offset 0x8004) */
19294df55fdeSJanie Lu 	if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
19304df55fdeSJanie Lu 	    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
19314df55fdeSJanie Lu 		goto fail;
19324df55fdeSJanie Lu 	}
19334df55fdeSJanie Lu 	NXGE_DELAY(20);
19344df55fdeSJanie Lu 
19354df55fdeSJanie Lu 	/* init TX channels */
19364df55fdeSJanie Lu 	for (chan = 0; chan < 4; chan++) {
19374df55fdeSJanie Lu 		if (mode_1g)
19384df55fdeSJanie Lu 			tx_cfg_l.value = 0;
19394df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
19404df55fdeSJanie Lu 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
19414df55fdeSJanie Lu 			goto fail;
19424df55fdeSJanie Lu 
19434df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
19444df55fdeSJanie Lu 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
19454df55fdeSJanie Lu 			goto fail;
19464df55fdeSJanie Lu 
19474df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19484df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
19494df55fdeSJanie Lu 		    "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value));
19504df55fdeSJanie Lu 
19514df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19524df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
19534df55fdeSJanie Lu 		    "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value));
19544df55fdeSJanie Lu 	}
19554df55fdeSJanie Lu 
19564df55fdeSJanie Lu 	/* init RX channels */
19574df55fdeSJanie Lu 	/* 1G mode only write to the first channel */
19584df55fdeSJanie Lu 	for (chan = 0; chan < 4; chan++) {
19594df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
19604df55fdeSJanie Lu 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
19614df55fdeSJanie Lu 		    != NXGE_OK)
19624df55fdeSJanie Lu 			goto fail;
19634df55fdeSJanie Lu 
19644df55fdeSJanie Lu 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
19654df55fdeSJanie Lu 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
19664df55fdeSJanie Lu 		    != NXGE_OK)
19674df55fdeSJanie Lu 			goto fail;
19684df55fdeSJanie Lu 
19694df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19704df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
19714df55fdeSJanie Lu 		    "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value));
19724df55fdeSJanie Lu 
19734df55fdeSJanie Lu 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19744df55fdeSJanie Lu 		    "==> nxge_n2_kt_serdes_init port<%d>: "
19754df55fdeSJanie Lu 		    "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value));
19764df55fdeSJanie Lu 	}
19774df55fdeSJanie Lu 
197889282175SSantwona Behera 	if (portn == 0) {
197989282175SSantwona Behera 		/* Wait for serdes to be ready */
198089282175SSantwona Behera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
198189282175SSantwona Behera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
198289282175SSantwona Behera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
198389282175SSantwona Behera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
198489282175SSantwona Behera 			    ESR_SIG_XSERDES_RDY_P0 |
198589282175SSantwona Behera 			    ESR_SIG_XDETECT_P0_CH3 |
198689282175SSantwona Behera 			    ESR_SIG_XDETECT_P0_CH2 |
198789282175SSantwona Behera 			    ESR_SIG_XDETECT_P0_CH1 |
198889282175SSantwona Behera 			    ESR_SIG_XDETECT_P0_CH0))
198989282175SSantwona Behera 
199089282175SSantwona Behera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
199189282175SSantwona Behera 			else
199289282175SSantwona Behera 				break;
199389282175SSantwona Behera 		}
199489282175SSantwona Behera 
199589282175SSantwona Behera 		if (i == MAX_SERDES_RDY_RETRIES) {
199689282175SSantwona Behera 			/*
199789282175SSantwona Behera 			 * RDY signal stays low may due to the absent of the
199889282175SSantwona Behera 			 * external PHY, it is not an error condition.
199989282175SSantwona Behera 			 * But still print the message for the debugging
200089282175SSantwona Behera 			 * purpose when link stays down
200189282175SSantwona Behera 			 */
200289282175SSantwona Behera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
200389282175SSantwona Behera 			    "nxge_n2_kt_serdes_init: "
200489282175SSantwona Behera 			    "Serdes/signal for port<%d> not ready", portn));
200589282175SSantwona Behera 				goto done;
200689282175SSantwona Behera 		}
200789282175SSantwona Behera 	} else if (portn == 1) {
200889282175SSantwona Behera 		/* Wait for serdes to be ready */
200989282175SSantwona Behera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
201089282175SSantwona Behera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
201189282175SSantwona Behera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
201289282175SSantwona Behera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
201389282175SSantwona Behera 			    ESR_SIG_XSERDES_RDY_P1 |
201489282175SSantwona Behera 			    ESR_SIG_XDETECT_P1_CH3 |
201589282175SSantwona Behera 			    ESR_SIG_XDETECT_P1_CH2 |
201689282175SSantwona Behera 			    ESR_SIG_XDETECT_P1_CH1 |
201789282175SSantwona Behera 			    ESR_SIG_XDETECT_P1_CH0))
201889282175SSantwona Behera 
201989282175SSantwona Behera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
202089282175SSantwona Behera 			else
202189282175SSantwona Behera 				break;
202289282175SSantwona Behera 		}
202389282175SSantwona Behera 
202489282175SSantwona Behera 		if (i == MAX_SERDES_RDY_RETRIES) {
202589282175SSantwona Behera 			/*
202689282175SSantwona Behera 			 * RDY signal stays low may due to the absent of the
202789282175SSantwona Behera 			 * external PHY, it is not an error condition.
202889282175SSantwona Behera 			 * But still print the message for the debugging
202989282175SSantwona Behera 			 * purpose when link stays down
203089282175SSantwona Behera 			 */
203189282175SSantwona Behera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
203289282175SSantwona Behera 			    "nxge_n2_kt_serdes_init: "
203389282175SSantwona Behera 			    "Serdes/signal for port<%d> not ready", portn));
203489282175SSantwona Behera 				goto done;
203589282175SSantwona Behera 		}
203689282175SSantwona Behera 	}
203789282175SSantwona Behera done:
203889282175SSantwona Behera 
20394df55fdeSJanie Lu 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
20404df55fdeSJanie Lu 	    "<== nxge_n2_kt_serdes_init port<%d>", portn));
20414df55fdeSJanie Lu 
20424df55fdeSJanie Lu 	return (NXGE_OK);
20434df55fdeSJanie Lu fail:
20444df55fdeSJanie Lu 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20454df55fdeSJanie Lu 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
20464df55fdeSJanie Lu 	    portn));
20474df55fdeSJanie Lu 
20484df55fdeSJanie Lu 	return (status);
20496f45ec7bSml29623 }
20506f45ec7bSml29623 
205159ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
20526f45ec7bSml29623 
205359ac0c16Sdavemq static nxge_status_t
205459ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
20556f45ec7bSml29623 {
20566f45ec7bSml29623 	npi_handle_t		handle;
20576f45ec7bSml29623 	uint8_t			portn;
2058321febdeSsbehera 	int			chan, i;
20596f45ec7bSml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
20606f45ec7bSml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
20616f45ec7bSml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
20626f45ec7bSml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
20636f45ec7bSml29623 	uint64_t		val;
20646f45ec7bSml29623 	uint16_t		val16l;
20656f45ec7bSml29623 	uint16_t		val16h;
20666f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
20676f45ec7bSml29623 
20686f45ec7bSml29623 	portn = nxgep->mac.portnum;
20696f45ec7bSml29623 
20706f45ec7bSml29623 	if ((portn != 0) && (portn != 1))
20716f45ec7bSml29623 		return (NXGE_OK);
20726f45ec7bSml29623 
207359ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
207459ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
20756f45ec7bSml29623 	handle = nxgep->npi_handle;
20766f45ec7bSml29623 	switch (portn) {
20776f45ec7bSml29623 	case 0:
20784202ea4bSsbehera 		/* Reset Serdes */
20794202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
20804202ea4bSsbehera 		NXGE_DELAY(20);
20814202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
20824202ea4bSsbehera 		NXGE_DELAY(2000);
20834202ea4bSsbehera 
20844202ea4bSsbehera 		/* Configure Serdes to 10G mode */
20854202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
20864202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
20874202ea4bSsbehera 
20886f45ec7bSml29623 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
20896f45ec7bSml29623 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
20906f45ec7bSml29623 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
20916f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
20926f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
20936f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
20946f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
20956f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
20966f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
20976f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
20986f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
20996f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
21006f45ec7bSml29623 
21016f45ec7bSml29623 		/* Set Serdes0 Internal Loopback if necessary */
210259ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
21036f45ec7bSml29623 			ESR_REG_WR(handle,
21046f45ec7bSml29623 			    ESR_0_TEST_CONFIG_REG,
21056f45ec7bSml29623 			    ESR_PAD_LOOPBACK_CH3 |
21066f45ec7bSml29623 			    ESR_PAD_LOOPBACK_CH2 |
21076f45ec7bSml29623 			    ESR_PAD_LOOPBACK_CH1 |
21086f45ec7bSml29623 			    ESR_PAD_LOOPBACK_CH0);
21096f45ec7bSml29623 		} else {
211059ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
21116f45ec7bSml29623 		}
21126f45ec7bSml29623 		break;
21136f45ec7bSml29623 	case 1:
21144202ea4bSsbehera 		/* Reset Serdes */
21154202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
21164202ea4bSsbehera 		NXGE_DELAY(20);
21174202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
21184202ea4bSsbehera 		NXGE_DELAY(2000);
21194202ea4bSsbehera 
21204202ea4bSsbehera 		/* Configure Serdes to 10G mode */
21214202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
21224202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
21234202ea4bSsbehera 
21246f45ec7bSml29623 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
21256f45ec7bSml29623 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
21266f45ec7bSml29623 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
21276f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
21286f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
21296f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
21306f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
21316f45ec7bSml29623 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
21326f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
21336f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
21346f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
21356f45ec7bSml29623 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
21366f45ec7bSml29623 
21376f45ec7bSml29623 		/* Set Serdes1 Internal Loopback if necessary */
213859ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
213959ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
214059ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
214159ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
21426f45ec7bSml29623 		} else {
214359ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
21446f45ec7bSml29623 		}
21456f45ec7bSml29623 		break;
21466f45ec7bSml29623 	default:
21476f45ec7bSml29623 		/* Nothing to do here */
21486f45ec7bSml29623 		goto done;
21496f45ec7bSml29623 	}
21506f45ec7bSml29623 
21516f45ec7bSml29623 	/* init TX RX channels */
21526f45ec7bSml29623 	for (chan = 0; chan < 4; chan++) {
21536f45ec7bSml29623 		if ((status = nxge_mdio_read(nxgep, portn,
215459ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
21556f45ec7bSml29623 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
21566f45ec7bSml29623 			goto fail;
21576f45ec7bSml29623 		if ((status = nxge_mdio_read(nxgep, portn,
215859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
21596f45ec7bSml29623 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
21606f45ec7bSml29623 			goto fail;
21616f45ec7bSml29623 		if ((status = nxge_mdio_read(nxgep, portn,
216259ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
21636f45ec7bSml29623 		    &glue_ctrl0_l.value)) != NXGE_OK)
21646f45ec7bSml29623 			goto fail;
21656f45ec7bSml29623 		if ((status = nxge_mdio_read(nxgep, portn,
216659ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
21676f45ec7bSml29623 		    &glue_ctrl0_h.value)) != NXGE_OK)
21686f45ec7bSml29623 			goto fail;
21696f45ec7bSml29623 		rx_tx_ctrl_l.bits.enstretch = 1;
21706f45ec7bSml29623 		rx_tx_ctrl_h.bits.vmuxlo = 2;
21716f45ec7bSml29623 		rx_tx_ctrl_h.bits.vpulselo = 2;
21726f45ec7bSml29623 		glue_ctrl0_l.bits.rxlosenable = 1;
21736f45ec7bSml29623 		glue_ctrl0_l.bits.samplerate = 0xF;
21746f45ec7bSml29623 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
21756f45ec7bSml29623 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
21766f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn,
217759ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
21786f45ec7bSml29623 		    rx_tx_ctrl_l.value)) != NXGE_OK)
21796f45ec7bSml29623 			goto fail;
21806f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn,
218159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
21826f45ec7bSml29623 		    rx_tx_ctrl_h.value)) != NXGE_OK)
21836f45ec7bSml29623 			goto fail;
21846f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn,
218559ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
21866f45ec7bSml29623 		    glue_ctrl0_l.value)) != NXGE_OK)
21876f45ec7bSml29623 			goto fail;
21886f45ec7bSml29623 		if ((status = nxge_mdio_write(nxgep, portn,
218959ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
21906f45ec7bSml29623 		    glue_ctrl0_h.value)) != NXGE_OK)
21916f45ec7bSml29623 			goto fail;
21926f45ec7bSml29623 		}
21936f45ec7bSml29623 
21946f45ec7bSml29623 	/* Apply Tx core reset */
21956f45ec7bSml29623 	if ((status = nxge_mdio_write(nxgep, portn,
219659ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
21976f45ec7bSml29623 	    (uint16_t)0)) != NXGE_OK)
21986f45ec7bSml29623 		goto fail;
21996f45ec7bSml29623 
220059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
220159ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
220259ac0c16Sdavemq 	    NXGE_OK)
22036f45ec7bSml29623 		goto fail;
22046f45ec7bSml29623 
22056f45ec7bSml29623 	NXGE_DELAY(200);
22066f45ec7bSml29623 
22076f45ec7bSml29623 	/* Apply Rx core reset */
220859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
220959ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
221059ac0c16Sdavemq 	    NXGE_OK)
22116f45ec7bSml29623 		goto fail;
22126f45ec7bSml29623 
22136f45ec7bSml29623 	NXGE_DELAY(200);
221459ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
221559ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
22166f45ec7bSml29623 		goto fail;
22176f45ec7bSml29623 
22186f45ec7bSml29623 	NXGE_DELAY(200);
22196f45ec7bSml29623 	if ((status = nxge_mdio_read(nxgep, portn,
222059ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
22216f45ec7bSml29623 	    &val16l)) != NXGE_OK)
22226f45ec7bSml29623 		goto fail;
222359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
222459ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
22256f45ec7bSml29623 		goto fail;
22266f45ec7bSml29623 	if ((val16l != 0) || (val16h != 0)) {
22276f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2228d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2229d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
2230d81011f0Ssbehera 		    portn, val16l, val16h));
22316f45ec7bSml29623 	}
22326f45ec7bSml29623 
22336f45ec7bSml29623 	if (portn == 0) {
2234321febdeSsbehera 		/* Wait for serdes to be ready */
2235321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2236321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
22376f45ec7bSml29623 			if ((val & ESR_SIG_P0_BITS_MASK) !=
22386f45ec7bSml29623 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
22396f45ec7bSml29623 			    ESR_SIG_XSERDES_RDY_P0 |
22406f45ec7bSml29623 			    ESR_SIG_XDETECT_P0_CH3 |
22416f45ec7bSml29623 			    ESR_SIG_XDETECT_P0_CH2 |
22426f45ec7bSml29623 			    ESR_SIG_XDETECT_P0_CH1 |
2243321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
2244321febdeSsbehera 
2245321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2246321febdeSsbehera 			else
2247321febdeSsbehera 				break;
2248321febdeSsbehera 		}
2249321febdeSsbehera 
2250321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
2251ab6abb7aSjoycey 			/*
2252ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2253ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2254ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2255ab6abb7aSjoycey 			 * stays down
2256ab6abb7aSjoycey 			 */
2257774da109Stc99174@train 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2258321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
2259321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
2260ab6abb7aSjoycey 				goto done;
22616f45ec7bSml29623 		}
22626f45ec7bSml29623 	} else if (portn == 1) {
2263321febdeSsbehera 		/* Wait for serdes to be ready */
2264321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
2265321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
22666f45ec7bSml29623 			if ((val & ESR_SIG_P1_BITS_MASK) !=
22676f45ec7bSml29623 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
22686f45ec7bSml29623 			    ESR_SIG_XSERDES_RDY_P1 |
22696f45ec7bSml29623 			    ESR_SIG_XDETECT_P1_CH3 |
22706f45ec7bSml29623 			    ESR_SIG_XDETECT_P1_CH2 |
22716f45ec7bSml29623 			    ESR_SIG_XDETECT_P1_CH1 |
2272321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
2273321febdeSsbehera 
2274321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
2275321febdeSsbehera 			else
2276321febdeSsbehera 				break;
2277321febdeSsbehera 		}
2278321febdeSsbehera 
2279321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
2280ab6abb7aSjoycey 			/*
2281ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2282ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2283ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2284ab6abb7aSjoycey 			 * stays down
2285ab6abb7aSjoycey 			 */
2286774da109Stc99174@train 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2287321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
2288321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
2289ab6abb7aSjoycey 				goto done;
22906f45ec7bSml29623 		}
22916f45ec7bSml29623 	}
22926f45ec7bSml29623 
229359ac0c16Sdavemq done:
229459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
229559ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
229659ac0c16Sdavemq 
229759ac0c16Sdavemq 	return (NXGE_OK);
229859ac0c16Sdavemq fail:
22992d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
230059ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
230159ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
230259ac0c16Sdavemq 
230359ac0c16Sdavemq 	return (status);
230459ac0c16Sdavemq }
230559ac0c16Sdavemq 
230659ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
230759ac0c16Sdavemq 
230859ac0c16Sdavemq static nxge_status_t
230959ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
231059ac0c16Sdavemq {
231159ac0c16Sdavemq 	npi_handle_t		handle;
231259ac0c16Sdavemq 	uint8_t			portn;
2313d81011f0Ssbehera 	int			chan;
2314d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
2315d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
2316d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
2317d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
231859ac0c16Sdavemq 	uint64_t		val;
2319d81011f0Ssbehera 	uint16_t		val16l;
2320d81011f0Ssbehera 	uint16_t		val16h;
2321d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
232259ac0c16Sdavemq 
232359ac0c16Sdavemq 	portn = nxgep->mac.portnum;
232459ac0c16Sdavemq 
232559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
232659ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
232759ac0c16Sdavemq 
232859ac0c16Sdavemq 	handle = nxgep->npi_handle;
232959ac0c16Sdavemq 
23306f45ec7bSml29623 	switch (portn) {
23316f45ec7bSml29623 	case 0:
2332d81011f0Ssbehera 		/* Assert the reset register */
2333d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2334d81011f0Ssbehera 		val |= ESR_RESET_0;
2335d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2336d81011f0Ssbehera 
2337d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
2338d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
2339d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
2340d81011f0Ssbehera 
2341d81011f0Ssbehera 		/* Set the control register to 0x249249f */
2342d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
2343d81011f0Ssbehera 
2344d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
2345d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2346d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
2347d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
2348d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
2349d81011f0Ssbehera 		} else {
2350d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
2351d81011f0Ssbehera 		}
2352d81011f0Ssbehera 
2353d81011f0Ssbehera 		/* Deassert the reset register */
2354d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2355d81011f0Ssbehera 		val &= ~ESR_RESET_0;
2356d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
23576f45ec7bSml29623 		break;
2358d81011f0Ssbehera 
23596f45ec7bSml29623 	case 1:
2360d81011f0Ssbehera 		/* Assert the reset register */
2361d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2362d81011f0Ssbehera 		val |= ESR_RESET_1;
2363d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
2364d81011f0Ssbehera 
2365d81011f0Ssbehera 		/* Set PLL register to 0x79 */
2366d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
2367d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
2368d81011f0Ssbehera 
2369d81011f0Ssbehera 		/* Set the control register to 0x249249f */
2370d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
2371d81011f0Ssbehera 
2372d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
2373d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
2374d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
2375d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
2376d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
2377d81011f0Ssbehera 		} else {
2378d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2379d81011f0Ssbehera 		}
2380d81011f0Ssbehera 
2381d81011f0Ssbehera 		/* Deassert the reset register */
2382d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2383d81011f0Ssbehera 		val &= ~ESR_RESET_1;
2384d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
23856f45ec7bSml29623 		break;
2386d81011f0Ssbehera 
23876f45ec7bSml29623 	default:
2388d81011f0Ssbehera 		/* Nothing to do here */
2389d81011f0Ssbehera 		goto done;
2390d81011f0Ssbehera 	}
2391d81011f0Ssbehera 
2392d81011f0Ssbehera 	/* init TX RX channels */
2393d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
2394d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2395d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2396d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
2397d81011f0Ssbehera 			goto fail;
2398d81011f0Ssbehera 		}
2399d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2400d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2401d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
2402d81011f0Ssbehera 			goto fail;
2403d81011f0Ssbehera 		}
2404d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2405d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2406d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
2407d81011f0Ssbehera 			goto fail;
2408d81011f0Ssbehera 		}
2409d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2410d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2411d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
24126f45ec7bSml29623 			goto fail;
24136f45ec7bSml29623 		}
24146f45ec7bSml29623 
2415d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
2416d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2417d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
2418d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
2419d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
2420d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2421d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2422d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2423d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2424d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
2425d81011f0Ssbehera 			goto fail;
2426d81011f0Ssbehera 		}
2427d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2428d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2429d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
2430d81011f0Ssbehera 			goto fail;
2431d81011f0Ssbehera 		}
2432d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2433d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2434d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
2435d81011f0Ssbehera 			goto fail;
2436d81011f0Ssbehera 		}
2437d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2438d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2439d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
2440d81011f0Ssbehera 			goto fail;
2441d81011f0Ssbehera 		}
2442d81011f0Ssbehera 	}
2443d81011f0Ssbehera 
2444d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2445d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2446d81011f0Ssbehera 		goto fail;
2447d81011f0Ssbehera 	}
2448d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2449d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2450d81011f0Ssbehera 		goto fail;
2451d81011f0Ssbehera 	}
2452d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2453d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2454d81011f0Ssbehera 		goto fail;
2455d81011f0Ssbehera 	}
2456d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2457d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2458d81011f0Ssbehera 		goto fail;
2459d81011f0Ssbehera 	}
2460d81011f0Ssbehera 
2461d81011f0Ssbehera 	/* Apply Tx core reset */
2462d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2463d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2464d81011f0Ssbehera 		goto fail;
2465d81011f0Ssbehera 	}
2466d81011f0Ssbehera 
2467d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2468d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2469d81011f0Ssbehera 	    NXGE_OK) {
2470d81011f0Ssbehera 		goto fail;
2471d81011f0Ssbehera 	}
2472d81011f0Ssbehera 
2473d81011f0Ssbehera 	NXGE_DELAY(200);
2474d81011f0Ssbehera 
2475d81011f0Ssbehera 	/* Apply Rx core reset */
2476d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2477d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2478d81011f0Ssbehera 	    NXGE_OK) {
2479d81011f0Ssbehera 		goto fail;
2480d81011f0Ssbehera 	}
2481d81011f0Ssbehera 
2482d81011f0Ssbehera 	NXGE_DELAY(200);
2483d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2484d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2485d81011f0Ssbehera 		goto fail;
2486d81011f0Ssbehera 	}
2487d81011f0Ssbehera 
2488d81011f0Ssbehera 	NXGE_DELAY(200);
2489d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2490d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2491d81011f0Ssbehera 		goto fail;
2492d81011f0Ssbehera 	}
2493d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2494d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2495d81011f0Ssbehera 		goto fail;
2496d81011f0Ssbehera 	}
2497d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
2498d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2499d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2500d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2501d81011f0Ssbehera 		status = NXGE_ERROR;
2502d81011f0Ssbehera 		goto fail;
2503d81011f0Ssbehera 	}
2504d81011f0Ssbehera 
2505d81011f0Ssbehera 	NXGE_DELAY(200);
2506d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2507d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2508d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2509d81011f0Ssbehera 	    "val 0x%x", portn, val));
2510d81011f0Ssbehera 	if (portn == 0) {
2511d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2512d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2513ab6abb7aSjoycey 			/*
2514ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2515ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2516ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2517ab6abb7aSjoycey 			 * stays down
2518ab6abb7aSjoycey 			 */
2519d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2520ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2521ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
2522ab6abb7aSjoycey 				goto done;
2523d81011f0Ssbehera 		}
2524d81011f0Ssbehera 	} else if (portn == 1) {
2525d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2526d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2527ab6abb7aSjoycey 			/*
2528ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2529ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2530ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2531ab6abb7aSjoycey 			 * stays down
2532ab6abb7aSjoycey 			 */
2533d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2534ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2535ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
2536ab6abb7aSjoycey 				goto done;
253700161856Syc148097 
2538d81011f0Ssbehera 		}
2539d81011f0Ssbehera 	}
2540d81011f0Ssbehera done:
25416f45ec7bSml29623 
254259ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
254359ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
25446f45ec7bSml29623 	return (NXGE_OK);
25456f45ec7bSml29623 fail:
2546d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
254759ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
25486f45ec7bSml29623 	    "Failed to initialize Neptune serdes for port<%d>",
25496f45ec7bSml29623 	    portn));
25506f45ec7bSml29623 
2551d81011f0Ssbehera 	return (status);
25526f45ec7bSml29623 }
25536f45ec7bSml29623 
2554*9d587972SSantwona Behera #define	NXGE_SET_PHY_TUNABLES(nxgep, phy_port, stat)			\
2555*9d587972SSantwona Behera {									\
2556*9d587972SSantwona Behera 	int i;								\
2557*9d587972SSantwona Behera 									\
2558*9d587972SSantwona Behera 	if (nxgep->phy_prop.cnt > 0) {					\
2559*9d587972SSantwona Behera 		for (i = 0; i < nxgep->phy_prop.cnt; i++) {		\
2560*9d587972SSantwona Behera 			if ((stat = nxge_mdio_write(nxgep, phy_port,	\
2561*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].dev,			\
2562*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].reg,			\
2563*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].val)) != NXGE_OK) {	\
2564*9d587972SSantwona Behera 				break;					\
2565*9d587972SSantwona Behera 			}						\
2566*9d587972SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,			\
2567*9d587972SSantwona Behera 			    "From OBP, write<dev.reg.val> = "		\
2568*9d587972SSantwona Behera 			    "<0x%x.0x%x.0x%x>",				\
2569*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].dev,			\
2570*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].reg,			\
2571*9d587972SSantwona Behera 			    nxgep->phy_prop.arr[i].val));		\
2572*9d587972SSantwona Behera 		}							\
2573*9d587972SSantwona Behera 	}								\
2574*9d587972SSantwona Behera }
2575*9d587972SSantwona Behera 
25762d17280bSsbehera /* Initialize the BCM 8704 xcvr */
25776f45ec7bSml29623 
257859ac0c16Sdavemq static nxge_status_t
25792d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
25806f45ec7bSml29623 {
25816f45ec7bSml29623 	uint16_t		val;
25826f45ec7bSml29623 #ifdef	NXGE_DEBUG
25836f45ec7bSml29623 	uint8_t			portn;
25846f45ec7bSml29623 	uint16_t		val1;
25856f45ec7bSml29623 #endif
25866f45ec7bSml29623 	uint8_t			phy_port_addr;
25876f45ec7bSml29623 	pmd_tx_control_t	tx_ctl;
25886f45ec7bSml29623 	control_t		ctl;
25896f45ec7bSml29623 	phyxs_control_t		phyxs_ctl;
25906f45ec7bSml29623 	pcs_control_t		pcs_ctl;
25916f45ec7bSml29623 	uint32_t		delay = 0;
25926f45ec7bSml29623 	optics_dcntr_t		op_ctr;
25936f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
25946f45ec7bSml29623 #ifdef	NXGE_DEBUG
25956f45ec7bSml29623 	portn = nxgep->mac.portnum;
25966f45ec7bSml29623 #endif
2597*9d587972SSantwona Behera 
25982d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
259959ac0c16Sdavemq 	    portn));
26006f45ec7bSml29623 
26016f45ec7bSml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
26026f45ec7bSml29623 
26036f45ec7bSml29623 	/* Reset the transceiver */
260459ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
260559ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
26066f45ec7bSml29623 		goto fail;
26076f45ec7bSml29623 
26086f45ec7bSml29623 	phyxs_ctl.bits.reset = 1;
260959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
261059ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
26116f45ec7bSml29623 		goto fail;
26126f45ec7bSml29623 
26136f45ec7bSml29623 	do {
26146f45ec7bSml29623 		drv_usecwait(500);
261559ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
261659ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
26176f45ec7bSml29623 		    &phyxs_ctl.value)) != NXGE_OK)
26186f45ec7bSml29623 			goto fail;
26196f45ec7bSml29623 		delay++;
26206f45ec7bSml29623 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
26216f45ec7bSml29623 	if (delay == 100) {
262259ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
262359ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
26246f45ec7bSml29623 		status = NXGE_ERROR;
26256f45ec7bSml29623 		goto fail;
26266f45ec7bSml29623 	}
26276f45ec7bSml29623 
26286f45ec7bSml29623 	/* Set to 0x7FBF */
26296f45ec7bSml29623 	ctl.value = 0;
26306f45ec7bSml29623 	ctl.bits.res1 = 0x3F;
26316f45ec7bSml29623 	ctl.bits.optxon_lvl = 1;
26326f45ec7bSml29623 	ctl.bits.oprxflt_lvl = 1;
26336f45ec7bSml29623 	ctl.bits.optrxlos_lvl = 1;
26346f45ec7bSml29623 	ctl.bits.optxflt_lvl = 1;
26356f45ec7bSml29623 	ctl.bits.opprflt_lvl = 1;
26366f45ec7bSml29623 	ctl.bits.obtmpflt_lvl = 1;
26376f45ec7bSml29623 	ctl.bits.opbiasflt_lvl = 1;
26386f45ec7bSml29623 	ctl.bits.optxrst_lvl = 1;
263959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
264059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
26416f45ec7bSml29623 	    != NXGE_OK)
26426f45ec7bSml29623 		goto fail;
26436f45ec7bSml29623 
26446f45ec7bSml29623 	/* Set to 0x164 */
26456f45ec7bSml29623 	tx_ctl.value = 0;
26466f45ec7bSml29623 	tx_ctl.bits.tsck_lpwren = 1;
26476f45ec7bSml29623 	tx_ctl.bits.tx_dac_txck = 0x2;
26486f45ec7bSml29623 	tx_ctl.bits.tx_dac_txd = 0x1;
26496f45ec7bSml29623 	tx_ctl.bits.xfp_clken = 1;
265059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
265159ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
265259ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
26536f45ec7bSml29623 		goto fail;
26546f45ec7bSml29623 	/*
26556f45ec7bSml29623 	 * According to Broadcom's instruction, SW needs to read
26566f45ec7bSml29623 	 * back these registers twice after written.
26576f45ec7bSml29623 	 */
265859ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
265959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
26606f45ec7bSml29623 	    != NXGE_OK)
26616f45ec7bSml29623 		goto fail;
26626f45ec7bSml29623 
266359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
266459ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
26656f45ec7bSml29623 	    != NXGE_OK)
26666f45ec7bSml29623 		goto fail;
26676f45ec7bSml29623 
266859ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
266959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
26706f45ec7bSml29623 	    != NXGE_OK)
26716f45ec7bSml29623 		goto fail;
26726f45ec7bSml29623 
267359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
267459ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
26756f45ec7bSml29623 	    != NXGE_OK)
26766f45ec7bSml29623 		goto fail;
26776f45ec7bSml29623 
26786f45ec7bSml29623 	/* Enable Tx and Rx LEDs to be driven by traffic */
267959ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
268059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
26816f45ec7bSml29623 	    &op_ctr.value)) != NXGE_OK)
26826f45ec7bSml29623 		goto fail;
2683cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2684cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
2685cb9d3ae6Smisaki 	} else {
26866f45ec7bSml29623 		op_ctr.bits.gpio_sel = 0x3;
2687cb9d3ae6Smisaki 	}
268859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
268959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
26906f45ec7bSml29623 	    op_ctr.value)) != NXGE_OK)
26916f45ec7bSml29623 		goto fail;
26926f45ec7bSml29623 
26936f45ec7bSml29623 	NXGE_DELAY(1000000);
26946f45ec7bSml29623 
2695*9d587972SSantwona Behera 	/*
2696*9d587972SSantwona Behera 	 * Set XAUI link tunables from OBP if present.
2697*9d587972SSantwona Behera 	 */
2698*9d587972SSantwona Behera 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2699*9d587972SSantwona Behera 	if (status != NXGE_OK) {
2700*9d587972SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2701*9d587972SSantwona Behera 		    "nxge_BCM8704_xcvr_init: Failed setting PHY tunables"));
2702*9d587972SSantwona Behera 		goto fail;
2703*9d587972SSantwona Behera 	}
2704*9d587972SSantwona Behera 
27056f45ec7bSml29623 	/* Set BCM8704 Internal Loopback mode if necessary */
270659ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
270759ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
270859ac0c16Sdavemq 	    != NXGE_OK)
27096f45ec7bSml29623 		goto fail;
27106f45ec7bSml29623 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
27116f45ec7bSml29623 		pcs_ctl.bits.loopback = 1;
27126f45ec7bSml29623 	else
27136f45ec7bSml29623 		pcs_ctl.bits.loopback = 0;
271459ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
271559ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
271659ac0c16Sdavemq 	    != NXGE_OK)
27176f45ec7bSml29623 		goto fail;
27186f45ec7bSml29623 
271959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
27206f45ec7bSml29623 	if (status != NXGE_OK)
27216f45ec7bSml29623 		goto fail;
27226f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
272359ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
27246f45ec7bSml29623 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
27256f45ec7bSml29623 	if (status != NXGE_OK)
27266f45ec7bSml29623 		goto fail;
27276f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
272859ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
27296f45ec7bSml29623 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
27306f45ec7bSml29623 	if (status != NXGE_OK)
27316f45ec7bSml29623 		goto fail;
27326f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
273359ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
27346f45ec7bSml29623 
27356f45ec7bSml29623 #ifdef	NXGE_DEBUG
27366f45ec7bSml29623 	/* Diagnose link issue if link is not up */
273759ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
27386f45ec7bSml29623 	    BCM8704_USER_ANALOG_STATUS0_REG,
27396f45ec7bSml29623 	    &val);
27406f45ec7bSml29623 	if (status != NXGE_OK)
27416f45ec7bSml29623 		goto fail;
27426f45ec7bSml29623 
27436f45ec7bSml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
274452ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
27456f45ec7bSml29623 	if (status != NXGE_OK)
27466f45ec7bSml29623 		goto fail;
27476f45ec7bSml29623 
27486f45ec7bSml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
274952ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
27506f45ec7bSml29623 	if (status != NXGE_OK)
27516f45ec7bSml29623 		goto fail;
27526f45ec7bSml29623 
27536f45ec7bSml29623 	status = nxge_mdio_read(nxgep, phy_port_addr,
275452ccf843Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
27556f45ec7bSml29623 	if (status != NXGE_OK)
27566f45ec7bSml29623 		goto fail;
27576f45ec7bSml29623 
27586f45ec7bSml29623 	if (val != 0x3FC) {
27596f45ec7bSml29623 		if ((val == 0x43BC) && (val1 != 0)) {
27606f45ec7bSml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
27616f45ec7bSml29623 			    "Cable not connected to peer or bad"
27626f45ec7bSml29623 			    " cable on port<%d>\n", portn));
27636f45ec7bSml29623 		} else if (val == 0x639C) {
27646f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
276559ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
27666f45ec7bSml29623 			    " on port<%d>\n", portn));
27676f45ec7bSml29623 		}
27686f45ec7bSml29623 	}
27696f45ec7bSml29623 #endif
27706f45ec7bSml29623 
27712d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
27722d17280bSsbehera 	    portn));
27732d17280bSsbehera 	return (NXGE_OK);
27742d17280bSsbehera 
27752d17280bSsbehera fail:
27762d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27772d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
27782d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
27792d17280bSsbehera 	return (NXGE_ERROR);
27802d17280bSsbehera }
27812d17280bSsbehera 
27822d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
27832d17280bSsbehera 
27842d17280bSsbehera static nxge_status_t
27852d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
27862d17280bSsbehera {
27872d17280bSsbehera 	uint8_t			phy_port_addr;
27882d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
27892d17280bSsbehera 	pcs_control_t		pcs_ctl;
27902d17280bSsbehera 	uint32_t		delay = 0;
27912d17280bSsbehera 	optics_dcntr_t		op_ctr;
27922d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
27932d17280bSsbehera #ifdef	NXGE_DEBUG
27942d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
27952d17280bSsbehera #endif
27962d17280bSsbehera 
27972d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
27982d17280bSsbehera 	    portn));
27992d17280bSsbehera 
28002d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
28012d17280bSsbehera 
28022d17280bSsbehera 	/* Reset the transceiver */
28032d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
28042d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
28052d17280bSsbehera 		goto fail;
28062d17280bSsbehera 
28072d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
28082d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
28092d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
28102d17280bSsbehera 		goto fail;
28112d17280bSsbehera 	do {
28122d17280bSsbehera 		drv_usecwait(500);
28132d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
28142d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
28152d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
28162d17280bSsbehera 			goto fail;
28172d17280bSsbehera 		delay++;
28182d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
28192d17280bSsbehera 
28202d17280bSsbehera 	if (delay == 100) {
28212d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
28222d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
28232d17280bSsbehera 		status = NXGE_ERROR;
28242d17280bSsbehera 		goto fail;
28252d17280bSsbehera 	}
28262d17280bSsbehera 
28272d17280bSsbehera 	NXGE_DELAY(1000000);
28282d17280bSsbehera 
2829*9d587972SSantwona Behera 	/*
2830*9d587972SSantwona Behera 	 * Set XAUI link tunables from OBP if present.
2831*9d587972SSantwona Behera 	 */
2832*9d587972SSantwona Behera 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
2833*9d587972SSantwona Behera 	if (status != NXGE_OK) {
2834*9d587972SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2835*9d587972SSantwona Behera 		    "nxge_BCM8706_xcvr_init: Failed setting PHY tunables"));
2836*9d587972SSantwona Behera 		goto fail;
2837*9d587972SSantwona Behera 	}
2838*9d587972SSantwona Behera 
28392d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
28402d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
28412d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
28422d17280bSsbehera 	    != NXGE_OK)
28432d17280bSsbehera 		goto fail;
28442d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
28452d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
28462d17280bSsbehera 	else
28472d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
28482d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
28492d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
28502d17280bSsbehera 	    != NXGE_OK)
28512d17280bSsbehera 		goto fail;
28522d17280bSsbehera 
28532d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
28542d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
28552d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
28562d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
28572d17280bSsbehera 		goto fail;
28582d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
28592d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
28602d17280bSsbehera 
28612d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
28622d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
28632d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
28642d17280bSsbehera 		goto fail;
28652d17280bSsbehera 
28662d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
28672d17280bSsbehera 	    portn));
28682d17280bSsbehera 	return (NXGE_OK);
28692d17280bSsbehera 
28702d17280bSsbehera fail:
28712d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
28722d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
28732d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
28742d17280bSsbehera 	return (status);
28752d17280bSsbehera }
28762d17280bSsbehera 
287789282175SSantwona Behera static int
287889282175SSantwona Behera nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address,
287989282175SSantwona Behera 	    uint16_t reg, uint8_t *data)
288089282175SSantwona Behera {
288189282175SSantwona Behera 	int  phy_dev, phy_reg;
288289282175SSantwona Behera 	uint16_t phy_data = 0;
288389282175SSantwona Behera 	uint16_t stat;
288489282175SSantwona Behera 	uint8_t count = 100;
288589282175SSantwona Behera 
288689282175SSantwona Behera 	/*
288789282175SSantwona Behera 	 * NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address
288889282175SSantwona Behera 	 * NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c
288989282175SSantwona Behera 	 */
289089282175SSantwona Behera 	phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR;
289189282175SSantwona Behera 	phy_reg = NLP2020_I2C_SNOOP_ADDR_REG;
289289282175SSantwona Behera 	phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg;
289389282175SSantwona Behera 	if (nxge_mdio_write(nxgep, ctrl_port,
289489282175SSantwona Behera 	    phy_dev, phy_reg, phy_data) != NXGE_OK)
289589282175SSantwona Behera 		goto fail;
289689282175SSantwona Behera 
289789282175SSantwona Behera 	phy_reg = NLP2020_I2C_SNOOP_STAT_REG;
289889282175SSantwona Behera 	(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat);
289989282175SSantwona Behera 	while ((stat != 0x01) && (count-- > 0)) {
290089282175SSantwona Behera 		(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
290189282175SSantwona Behera 		    &stat);
290289282175SSantwona Behera 	}
290389282175SSantwona Behera 	if (count) {
290489282175SSantwona Behera 		phy_reg = NLP2020_I2C_SNOOP_DATA_REG;
290589282175SSantwona Behera 		(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
290689282175SSantwona Behera 		    &phy_data);
290789282175SSantwona Behera 		*data = (phy_data >> 8);
290889282175SSantwona Behera 		return (0);
290989282175SSantwona Behera 	}
291089282175SSantwona Behera fail:
291189282175SSantwona Behera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
291289282175SSantwona Behera 	    "nxge_nlp2020_i2c_read: FAILED"));
291389282175SSantwona Behera 	return (1);
291489282175SSantwona Behera 
291589282175SSantwona Behera }
291689282175SSantwona Behera 
291789282175SSantwona Behera /* Initialize the Netlogic AEL2020 Transceiver */
291889282175SSantwona Behera 
291989282175SSantwona Behera #define	NLP_INI_WAIT	1
292089282175SSantwona Behera #define	NLP_INI_STOP	0
292189282175SSantwona Behera 
292289282175SSantwona Behera static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = {
292389282175SSantwona Behera 	{0x1C003, 0x3101},
292489282175SSantwona Behera 	{0x1CC01, 0x488a},
292589282175SSantwona Behera 	{0x1CB1B, 0x0200},
292689282175SSantwona Behera 	{0x1CB1C, 0x00f0},
292789282175SSantwona Behera 	{0x1CC06, 0x00e0},
292889282175SSantwona Behera 	{NLP_INI_STOP, 0},
292989282175SSantwona Behera };
293089282175SSantwona Behera 
293189282175SSantwona Behera static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = {
293289282175SSantwona Behera 
293389282175SSantwona Behera 	{0x1C003, 0x3101},
293489282175SSantwona Behera 	{0x1CD40, 0x0001},
293589282175SSantwona Behera 
293689282175SSantwona Behera 	{0x1CA12, 0x0100},
293789282175SSantwona Behera 	{0x1CA22, 0x0100},
293889282175SSantwona Behera 	{0x1CA42, 0x0100},
293989282175SSantwona Behera 	{0x1C20D, 0x0002},
294089282175SSantwona Behera 	{NLP_INI_WAIT, 100},
294189282175SSantwona Behera 
294289282175SSantwona Behera 	{0x1ff28, 0x4001},
294389282175SSantwona Behera 	{0x1ff2A, 0x004A},
294489282175SSantwona Behera 	{NLP_INI_WAIT, 500},
294589282175SSantwona Behera 
294689282175SSantwona Behera 	{0x1d000, 0x5200},
294789282175SSantwona Behera 	{NLP_INI_WAIT, 500},
294889282175SSantwona Behera 
294989282175SSantwona Behera 	{0x1d800, 0x4009},
295089282175SSantwona Behera 	{0x1d801, 0x2fff},
295189282175SSantwona Behera 	{0x1d802, 0x300f},
295289282175SSantwona Behera 	{0x1d803, 0x40aa},
295389282175SSantwona Behera 	{0x1d804, 0x401c},
295489282175SSantwona Behera 	{0x1d805, 0x401e},
295589282175SSantwona Behera 	{0x1d806, 0x20c5},
295689282175SSantwona Behera 	{0x1d807, 0x3c05},
295789282175SSantwona Behera 	{0x1d808, 0x6536},
295889282175SSantwona Behera 	{0x1d809, 0x2fe4},
295989282175SSantwona Behera 	{0x1d80a, 0x3dc4},
296089282175SSantwona Behera 	{0x1d80b, 0x6624},
296189282175SSantwona Behera 	{0x1d80c, 0x2ff4},
296289282175SSantwona Behera 	{0x1d80d, 0x3dc4},
296389282175SSantwona Behera 	{0x1d80e, 0x2035},
296489282175SSantwona Behera 	{0x1d80f, 0x30a5},
296589282175SSantwona Behera 	{0x1d810, 0x6524},
296689282175SSantwona Behera 	{0x1d811, 0x2ca2},
296789282175SSantwona Behera 	{0x1d812, 0x3012},
296889282175SSantwona Behera 	{0x1d813, 0x1002},
296989282175SSantwona Behera 	{0x1d814, 0x2882},
297089282175SSantwona Behera 	{0x1d815, 0x3022},
297189282175SSantwona Behera 	{0x1d816, 0x1002},
297289282175SSantwona Behera 	{0x1d817, 0x2972},
297389282175SSantwona Behera 	{0x1d818, 0x3022},
297489282175SSantwona Behera 	{0x1d819, 0x1002},
297589282175SSantwona Behera 	{0x1d81a, 0x2892},
297689282175SSantwona Behera 	{0x1d81b, 0x3012},
297789282175SSantwona Behera 	{0x1d81c, 0x1002},
297889282175SSantwona Behera 	{0x1d81d, 0x24e2},
297989282175SSantwona Behera 	{0x1d81e, 0x3022},
298089282175SSantwona Behera 	{0x1d81f, 0x1002},
298189282175SSantwona Behera 	{0x1d820, 0x27e2},
298289282175SSantwona Behera 	{0x1d821, 0x3012},
298389282175SSantwona Behera 	{0x1d822, 0x1002},
298489282175SSantwona Behera 	{0x1d823, 0x2422},
298589282175SSantwona Behera 	{0x1d824, 0x3022},
298689282175SSantwona Behera 	{0x1d825, 0x1002},
298789282175SSantwona Behera 	{0x1d826, 0x22cd},
298889282175SSantwona Behera 	{0x1d827, 0x301d},
298989282175SSantwona Behera 	{0x1d828, 0x2992},
299089282175SSantwona Behera 	{0x1d829, 0x3022},
299189282175SSantwona Behera 	{0x1d82a, 0x1002},
299289282175SSantwona Behera 	{0x1d82b, 0x5553},
299389282175SSantwona Behera 	{0x1d82c, 0x0307},
299489282175SSantwona Behera 	{0x1d82d, 0x2572},
299589282175SSantwona Behera 	{0x1d82e, 0x3022},
299689282175SSantwona Behera 	{0x1d82f, 0x1002},
299789282175SSantwona Behera 	{0x1d830, 0x21a2},
299889282175SSantwona Behera 	{0x1d831, 0x3012},
299989282175SSantwona Behera 	{0x1d832, 0x1002},
300089282175SSantwona Behera 	{0x1d833, 0x4016},
300189282175SSantwona Behera 	{0x1d834, 0x5e63},
300289282175SSantwona Behera 	{0x1d835, 0x0344},
300389282175SSantwona Behera 	{0x1d836, 0x21a2},
300489282175SSantwona Behera 	{0x1d837, 0x3012},
300589282175SSantwona Behera 	{0x1d838, 0x1002},
300689282175SSantwona Behera 	{0x1d839, 0x400e},
300789282175SSantwona Behera 	{0x1d83a, 0x2572},
300889282175SSantwona Behera 	{0x1d83b, 0x3022},
300989282175SSantwona Behera 	{0x1d83c, 0x1002},
301089282175SSantwona Behera 	{0x1d83d, 0x2b22},
301189282175SSantwona Behera 	{0x1d83e, 0x3012},
301289282175SSantwona Behera 	{0x1d83f, 0x1002},
301389282175SSantwona Behera 	{0x1d840, 0x28e2},
301489282175SSantwona Behera 	{0x1d841, 0x3022},
301589282175SSantwona Behera 	{0x1d842, 0x1002},
301689282175SSantwona Behera 	{0x1d843, 0x2782},
301789282175SSantwona Behera 	{0x1d844, 0x3022},
301889282175SSantwona Behera 	{0x1d845, 0x1002},
301989282175SSantwona Behera 	{0x1d846, 0x2fa4},
302089282175SSantwona Behera 	{0x1d847, 0x3dc4},
302189282175SSantwona Behera 	{0x1d848, 0x6624},
302289282175SSantwona Behera 	{0x1d849, 0x2e8b},
302389282175SSantwona Behera 	{0x1d84a, 0x303b},
302489282175SSantwona Behera 	{0x1d84b, 0x56b3},
302589282175SSantwona Behera 	{0x1d84c, 0x03c6},
302689282175SSantwona Behera 	{0x1d84d, 0x866b},
302789282175SSantwona Behera 	{0x1d84e, 0x400c},
302889282175SSantwona Behera 	{0x1d84f, 0x2782},
302989282175SSantwona Behera 	{0x1d850, 0x3012},
303089282175SSantwona Behera 	{0x1d851, 0x1002},
303189282175SSantwona Behera 	{0x1d852, 0x2c4b},
303289282175SSantwona Behera 	{0x1d853, 0x309b},
303389282175SSantwona Behera 	{0x1d854, 0x56b3},
303489282175SSantwona Behera 	{0x1d855, 0x03c3},
303589282175SSantwona Behera 	{0x1d856, 0x866b},
303689282175SSantwona Behera 	{0x1d857, 0x400c},
303789282175SSantwona Behera 	{0x1d858, 0x22a2},
303889282175SSantwona Behera 	{0x1d859, 0x3022},
303989282175SSantwona Behera 	{0x1d85a, 0x1002},
304089282175SSantwona Behera 	{0x1d85b, 0x28e2},
304189282175SSantwona Behera 	{0x1d85c, 0x3022},
304289282175SSantwona Behera 	{0x1d85d, 0x1002},
304389282175SSantwona Behera 	{0x1d85e, 0x2782},
304489282175SSantwona Behera 	{0x1d85f, 0x3022},
304589282175SSantwona Behera 	{0x1d860, 0x1002},
304689282175SSantwona Behera 	{0x1d861, 0x2fb4},
304789282175SSantwona Behera 	{0x1d862, 0x3dc4},
304889282175SSantwona Behera 	{0x1d863, 0x6624},
304989282175SSantwona Behera 	{0x1d864, 0x56b3},
305089282175SSantwona Behera 	{0x1d865, 0x03c3},
305189282175SSantwona Behera 	{0x1d866, 0x866b},
305289282175SSantwona Behera 	{0x1d867, 0x401c},
305389282175SSantwona Behera 	{0x1d868, 0x2c45},
305489282175SSantwona Behera 	{0x1d869, 0x3095},
305589282175SSantwona Behera 	{0x1d86a, 0x5b53},
305689282175SSantwona Behera 	{0x1d86b, 0x23d2},
305789282175SSantwona Behera 	{0x1d86c, 0x3012},
305889282175SSantwona Behera 	{0x1d86d, 0x13c2},
305989282175SSantwona Behera 	{0x1d86e, 0x5cc3},
306089282175SSantwona Behera 	{0x1d86f, 0x2782},
306189282175SSantwona Behera 	{0x1d870, 0x3012},
306289282175SSantwona Behera 	{0x1d871, 0x1312},
306389282175SSantwona Behera 	{0x1d872, 0x2b22},
306489282175SSantwona Behera 	{0x1d873, 0x3012},
306589282175SSantwona Behera 	{0x1d874, 0x1002},
306689282175SSantwona Behera 	{0x1d875, 0x28e2},
306789282175SSantwona Behera 	{0x1d876, 0x3022},
306889282175SSantwona Behera 	{0x1d877, 0x1002},
306989282175SSantwona Behera 	{0x1d878, 0x2672},
307089282175SSantwona Behera 	{0x1d879, 0x3022},
307189282175SSantwona Behera 	{0x1d87a, 0x1002},
307289282175SSantwona Behera 	{0x1d87b, 0x21a2},
307389282175SSantwona Behera 	{0x1d87c, 0x3012},
307489282175SSantwona Behera 	{0x1d87d, 0x1002},
307589282175SSantwona Behera 	{0x1d87e, 0x628f},
307689282175SSantwona Behera 	{0x1d87f, 0x2985},
307789282175SSantwona Behera 	{0x1d880, 0x33a5},
307889282175SSantwona Behera 	{0x1d881, 0x2782},
307989282175SSantwona Behera 	{0x1d882, 0x3022},
308089282175SSantwona Behera 	{0x1d883, 0x1002},
308189282175SSantwona Behera 	{0x1d884, 0x5653},
308289282175SSantwona Behera 	{0x1d885, 0x03d2},
308389282175SSantwona Behera 	{0x1d886, 0x401e},
308489282175SSantwona Behera 	{0x1d887, 0x6f72},
308589282175SSantwona Behera 	{0x1d888, 0x1002},
308689282175SSantwona Behera 	{0x1d889, 0x628f},
308789282175SSantwona Behera 	{0x1d88a, 0x2304},
308889282175SSantwona Behera 	{0x1d88b, 0x3c84},
308989282175SSantwona Behera 	{0x1d88c, 0x6436},
309089282175SSantwona Behera 	{0x1d88d, 0xdff4},
309189282175SSantwona Behera 	{0x1d88e, 0x6436},
309289282175SSantwona Behera 	{0x1d88f, 0x2ff5},
309389282175SSantwona Behera 	{0x1d890, 0x3005},
309489282175SSantwona Behera 	{0x1d891, 0x8656},
309589282175SSantwona Behera 	{0x1d892, 0xdfba},
309689282175SSantwona Behera 	{0x1d893, 0x56a3},
309789282175SSantwona Behera 	{0x1d894, 0xd05a},
309889282175SSantwona Behera 	{0x1d895, 0x29e2},
309989282175SSantwona Behera 	{0x1d896, 0x3012},
310089282175SSantwona Behera 	{0x1d897, 0x1392},
310189282175SSantwona Behera 	{0x1d898, 0xd05a},
310289282175SSantwona Behera 	{0x1d899, 0x56a3},
310389282175SSantwona Behera 	{0x1d89a, 0xdfba},
310489282175SSantwona Behera 	{0x1d89b, 0x0383},
310589282175SSantwona Behera 	{0x1d89c, 0x6f72},
310689282175SSantwona Behera 	{0x1d89d, 0x1002},
310789282175SSantwona Behera 	{0x1d89e, 0x2a64},
310889282175SSantwona Behera 	{0x1d89f, 0x3014},
310989282175SSantwona Behera 	{0x1d8a0, 0x2005},
311089282175SSantwona Behera 	{0x1d8a1, 0x3d75},
311189282175SSantwona Behera 	{0x1d8a2, 0xc451},
311289282175SSantwona Behera 	{0x1d8a3, 0x2a42},
311389282175SSantwona Behera 	{0x1d8a4, 0x3022},
311489282175SSantwona Behera 	{0x1d8a5, 0x1002},
311589282175SSantwona Behera 	{0x1d8a6, 0x178c},
311689282175SSantwona Behera 	{0x1d8a7, 0x1898},
311789282175SSantwona Behera 	{0x1d8a8, 0x19a4},
311889282175SSantwona Behera 	{0x1d8a9, 0x1ab0},
311989282175SSantwona Behera 	{0x1d8aa, 0x1bbc},
312089282175SSantwona Behera 	{0x1d8ab, 0x1cc8},
312189282175SSantwona Behera 	{0x1d8ac, 0x1dd3},
312289282175SSantwona Behera 	{0x1d8ad, 0x1ede},
312389282175SSantwona Behera 	{0x1d8ae, 0x1fe9},
312489282175SSantwona Behera 	{0x1d8af, 0x20f4},
312589282175SSantwona Behera 	{0x1d8b0, 0x21ff},
312689282175SSantwona Behera 	{0x1d8b1, 0x0000},
312789282175SSantwona Behera 	{0x1d8b2, 0x27e1},
312889282175SSantwona Behera 	{0x1d8b3, 0x3021},
312989282175SSantwona Behera 	{0x1d8b4, 0x1001},
313089282175SSantwona Behera 	{0x1d8b5, 0xc620},
313189282175SSantwona Behera 	{0x1d8b6, 0x0000},
313289282175SSantwona Behera 	{0x1d8b7, 0xc621},
313389282175SSantwona Behera 	{0x1d8b8, 0x0000},
313489282175SSantwona Behera 	{0x1d8b9, 0xc622},
313589282175SSantwona Behera 	{0x1d8ba, 0x00e2},
313689282175SSantwona Behera 	{0x1d8bb, 0xc623},
313789282175SSantwona Behera 	{0x1d8bc, 0x007f},
313889282175SSantwona Behera 	{0x1d8bd, 0xc624},
313989282175SSantwona Behera 	{0x1d8be, 0x00ce},
314089282175SSantwona Behera 	{0x1d8bf, 0xc625},
314189282175SSantwona Behera 	{0x1d8c0, 0x0000},
314289282175SSantwona Behera 	{0x1d8c1, 0xc627},
314389282175SSantwona Behera 	{0x1d8c2, 0x0000},
314489282175SSantwona Behera 	{0x1d8c3, 0xc628},
314589282175SSantwona Behera 	{0x1d8c4, 0x0000},
314689282175SSantwona Behera 	{0x1d8c5, 0xc90a},
314789282175SSantwona Behera 	{0x1d8c6, 0x3a7c},
314889282175SSantwona Behera 	{0x1d8c7, 0xc62c},
314989282175SSantwona Behera 	{0x1d8c8, 0x0000},
315089282175SSantwona Behera 	{0x1d8c9, 0x0000},
315189282175SSantwona Behera 	{0x1d8ca, 0x27e1},
315289282175SSantwona Behera 	{0x1d8cb, 0x3021},
315389282175SSantwona Behera 	{0x1d8cc, 0x1001},
315489282175SSantwona Behera 	{0x1d8cd, 0xc502},
315589282175SSantwona Behera 	{0x1d8ce, 0x53ac},
315689282175SSantwona Behera 	{0x1d8cf, 0xc503},
315789282175SSantwona Behera 	{0x1d8d0, 0x2cd3},
315889282175SSantwona Behera 	{0x1d8d1, 0xc600},
315989282175SSantwona Behera 	{0x1d8d2, 0x2a6e},
316089282175SSantwona Behera 	{0x1d8d3, 0xc601},
316189282175SSantwona Behera 	{0x1d8d4, 0x2a2c},
316289282175SSantwona Behera 	{0x1d8d5, 0xc605},
316389282175SSantwona Behera 	{0x1d8d6, 0x5557},
316489282175SSantwona Behera 	{0x1d8d7, 0xc60c},
316589282175SSantwona Behera 	{0x1d8d8, 0x5400},
316689282175SSantwona Behera 	{0x1d8d9, 0xc710},
316789282175SSantwona Behera 	{0x1d8da, 0x0700},
316889282175SSantwona Behera 	{0x1d8db, 0xc711},
316989282175SSantwona Behera 	{0x1d8dc, 0x0f06},
317089282175SSantwona Behera 	{0x1d8dd, 0xc718},
317189282175SSantwona Behera 	{0x1d8de, 0x0700},
317289282175SSantwona Behera 	{0x1d8df, 0xc719},
317389282175SSantwona Behera 	{0x1d8e0, 0x0f06},
317489282175SSantwona Behera 	{0x1d8e1, 0xc720},
317589282175SSantwona Behera 	{0x1d8e2, 0x4700},
317689282175SSantwona Behera 	{0x1d8e3, 0xc721},
317789282175SSantwona Behera 	{0x1d8e4, 0x0f06},
317889282175SSantwona Behera 	{0x1d8e5, 0xc728},
317989282175SSantwona Behera 	{0x1d8e6, 0x0700},
318089282175SSantwona Behera 	{0x1d8e7, 0xc729},
318189282175SSantwona Behera 	{0x1d8e8, 0x1207},
318289282175SSantwona Behera 	{0x1d8e9, 0xc801},
318389282175SSantwona Behera 	{0x1d8ea, 0x7f50},
318489282175SSantwona Behera 	{0x1d8eb, 0xc802},
318589282175SSantwona Behera 	{0x1d8ec, 0x7760},
318689282175SSantwona Behera 	{0x1d8ed, 0xc803},
318789282175SSantwona Behera 	{0x1d8ee, 0x7fce},
318889282175SSantwona Behera 	{0x1d8ef, 0xc804},
318989282175SSantwona Behera 	{0x1d8f0, 0x520e},
319089282175SSantwona Behera 	{0x1d8f1, 0xc805},
319189282175SSantwona Behera 	{0x1d8f2, 0x5c11},
319289282175SSantwona Behera 	{0x1d8f3, 0xc806},
319389282175SSantwona Behera 	{0x1d8f4, 0x3c51},
319489282175SSantwona Behera 	{0x1d8f5, 0xc807},
319589282175SSantwona Behera 	{0x1d8f6, 0x4061},
319689282175SSantwona Behera 	{0x1d8f7, 0xc808},
319789282175SSantwona Behera 	{0x1d8f8, 0x49c1},
319889282175SSantwona Behera 	{0x1d8f9, 0xc809},
319989282175SSantwona Behera 	{0x1d8fa, 0x3840},
320089282175SSantwona Behera 	{0x1d8fb, 0xc80a},
320189282175SSantwona Behera 	{0x1d8fc, 0x0000},
320289282175SSantwona Behera 	{0x1d8fd, 0xc821},
320389282175SSantwona Behera 	{0x1d8fe, 0x0002},
320489282175SSantwona Behera 	{0x1d8ff, 0xc822},
320589282175SSantwona Behera 	{0x1d900, 0x0046},
320689282175SSantwona Behera 	{0x1d901, 0xc844},
320789282175SSantwona Behera 	{0x1d902, 0x182f},
320889282175SSantwona Behera 	{0x1d903, 0xc849},
320989282175SSantwona Behera 	{0x1d904, 0x0400},
321089282175SSantwona Behera 	{0x1d905, 0xc84a},
321189282175SSantwona Behera 	{0x1d906, 0x0002},
321289282175SSantwona Behera 	{0x1d907, 0xc013},
321389282175SSantwona Behera 	{0x1d908, 0xf341},
321489282175SSantwona Behera 	{0x1d909, 0xc084},
321589282175SSantwona Behera 	{0x1d90a, 0x0030},
321689282175SSantwona Behera 	{0x1d90b, 0xc904},
321789282175SSantwona Behera 	{0x1d90c, 0x1401},
321889282175SSantwona Behera 	{0x1d90d, 0xcb0c},
321989282175SSantwona Behera 	{0x1d90e, 0x0004},
322089282175SSantwona Behera 	{0x1d90f, 0xcb0e},
322189282175SSantwona Behera 	{0x1d910, 0xa00a},
322289282175SSantwona Behera 	{0x1d911, 0xcb0f},
322389282175SSantwona Behera 	{0x1d912, 0xc0c0},
322489282175SSantwona Behera 	{0x1d913, 0xcb10},
322589282175SSantwona Behera 	{0x1d914, 0xc0c0},
322689282175SSantwona Behera 	{0x1d915, 0xcb11},
322789282175SSantwona Behera 	{0x1d916, 0x00a0},
322889282175SSantwona Behera 	{0x1d917, 0xcb12},
322989282175SSantwona Behera 	{0x1d918, 0x0007},
323089282175SSantwona Behera 	{0x1d919, 0xc241},
323189282175SSantwona Behera 	{0x1d91a, 0xa000},
323289282175SSantwona Behera 	{0x1d91b, 0xc243},
323389282175SSantwona Behera 	{0x1d91c, 0x7fe0},
323489282175SSantwona Behera 	{0x1d91d, 0xc604},
323589282175SSantwona Behera 	{0x1d91e, 0x000e},
323689282175SSantwona Behera 	{0x1d91f, 0xc609},
323789282175SSantwona Behera 	{0x1d920, 0x00f5},
323889282175SSantwona Behera 	{0x1d921, 0x0c61},
323989282175SSantwona Behera 	{0x1d922, 0x000e},
324089282175SSantwona Behera 	{0x1d923, 0xc660},
324189282175SSantwona Behera 	{0x1d924, 0x9600},
324289282175SSantwona Behera 	{0x1d925, 0xc687},
324389282175SSantwona Behera 	{0x1d926, 0x0004},
324489282175SSantwona Behera 	{0x1d927, 0xc60a},
324589282175SSantwona Behera 	{0x1d928, 0x04f5},
324689282175SSantwona Behera 	{0x1d929, 0x0000},
324789282175SSantwona Behera 	{0x1d92a, 0x27e1},
324889282175SSantwona Behera 	{0x1d92b, 0x3021},
324989282175SSantwona Behera 	{0x1d92c, 0x1001},
325089282175SSantwona Behera 	{0x1d92d, 0xc620},
325189282175SSantwona Behera 	{0x1d92e, 0x14e5},
325289282175SSantwona Behera 	{0x1d92f, 0xc621},
325389282175SSantwona Behera 	{0x1d930, 0xc53d},
325489282175SSantwona Behera 	{0x1d931, 0xc622},
325589282175SSantwona Behera 	{0x1d932, 0x3cbe},
325689282175SSantwona Behera 	{0x1d933, 0xc623},
325789282175SSantwona Behera 	{0x1d934, 0x4452},
325889282175SSantwona Behera 	{0x1d935, 0xc624},
325989282175SSantwona Behera 	{0x1d936, 0xc5c5},
326089282175SSantwona Behera 	{0x1d937, 0xc625},
326189282175SSantwona Behera 	{0x1d938, 0xe01e},
326289282175SSantwona Behera 	{0x1d939, 0xc627},
326389282175SSantwona Behera 	{0x1d93a, 0x0000},
326489282175SSantwona Behera 	{0x1d93b, 0xc628},
326589282175SSantwona Behera 	{0x1d93c, 0x0000},
326689282175SSantwona Behera 	{0x1d93d, 0xc62c},
326789282175SSantwona Behera 	{0x1d93e, 0x0000},
326889282175SSantwona Behera 	{0x1d93f, 0xc90a},
326989282175SSantwona Behera 	{0x1d940, 0x3a7c},
327089282175SSantwona Behera 	{0x1d941, 0x0000},
327189282175SSantwona Behera 	{0x1d942, 0x2b84},
327289282175SSantwona Behera 	{0x1d943, 0x3c74},
327389282175SSantwona Behera 	{0x1d944, 0x6435},
327489282175SSantwona Behera 	{0x1d945, 0xdff4},
327589282175SSantwona Behera 	{0x1d946, 0x6435},
327689282175SSantwona Behera 	{0x1d947, 0x2806},
327789282175SSantwona Behera 	{0x1d948, 0x3006},
327889282175SSantwona Behera 	{0x1d949, 0x8565},
327989282175SSantwona Behera 	{0x1d94a, 0x2b24},
328089282175SSantwona Behera 	{0x1d94b, 0x3c24},
328189282175SSantwona Behera 	{0x1d94c, 0x6436},
328289282175SSantwona Behera 	{0x1d94d, 0x1002},
328389282175SSantwona Behera 	{0x1d94e, 0x2b24},
328489282175SSantwona Behera 	{0x1d94f, 0x3c24},
328589282175SSantwona Behera 	{0x1d950, 0x6436},
328689282175SSantwona Behera 	{0x1d951, 0x4045},
328789282175SSantwona Behera 	{0x1d952, 0x8656},
328889282175SSantwona Behera 	{0x1d953, 0x5663},
328989282175SSantwona Behera 	{0x1d954, 0x0302},
329089282175SSantwona Behera 	{0x1d955, 0x401e},
329189282175SSantwona Behera 	{0x1d956, 0x1002},
329289282175SSantwona Behera 	{0x1d957, 0x2017},
329389282175SSantwona Behera 	{0x1d958, 0x3b17},
329489282175SSantwona Behera 	{0x1d959, 0x2084},
329589282175SSantwona Behera 	{0x1d95a, 0x3c14},
329689282175SSantwona Behera 	{0x1d95b, 0x6724},
329789282175SSantwona Behera 	{0x1d95c, 0x2807},
329889282175SSantwona Behera 	{0x1d95d, 0x31a7},
329989282175SSantwona Behera 	{0x1d95e, 0x20c4},
330089282175SSantwona Behera 	{0x1d95f, 0x3c24},
330189282175SSantwona Behera 	{0x1d960, 0x6724},
330289282175SSantwona Behera 	{0x1d961, 0x2ff7},
330389282175SSantwona Behera 	{0x1d962, 0x30f7},
330489282175SSantwona Behera 	{0x1d963, 0x20c4},
330589282175SSantwona Behera 	{0x1d964, 0x3c04},
330689282175SSantwona Behera 	{0x1d965, 0x6724},
330789282175SSantwona Behera 	{0x1d966, 0x1002},
330889282175SSantwona Behera 	{0x1d967, 0x2807},
330989282175SSantwona Behera 	{0x1d968, 0x3187},
331089282175SSantwona Behera 	{0x1d969, 0x20c4},
331189282175SSantwona Behera 	{0x1d96a, 0x3c24},
331289282175SSantwona Behera 	{0x1d96b, 0x6724},
331389282175SSantwona Behera 	{0x1d96c, 0x2fe4},
331489282175SSantwona Behera 	{0x1d96d, 0x3dc4},
331589282175SSantwona Behera 	{0x1d96e, 0x6437},
331689282175SSantwona Behera 	{0x1d96f, 0x20c4},
331789282175SSantwona Behera 	{0x1d970, 0x3c04},
331889282175SSantwona Behera 	{0x1d971, 0x6724},
331989282175SSantwona Behera 	{0x1d972, 0x2017},
332089282175SSantwona Behera 	{0x1d973, 0x3d17},
332189282175SSantwona Behera 	{0x1d974, 0x2084},
332289282175SSantwona Behera 	{0x1d975, 0x3c14},
332389282175SSantwona Behera 	{0x1d976, 0x6724},
332489282175SSantwona Behera 	{0x1d977, 0x1002},
332589282175SSantwona Behera 	{0x1d978, 0x24f4},
332689282175SSantwona Behera 	{0x1d979, 0x3c64},
332789282175SSantwona Behera 	{0x1d97a, 0x6436},
332889282175SSantwona Behera 	{0x1d97b, 0xdff4},
332989282175SSantwona Behera 	{0x1d97c, 0x6436},
333089282175SSantwona Behera 	{0x1d97d, 0x1002},
333189282175SSantwona Behera 	{0x1d97e, 0x2006},
333289282175SSantwona Behera 	{0x1d97f, 0x3d76},
333389282175SSantwona Behera 	{0x1d980, 0xc161},
333489282175SSantwona Behera 	{0x1d981, 0x6134},
333589282175SSantwona Behera 	{0x1d982, 0x6135},
333689282175SSantwona Behera 	{0x1d983, 0x5443},
333789282175SSantwona Behera 	{0x1d984, 0x0303},
333889282175SSantwona Behera 	{0x1d985, 0x6524},
333989282175SSantwona Behera 	{0x1d986, 0x00fb},
334089282175SSantwona Behera 	{0x1d987, 0x1002},
334189282175SSantwona Behera 	{0x1d988, 0x20d4},
334289282175SSantwona Behera 	{0x1d989, 0x3c24},
334389282175SSantwona Behera 	{0x1d98a, 0x2025},
334489282175SSantwona Behera 	{0x1d98b, 0x3005},
334589282175SSantwona Behera 	{0x1d98c, 0x6524},
334689282175SSantwona Behera 	{0x1d98d, 0x1002},
334789282175SSantwona Behera 	{0x1d98e, 0xd019},
334889282175SSantwona Behera 	{0x1d98f, 0x2104},
334989282175SSantwona Behera 	{0x1d990, 0x3c24},
335089282175SSantwona Behera 	{0x1d991, 0x2105},
335189282175SSantwona Behera 	{0x1d992, 0x3805},
335289282175SSantwona Behera 	{0x1d993, 0x6524},
335389282175SSantwona Behera 	{0x1d994, 0xdff4},
335489282175SSantwona Behera 	{0x1d995, 0x4005},
335589282175SSantwona Behera 	{0x1d996, 0x6524},
335689282175SSantwona Behera 	{0x1d997, 0x2e8d},
335789282175SSantwona Behera 	{0x1d998, 0x303d},
335889282175SSantwona Behera 	{0x1d999, 0x2408},
335989282175SSantwona Behera 	{0x1d99a, 0x35d8},
336089282175SSantwona Behera 	{0x1d99b, 0x5dd3},
336189282175SSantwona Behera 	{0x1d99c, 0x0307},
336289282175SSantwona Behera 	{0x1d99d, 0x8887},
336389282175SSantwona Behera 	{0x1d99e, 0x63a7},
336489282175SSantwona Behera 	{0x1d99f, 0x8887},
336589282175SSantwona Behera 	{0x1d9a0, 0x63a7},
336689282175SSantwona Behera 	{0x1d9a1, 0xdffd},
336789282175SSantwona Behera 	{0x1d9a2, 0x00f9},
336889282175SSantwona Behera 	{0x1d9a3, 0x1002},
336989282175SSantwona Behera 	{0x1d9a4, 0x866a},
337089282175SSantwona Behera 	{0x1d9a5, 0x6138},
337189282175SSantwona Behera 	{0x1d9a6, 0x5883},
337289282175SSantwona Behera 	{0x1d9a7, 0x2b42},
337389282175SSantwona Behera 	{0x1d9a8, 0x3022},
337489282175SSantwona Behera 	{0x1d9a9, 0x1302},
337589282175SSantwona Behera 	{0x1d9aa, 0x2ff7},
337689282175SSantwona Behera 	{0x1d9ab, 0x3007},
337789282175SSantwona Behera 	{0x1d9ac, 0x8785},
337889282175SSantwona Behera 	{0x1d9ad, 0xb887},
337989282175SSantwona Behera 	{0x1d9ae, 0x8786},
338089282175SSantwona Behera 	{0x1d9af, 0xb8c6},
338189282175SSantwona Behera 	{0x1d9b0, 0x5a53},
338289282175SSantwona Behera 	{0x1d9b1, 0x2a52},
338389282175SSantwona Behera 	{0x1d9b2, 0x3022},
338489282175SSantwona Behera 	{0x1d9b3, 0x13c2},
338589282175SSantwona Behera 	{0x1d9b4, 0x2474},
338689282175SSantwona Behera 	{0x1d9b5, 0x3c84},
338789282175SSantwona Behera 	{0x1d9b6, 0x64d7},
338889282175SSantwona Behera 	{0x1d9b7, 0x64d7},
338989282175SSantwona Behera 	{0x1d9b8, 0x2ff5},
339089282175SSantwona Behera 	{0x1d9b9, 0x3c05},
339189282175SSantwona Behera 	{0x1d9ba, 0x8757},
339289282175SSantwona Behera 	{0x1d9bb, 0xb886},
339389282175SSantwona Behera 	{0x1d9bc, 0x9767},
339489282175SSantwona Behera 	{0x1d9bd, 0x67c4},
339589282175SSantwona Behera 	{0x1d9be, 0x6f72},
339689282175SSantwona Behera 	{0x1d9bf, 0x1002},
339789282175SSantwona Behera 	{0x1d9c0, 0x0000},
339889282175SSantwona Behera 	{0x1d080, 0x0100},
339989282175SSantwona Behera 	{0x1d092, 0x0000},
340089282175SSantwona Behera 	{NLP_INI_STOP, 0},
340189282175SSantwona Behera };
340289282175SSantwona Behera 
340389282175SSantwona Behera static nxge_status_t
340489282175SSantwona Behera nxge_nlp2020_xcvr_init(p_nxge_t nxgep)
340589282175SSantwona Behera {
340689282175SSantwona Behera 	uint8_t			phy_port_addr;
340789282175SSantwona Behera 	nxge_status_t		status = NXGE_OK;
340889282175SSantwona Behera 	uint16_t		ctrl_reg, rst_val, pmd_ctl, rx_los;
340989282175SSantwona Behera 	int			i = 0, count = 1000;
341089282175SSantwona Behera 
341189282175SSantwona Behera 	uint8_t			connector = 0, len, lpm;
341289282175SSantwona Behera 	p_nxge_nlp_initseq_t	initseq;
341389282175SSantwona Behera 	uint16_t		dev, reg, val;
341489282175SSantwona Behera 
341589282175SSantwona Behera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: "
341689282175SSantwona Behera 	    "port<%d>, phyaddr[0x%x]", nxgep->mac.portnum,
341789282175SSantwona Behera 	    nxgep->statsp->mac_stats.xcvr_portn));
341889282175SSantwona Behera 
341989282175SSantwona Behera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
342089282175SSantwona Behera 
342189282175SSantwona Behera 	/* Reset the transceiver */
342289282175SSantwona Behera 	rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST;
342389282175SSantwona Behera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
342489282175SSantwona Behera 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val))
342589282175SSantwona Behera 	    != NXGE_OK)
342689282175SSantwona Behera 		goto fail;
342789282175SSantwona Behera 	while ((count--) && (ctrl_reg & rst_val)) {
342889282175SSantwona Behera 		drv_usecwait(1000);
342989282175SSantwona Behera 		(void) nxge_mdio_read(nxgep, phy_port_addr,
343089282175SSantwona Behera 		    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg);
343189282175SSantwona Behera 	}
343289282175SSantwona Behera 	if (count == 0) {
343389282175SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: "
343489282175SSantwona Behera 		    "PMA_PMD reset failed"));
343589282175SSantwona Behera 		goto fail;
343689282175SSantwona Behera 	}
343789282175SSantwona Behera 
343889282175SSantwona Behera 	/* Set loopback mode if required */
343989282175SSantwona Behera 	/* Set PMA PMD system loopback */
344089282175SSantwona Behera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
344189282175SSantwona Behera 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl))
344289282175SSantwona Behera 	    != NXGE_OK)
344389282175SSantwona Behera 		goto fail;
344489282175SSantwona Behera 
344589282175SSantwona Behera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
344689282175SSantwona Behera 		pmd_ctl |= 0x0001;
344789282175SSantwona Behera 	else
344889282175SSantwona Behera 		pmd_ctl &= 0xfffe;
344989282175SSantwona Behera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
345089282175SSantwona Behera 	    NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl))
345189282175SSantwona Behera 	    != NXGE_OK)
345289282175SSantwona Behera 		goto fail;
345389282175SSantwona Behera 
345489282175SSantwona Behera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: "
345589282175SSantwona Behera 	    "setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl));
345689282175SSantwona Behera 
345789282175SSantwona Behera 	/* Check connector details using I2c */
345889282175SSantwona Behera 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
345989282175SSantwona Behera 	    QSFP_MSA_CONN_REG, &connector) == 1) {
346089282175SSantwona Behera 		goto fail;
346189282175SSantwona Behera 	}
346289282175SSantwona Behera 
346389282175SSantwona Behera 	switch (connector) {
346489282175SSantwona Behera 	case SFPP_FIBER:
346589282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
346689282175SSantwona Behera 		    "nxge_nlp2020_xcvr_init: SFPP_FIBER detected"));
346789282175SSantwona Behera 		initseq = nlp2020_revC_fiber_init;
346889282175SSantwona Behera 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
346989282175SSantwona Behera 		break;
347089282175SSantwona Behera 	case QSFP_FIBER:
347189282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
347289282175SSantwona Behera 		    "nxge_nlp2020_xcvr_init: QSFP_FIBER detected"));
347389282175SSantwona Behera 		initseq = nlp2020_revC_fiber_init;
347489282175SSantwona Behera 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
347589282175SSantwona Behera 		break;
347689282175SSantwona Behera 	case QSFP_COPPER_TWINAX:
347789282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
347889282175SSantwona Behera 		    "nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/"
347989282175SSantwona Behera 		    "SFPP_COPPER_TWINAX detected"));
348089282175SSantwona Behera 
348189282175SSantwona Behera 		initseq = nlp2020_revC_copper_init;
348289282175SSantwona Behera 		nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M;
348389282175SSantwona Behera 		break;
348489282175SSantwona Behera 	default:
348589282175SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
348689282175SSantwona Behera 		    "nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected",
348789282175SSantwona Behera 		    "...setting to QSFP_FIBER",
348889282175SSantwona Behera 		    connector));
348989282175SSantwona Behera 		initseq = nlp2020_revC_fiber_init;
349089282175SSantwona Behera 		nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
349189282175SSantwona Behera 		break;
349289282175SSantwona Behera 	}
349389282175SSantwona Behera 
349489282175SSantwona Behera 	/* Run appropriate init sequence */
349589282175SSantwona Behera 	for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) {
349689282175SSantwona Behera 		dev = initseq[i].dev_reg >> 16;
349789282175SSantwona Behera 		reg = initseq[i].dev_reg & 0xffff;
349889282175SSantwona Behera 		val = initseq[i].val;
349989282175SSantwona Behera 
350089282175SSantwona Behera 		if (reg == NLP_INI_WAIT) {
350189282175SSantwona Behera 			drv_usecwait(1000 * val);
350289282175SSantwona Behera 		} else {
350389282175SSantwona Behera 			if ((status = nxge_mdio_write(nxgep, phy_port_addr,
350489282175SSantwona Behera 			    dev, reg, val)) != NXGE_OK)
350589282175SSantwona Behera 				goto fail;
350689282175SSantwona Behera 		}
350789282175SSantwona Behera 	}
350889282175SSantwona Behera 
350989282175SSantwona Behera 	/* rx_los inversion */
351089282175SSantwona Behera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
351189282175SSantwona Behera 	    NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK)
351289282175SSantwona Behera 			goto fail;
351389282175SSantwona Behera 
351489282175SSantwona Behera 	rx_los &= ~(NLP2020_RXLOS_ACT_H);
351589282175SSantwona Behera 
351689282175SSantwona Behera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
351789282175SSantwona Behera 	    NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK)
351889282175SSantwona Behera 			goto fail;
351989282175SSantwona Behera 
352089282175SSantwona Behera 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
352189282175SSantwona Behera 	    QSFP_MSA_LEN_REG, &len) == 1) {
352289282175SSantwona Behera 		goto fail;
352389282175SSantwona Behera 	}
352489282175SSantwona Behera 
352589282175SSantwona Behera 	if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
352689282175SSantwona Behera 	    QSFP_MSA_LPM_REG, &lpm) == 1) {
352789282175SSantwona Behera 		goto fail;
352889282175SSantwona Behera 	}
352989282175SSantwona Behera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
353089282175SSantwona Behera 	    "nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm));
353189282175SSantwona Behera 
353289282175SSantwona Behera 	if (connector == QSFP_COPPER_TWINAX) {
353389282175SSantwona Behera 		if (len >= 7) {
353489282175SSantwona Behera 			nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE;
353589282175SSantwona Behera 			/* enable pre-emphasis */
353689282175SSantwona Behera 			(void) nxge_mdio_write(nxgep, phy_port_addr,
353789282175SSantwona Behera 			    NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG,
353889282175SSantwona Behera 			    NLP2020_TX_DRV_CTL1_PREEMP_EN);
353989282175SSantwona Behera 			/* write emphasis value */
354089282175SSantwona Behera 			(void) nxge_mdio_write(nxgep, phy_port_addr,
354189282175SSantwona Behera 			    NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG,
354289282175SSantwona Behera 			    NLP2020_TX_DRV_CTL2_EMP_VAL);
354389282175SSantwona Behera 			/* stop microcontroller */
354489282175SSantwona Behera 			(void) nxge_mdio_write(nxgep, phy_port_addr,
354589282175SSantwona Behera 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
354689282175SSantwona Behera 			    NLP2020_UC_CTL_STOP);
354789282175SSantwona Behera 			/* reset program counter */
354889282175SSantwona Behera 			(void) nxge_mdio_write(nxgep, phy_port_addr,
354989282175SSantwona Behera 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG,
355089282175SSantwona Behera 			    NLP2020_UC_PC_START_VAL);
355189282175SSantwona Behera 			/* start microcontroller */
355289282175SSantwona Behera 			(void) nxge_mdio_write(nxgep, phy_port_addr,
355389282175SSantwona Behera 			    NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
355489282175SSantwona Behera 			    NLP2020_UC_CTL_START);
355589282175SSantwona Behera 		}
355689282175SSantwona Behera 	}
355789282175SSantwona Behera 	if (lpm & QSFP_MSA_LPM_HIGH) {
355889282175SSantwona Behera 		/* enable high power mode */
355989282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy_port_addr,
356089282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
356189282175SSantwona Behera 		    NLP2020_GPIO_ACT);
356289282175SSantwona Behera 	} else {
356389282175SSantwona Behera 		/* revert to low power mode */
356489282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy_port_addr,
356589282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
356689282175SSantwona Behera 		    NLP2020_GPIO_INACT);
356789282175SSantwona Behera 	}
3568*9d587972SSantwona Behera 
3569*9d587972SSantwona Behera 	/*
3570*9d587972SSantwona Behera 	 * Set XAUI link tunables from OBP if present.
3571*9d587972SSantwona Behera 	 */
3572*9d587972SSantwona Behera 	NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
3573*9d587972SSantwona Behera 	if (status != NXGE_OK) {
3574*9d587972SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3575*9d587972SSantwona Behera 		    "nxge_nlp2020_xcvr_init: Failed setting PHY tunables"));
3576*9d587972SSantwona Behera 		goto fail;
3577*9d587972SSantwona Behera 	}
3578*9d587972SSantwona Behera 
357989282175SSantwona Behera 	/* It takes ~2s for EDC to settle */
358089282175SSantwona Behera 	drv_usecwait(2000000);
358189282175SSantwona Behera 
358289282175SSantwona Behera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: "
358389282175SSantwona Behera 	    "port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr));
358489282175SSantwona Behera 
358589282175SSantwona Behera 	return (NXGE_OK);
358689282175SSantwona Behera 
358789282175SSantwona Behera fail:
358889282175SSantwona Behera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
358989282175SSantwona Behera 	    "nxge_nlp2020_xcvr_init: failed to initialize transceiver for "
359089282175SSantwona Behera 	    "port<%d>", nxgep->mac.portnum));
359189282175SSantwona Behera 	return (status);
359289282175SSantwona Behera }
359389282175SSantwona Behera 
359489282175SSantwona Behera static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep)
359589282175SSantwona Behera {
359689282175SSantwona Behera 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
359789282175SSantwona Behera 	uint32_t	pcs_id = 0;
359889282175SSantwona Behera 	uint32_t	pma_pmd_id = 0;
359989282175SSantwona Behera 	uint8_t		xcvr_addr =  nxgep->nxge_hw_p->xcvr_addr[portn];
360089282175SSantwona Behera 
360189282175SSantwona Behera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr);
360289282175SSantwona Behera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr);
360389282175SSantwona Behera 
360489282175SSantwona Behera 	if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) ||
360589282175SSantwona Behera 	    ((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) {
360689282175SSantwona Behera 		return (B_TRUE);
360789282175SSantwona Behera 	} else {
360889282175SSantwona Behera 		return (B_FALSE);
360989282175SSantwona Behera 	}
361089282175SSantwona Behera }
361189282175SSantwona Behera 
361289282175SSantwona Behera static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep)
361389282175SSantwona Behera {
361489282175SSantwona Behera 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
361589282175SSantwona Behera 	uint8_t xcvr_addr =  nxgep->nxge_hw_p->xcvr_addr[portn];
361689282175SSantwona Behera 	uint8_t	connector = 0;
361789282175SSantwona Behera 
361889282175SSantwona Behera 	(void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR,
361989282175SSantwona Behera 	    QSFP_MSA_CONN_REG, &connector);
362089282175SSantwona Behera 
362189282175SSantwona Behera 	return (connector);
362289282175SSantwona Behera }
362389282175SSantwona Behera 
362489282175SSantwona Behera static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep)
362589282175SSantwona Behera {
362689282175SSantwona Behera 	uint8_t connector = 0;
362789282175SSantwona Behera 
362889282175SSantwona Behera 	connector = nxge_get_nlp2020_connector_type(nxgep);
362989282175SSantwona Behera 
363089282175SSantwona Behera 	switch (connector) {
363189282175SSantwona Behera 	case SFPP_FIBER:
363289282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
363389282175SSantwona Behera 		    "nxge_set_nlp2020_param: SFPP_FIBER detected"));
363489282175SSantwona Behera 		nxgep->mac.portmode = PORT_10G_FIBER;
363589282175SSantwona Behera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
363689282175SSantwona Behera 		break;
363789282175SSantwona Behera 	case QSFP_FIBER:
363889282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
363989282175SSantwona Behera 		    "nxge_set_nlp2020_param: QSFP_FIBER detected"));
364089282175SSantwona Behera 		nxgep->mac.portmode = PORT_10G_FIBER;
364189282175SSantwona Behera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
364289282175SSantwona Behera 		break;
364389282175SSantwona Behera 	case QSFP_COPPER_TWINAX:
364489282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
364589282175SSantwona Behera 		    "nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/"
364689282175SSantwona Behera 		    "SFPP_COPPER_TWINAX detected"));
364789282175SSantwona Behera 		nxgep->mac.portmode = PORT_10G_COPPER;
364889282175SSantwona Behera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
364989282175SSantwona Behera 		break;
365089282175SSantwona Behera 	default:
365189282175SSantwona Behera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
365289282175SSantwona Behera 		    "nxge_set_nlp2020_param: Unknown type [0x%x] detected"
365389282175SSantwona Behera 		    "...setting to QSFP_FIBER",
365489282175SSantwona Behera 		    connector));
365589282175SSantwona Behera 		nxgep->mac.portmode = PORT_10G_FIBER;
365689282175SSantwona Behera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
365789282175SSantwona Behera 		break;
365889282175SSantwona Behera 	}
365989282175SSantwona Behera 
366089282175SSantwona Behera 	return (NXGE_OK);
366189282175SSantwona Behera }
366289282175SSantwona Behera 
366352cdd236Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
366452cdd236Ssbehera 
366552cdd236Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
366652cdd236Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
366752cdd236Ssbehera 
366852cdd236Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
366952cdd236Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
367052cdd236Ssbehera 
367152cdd236Ssbehera 
367252cdd236Ssbehera static void
367352cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
367452cdd236Ssbehera {
367552cdd236Ssbehera 	uint16_t	value;
367652cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
367752cdd236Ssbehera 
367852cdd236Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
367952cdd236Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
368052cdd236Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
368152cdd236Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
368252cdd236Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
368352cdd236Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
368452cdd236Ssbehera 		    value);
368552cdd236Ssbehera 	}
368652cdd236Ssbehera }
368752cdd236Ssbehera 
368852cdd236Ssbehera static nxge_status_t
368952cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
369052cdd236Ssbehera {
369152cdd236Ssbehera 	nxge_status_t	status;
369252cdd236Ssbehera 	pcs_control_t	pcs_ctl;
369352cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
369452cdd236Ssbehera 
369552cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
369652cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
369752cdd236Ssbehera 
369852cdd236Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
369952cdd236Ssbehera 		pcs_ctl.bits.loopback = 1;
370052cdd236Ssbehera 	else
370152cdd236Ssbehera 		pcs_ctl.bits.loopback = 0;
370252cdd236Ssbehera 
370352cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
370452cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
370552cdd236Ssbehera 
370652cdd236Ssbehera fail:
370752cdd236Ssbehera 	return (status);
370852cdd236Ssbehera }
370952cdd236Ssbehera 
371052cdd236Ssbehera 
371152cdd236Ssbehera static void
371252cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
371352cdd236Ssbehera {
371452cdd236Ssbehera 	uint16_t	val2;
371552cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
371652cdd236Ssbehera 
371752cdd236Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
371852cdd236Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
371952cdd236Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
372052cdd236Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
372152cdd236Ssbehera 
372252cdd236Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
372352cdd236Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
372452cdd236Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
372552cdd236Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
372652cdd236Ssbehera 	}
372752cdd236Ssbehera }
372852cdd236Ssbehera 
372952cdd236Ssbehera 
373052cdd236Ssbehera static nxge_status_t
373152cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
373252cdd236Ssbehera {
373352cdd236Ssbehera 	uint8_t		phy;
373452cdd236Ssbehera 	nxge_status_t	status;
373552cdd236Ssbehera 	uint16_t	clk;
373652cdd236Ssbehera 
373752cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
373852cdd236Ssbehera 
373952cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
374052cdd236Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
374152cdd236Ssbehera 	    nxgep->mac.portnum, phy));
374252cdd236Ssbehera 
374352cdd236Ssbehera 	/* Set LED functions	*/
374452cdd236Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
374552cdd236Ssbehera 	/* PCS activity */
374652cdd236Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
374752cdd236Ssbehera 
374852cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
374952cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
375052cdd236Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
375152cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
375252cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
375352cdd236Ssbehera 
375452cdd236Ssbehera 	/* Set internal loopback mode if necessary */
375552cdd236Ssbehera 
375652cdd236Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
375752cdd236Ssbehera 
375852cdd236Ssbehera 	/* Enable PMD */
375952cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
376052cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
376152cdd236Ssbehera 
376252cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
376352cdd236Ssbehera 
376452cdd236Ssbehera fail:
376552cdd236Ssbehera 	return (status);
376652cdd236Ssbehera }
376752cdd236Ssbehera 
376852cdd236Ssbehera 
376952cdd236Ssbehera 
37702d17280bSsbehera /* Initialize the 10G Transceiver */
37712d17280bSsbehera 
37722d17280bSsbehera static nxge_status_t
37732d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
37742d17280bSsbehera {
37752d17280bSsbehera 	p_nxge_stats_t		statsp;
37761bd6825cSml29623 	p_nxge_param_t		param_arr = nxgep->param_arr;
37772d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
37782d17280bSsbehera #ifdef	NXGE_DEBUG
37792d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
37802d17280bSsbehera #endif
37812d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
37822d17280bSsbehera 	    portn));
37832d17280bSsbehera 
37842d17280bSsbehera 	statsp = nxgep->statsp;
37852d17280bSsbehera 
37861c7408c9Stc99174@train 	/* Disable Link LEDs, with or without PHY */
37871c7408c9Stc99174@train 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
37881c7408c9Stc99174@train 		goto done;
37891c7408c9Stc99174@train 
37901c7408c9Stc99174@train 	/* Skip MDIO, if PHY absent */
37911c7408c9Stc99174@train 	if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
37922d17280bSsbehera 		goto done;
37932d17280bSsbehera 	}
37942d17280bSsbehera 
37952d17280bSsbehera 	/* Set Clause 45 */
37962d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
37972d17280bSsbehera 
37982d17280bSsbehera 	switch (nxgep->chip_id) {
37992d17280bSsbehera 	case BCM8704_CHIP_ID:
380000161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
38012d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
38022d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
38032d17280bSsbehera 		break;
38042d17280bSsbehera 	case BCM8706_CHIP_ID:
380500161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
38062d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
38072d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
38082d17280bSsbehera 		break;
380952cdd236Ssbehera 	case MRVL88X201X_CHIP_ID:
381000161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
381189282175SSantwona Behera 		    "Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id));
381252cdd236Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
381352cdd236Ssbehera 		break;
381489282175SSantwona Behera 	case NLP2020_CHIP_ID:
381589282175SSantwona Behera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
381689282175SSantwona Behera 		    "Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id));
381789282175SSantwona Behera 		status = nxge_nlp2020_xcvr_init(nxgep);
381889282175SSantwona Behera 		break;
38192d17280bSsbehera 	default:
38202d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
38212d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
38222d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
38232d17280bSsbehera 		goto fail;
38242d17280bSsbehera 	}
38252d17280bSsbehera 
38262d17280bSsbehera 	if (status != NXGE_OK) {
38272d17280bSsbehera 		goto fail;
38282d17280bSsbehera 	}
38292e59129aSraghus done:
38306f45ec7bSml29623 	statsp->mac_stats.cap_10gfdx = 1;
38316f45ec7bSml29623 	statsp->mac_stats.lp_cap_10gfdx = 1;
38321bd6825cSml29623 	statsp->mac_stats.adv_cap_asmpause =
38331bd6825cSml29623 	    param_arr[param_anar_asmpause].value;
38341bd6825cSml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
383559ac0c16Sdavemq 
383659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
383759ac0c16Sdavemq 	    portn));
383859ac0c16Sdavemq 	return (NXGE_OK);
383959ac0c16Sdavemq 
384059ac0c16Sdavemq fail:
38412d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
384259ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
38432d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
38442d17280bSsbehera 	return (NXGE_ERROR);
384559ac0c16Sdavemq }
384659ac0c16Sdavemq 
384759ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
384859ac0c16Sdavemq 
384959ac0c16Sdavemq static nxge_status_t
385059ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
385159ac0c16Sdavemq {
385259ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
385359ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
385459ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
385559ac0c16Sdavemq 
38562e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
38572e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
38582e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
38592e59129aSraghus 		goto done;
38602e59129aSraghus 	}
38612e59129aSraghus 
38626f45ec7bSml29623 	/* Set Clause 22 */
38636f45ec7bSml29623 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
38646f45ec7bSml29623 
38656f45ec7bSml29623 	/* Set capability flags */
386659ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
38672e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
38682e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
38692e59129aSraghus 		statsp->mac_stats.cap_100fdx =
38702e59129aSraghus 		    param_arr[param_anar_100fdx].value;
38712e59129aSraghus 		statsp->mac_stats.cap_10fdx =
38722e59129aSraghus 		    param_arr[param_anar_10fdx].value;
38732e59129aSraghus 	}
38746f45ec7bSml29623 
387559ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
38762e59129aSraghus done:
387759ac0c16Sdavemq 	return (status);
38786f45ec7bSml29623 }
38796f45ec7bSml29623 
388000161856Syc148097 /*
388100161856Syc148097  * Although the Teranetics copper transceiver (TN1010) does not need
388200161856Syc148097  * to be initialized by the driver for passing packets, this funtion
388300161856Syc148097  * initializes the members of nxgep->statsp->mac_stats struct for
388400161856Syc148097  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
388500161856Syc148097  * It also configures the TN1010 for PHY loopback to support SunVTS.
388600161856Syc148097  *
388700161856Syc148097  * TN1010 only has the option to disable advertisement for the 10G
388800161856Syc148097  * mode. So we can set it to either Dual Mode or 1G Only mode but
388900161856Syc148097  * can't set it to 10G Only mode.
389000161856Syc148097  *
389100161856Syc148097  * ndd -set command can set the following 6 speed/duplex related parameters.
389200161856Syc148097  *
389300161856Syc148097  * ----------------------------------------------------------------
389400161856Syc148097  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
389500161856Syc148097  * ----------------------------------------------------------------
389600161856Syc148097  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
389700161856Syc148097  * adv_10gfdx_cap
389800161856Syc148097  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
389900161856Syc148097  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
390000161856Syc148097  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
390100161856Syc148097  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
390200161856Syc148097  * ----------------------------------------------------------------
390300161856Syc148097  */
390400161856Syc148097 static nxge_status_t
390500161856Syc148097 nxge_tn1010_xcvr_init(p_nxge_t nxgep)
390600161856Syc148097 {
390700161856Syc148097 	p_nxge_param_t		param_arr;
390800161856Syc148097 	p_nxge_stats_t		statsp;
390900161856Syc148097 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
391000161856Syc148097 	uint16_t		speed;
391100161856Syc148097 	uint8_t			phy_port_addr;
391200161856Syc148097 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
391300161856Syc148097 	int			status = NXGE_OK;
391400161856Syc148097 
391500161856Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
391600161856Syc148097 
391700161856Syc148097 	param_arr	= nxgep->param_arr;
391800161856Syc148097 	statsp		= nxgep->statsp;
391900161856Syc148097 
392000161856Syc148097 	/*
392100161856Syc148097 	 * Initialize the xcvr statistics which are NOT controlled by ndd
392200161856Syc148097 	 */
392300161856Syc148097 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
392400161856Syc148097 	statsp->mac_stats.cap_100T4    = 0;
392500161856Syc148097 
392600161856Syc148097 	/*
392700161856Syc148097 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
392800161856Syc148097 	 * that function nxge_check_tn1010_link repeatedly invoked by the
392900161856Syc148097 	 * timer will update link_speed real time.
393000161856Syc148097 	 */
393100161856Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
393200161856Syc148097 		goto fail;
393300161856Syc148097 	}
393400161856Syc148097 	if (speed == TN1010_SPEED_1G) {
393500161856Syc148097 		statsp->mac_stats.cap_10gfdx = 0;
393600161856Syc148097 	} else {
393700161856Syc148097 		statsp->mac_stats.cap_10gfdx = 1;
393800161856Syc148097 	}
393900161856Syc148097 
394000161856Syc148097 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
394100161856Syc148097 	statsp->mac_stats.cap_1000fdx  = 1;
394200161856Syc148097 
394300161856Syc148097 	/* TN1010 is not able to operate in the following states */
394400161856Syc148097 	statsp->mac_stats.cap_1000hdx  = 0;
394500161856Syc148097 	statsp->mac_stats.cap_100fdx   = 0;
394600161856Syc148097 	statsp->mac_stats.cap_100hdx   = 0;
394700161856Syc148097 	statsp->mac_stats.cap_10fdx    = 0;
394800161856Syc148097 	statsp->mac_stats.cap_10hdx    = 0;
394900161856Syc148097 
395000161856Syc148097 	/* param_anar_pause can be modified by ndd -set */
395100161856Syc148097 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
395200161856Syc148097 
395300161856Syc148097 	/*
395400161856Syc148097 	 * The following 4 lines actually overwrites what ever the ndd command
395500161856Syc148097 	 * has set. For example, by command
395600161856Syc148097 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
395700161856Syc148097 	 * we could set param_arr[param_autoneg].value to n.  However, because
395800161856Syc148097 	 * here we assign constants to these parameters, whatever we set with
395900161856Syc148097 	 * the "ndd -set" command will be replaced. So command
396000161856Syc148097 	 *	kstat nxge:X | grep param
396100161856Syc148097 	 * will always show those constant values.  In other words, the
396200161856Syc148097 	 * "ndd -set" command can NOT change the values of these 4 parameters
396300161856Syc148097 	 * even though the command appears to be successful.
396400161856Syc148097 	 *
396500161856Syc148097 	 * Note: TN1010 auto negotiation is always enabled.
396600161856Syc148097 	 */
396700161856Syc148097 	statsp->mac_stats.adv_cap_autoneg
396800161856Syc148097 	    = param_arr[param_autoneg].value = 1;
396900161856Syc148097 	statsp->mac_stats.adv_cap_1000fdx
397000161856Syc148097 	    = param_arr[param_anar_1000fdx].value = 1;
397100161856Syc148097 	statsp->mac_stats.adv_cap_100fdx
397200161856Syc148097 	    = param_arr[param_anar_100fdx].value = 0;
397300161856Syc148097 	statsp->mac_stats.adv_cap_10fdx
397400161856Syc148097 	    = param_arr[param_anar_10fdx].value = 0;
397500161856Syc148097 
397600161856Syc148097 	/*
397700161856Syc148097 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
397800161856Syc148097 	 * defined in nxge_param_arr[], therefore they are not seen by the
397900161856Syc148097 	 * "ndd -get" command and can not be changed by ndd.  We just set
398000161856Syc148097 	 * them (both ndd param and kstat values) to constant 0 because TN1010
398100161856Syc148097 	 * does not support those speeds.
398200161856Syc148097 	 */
398300161856Syc148097 	statsp->mac_stats.adv_cap_100T4
398400161856Syc148097 	    = param_arr[param_anar_100T4].value = 0;
398500161856Syc148097 	statsp->mac_stats.adv_cap_1000hdx
398600161856Syc148097 	    = param_arr[param_anar_1000hdx].value = 0;
398700161856Syc148097 	statsp->mac_stats.adv_cap_100hdx
398800161856Syc148097 	    = param_arr[param_anar_100hdx].value = 0;
398900161856Syc148097 	statsp->mac_stats.adv_cap_10hdx
399000161856Syc148097 	    = param_arr[param_anar_10hdx].value = 0;
399100161856Syc148097 
399200161856Syc148097 	/*
399300161856Syc148097 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
399400161856Syc148097 	 * by ndd
399500161856Syc148097 	 */
399600161856Syc148097 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
399700161856Syc148097 
399800161856Syc148097 	/*
399900161856Syc148097 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
400000161856Syc148097 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
400100161856Syc148097 	 * "ndd -get" command and can not be changed by ndd. Here we do not
400200161856Syc148097 	 * assign a constant to it so the default value defined in
400300161856Syc148097 	 * nxge_param_arr[] will be used to set the parameter and
400400161856Syc148097 	 * will be shown by the kstat.
400500161856Syc148097 	 */
400600161856Syc148097 	statsp->mac_stats.adv_cap_asmpause
400700161856Syc148097 	    = param_arr[param_anar_asmpause].value;
400800161856Syc148097 
400900161856Syc148097 	/*
401000161856Syc148097 	 * Initialize the link statistics.
401100161856Syc148097 	 */
401200161856Syc148097 	statsp->mac_stats.link_T4 = 0;
401300161856Syc148097 	statsp->mac_stats.link_asmpause = 0;
401400161856Syc148097 	statsp->mac_stats.link_pause = 0;
401500161856Syc148097 	if (speed == TN1010_SPEED_1G) {
401600161856Syc148097 		statsp->mac_stats.link_speed = 1000;
401700161856Syc148097 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
401800161856Syc148097 		statsp->mac_stats.link_up = 1;
401900161856Syc148097 	} else {
402000161856Syc148097 		statsp->mac_stats.link_speed = 10000;
402100161856Syc148097 		statsp->mac_stats.link_duplex = 2;
402200161856Syc148097 		statsp->mac_stats.link_up = 1;
402300161856Syc148097 	}
402400161856Syc148097 
402500161856Syc148097 	/*
402600161856Syc148097 	 * Because TN1010 does not have a link partner register, to
402700161856Syc148097 	 * figure out the link partner's capabilities is tricky. Here we
402800161856Syc148097 	 * just set the kstat based on our knowledge about the partner
402900161856Syc148097 	 * (The partner must support auto-neg because auto-negotiation
403000161856Syc148097 	 * has completed, it must support 1G or 10G because that is the
403100161856Syc148097 	 * negotiated speed we are using.)
403200161856Syc148097 	 *
403300161856Syc148097 	 * Note: Current kstat does not show lp_cap_10gfdx and
403400161856Syc148097 	 *	lp_cap_10ghdx.
403500161856Syc148097 	 */
403600161856Syc148097 	if (speed == TN1010_SPEED_1G) {
403700161856Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 1;
403800161856Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 0;
403900161856Syc148097 	} else {
404000161856Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 0;
404100161856Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 1;
404200161856Syc148097 	}
404300161856Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
404400161856Syc148097 	statsp->mac_stats.lp_cap_1000hdx  = 0;
404500161856Syc148097 	statsp->mac_stats.lp_cap_100fdx   = 0;
404600161856Syc148097 	statsp->mac_stats.lp_cap_100hdx   = 0;
404700161856Syc148097 	statsp->mac_stats.lp_cap_10fdx    = 0;
404800161856Syc148097 	statsp->mac_stats.lp_cap_10hdx    = 0;
404900161856Syc148097 	statsp->mac_stats.lp_cap_10gfdx   = 0;
405000161856Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
405100161856Syc148097 	statsp->mac_stats.lp_cap_100T4    = 0;
405200161856Syc148097 	statsp->mac_stats.lp_cap_autoneg  = 1;
405300161856Syc148097 	statsp->mac_stats.lp_cap_asmpause = 0;
405400161856Syc148097 	statsp->mac_stats.lp_cap_pause    = 0;
405500161856Syc148097 
405600161856Syc148097 	/* Handle PHY loopback for SunVTS loopback test */
405700161856Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
405800161856Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
405900161856Syc148097 
406000161856Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
406100161856Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
406200161856Syc148097 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
406300161856Syc148097 		goto fail;
406400161856Syc148097 	}
406500161856Syc148097 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
406600161856Syc148097 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
406700161856Syc148097 		tn1010_pcs_ctrl.bits.loopback = 1;
406800161856Syc148097 	} else {
406900161856Syc148097 		tn1010_pcs_ctrl.bits.loopback = 0;
407000161856Syc148097 	}
407100161856Syc148097 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
407200161856Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
407300161856Syc148097 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
407400161856Syc148097 		goto fail;
407500161856Syc148097 	}
407600161856Syc148097 
407700161856Syc148097 	statsp->mac_stats.xcvr_inits++;
407800161856Syc148097 
407900161856Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
408000161856Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
408100161856Syc148097 	return (status);
408200161856Syc148097 fail:
408300161856Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
408400161856Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
408500161856Syc148097 	return (status);
408600161856Syc148097 }
408700161856Syc148097 
408859ac0c16Sdavemq /* Initialize transceiver */
40896f45ec7bSml29623 
409059ac0c16Sdavemq nxge_status_t
409159ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
409259ac0c16Sdavemq {
409359ac0c16Sdavemq 	p_nxge_stats_t		statsp;
409459ac0c16Sdavemq #ifdef	NXGE_DEBUG
409559ac0c16Sdavemq 	uint8_t			portn;
409659ac0c16Sdavemq #endif
409759ac0c16Sdavemq 
409859ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
409959ac0c16Sdavemq #ifdef	NXGE_DEBUG
410059ac0c16Sdavemq 	portn = nxgep->mac.portnum;
410159ac0c16Sdavemq #endif
41026f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
410359ac0c16Sdavemq 	statsp = nxgep->statsp;
410459ac0c16Sdavemq 
410559ac0c16Sdavemq 	/*
410600161856Syc148097 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
410700161856Syc148097 	 * modify mac_stats.
410859ac0c16Sdavemq 	 */
410959ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
411059ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
411159ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
411259ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
411359ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
411459ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
411559ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
411659ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
411759ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
411859ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
411959ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
412059ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
412159ac0c16Sdavemq 
412259ac0c16Sdavemq 	/*
412359ac0c16Sdavemq 	 * Initialize the link statistics.
412459ac0c16Sdavemq 	 */
412559ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
412659ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
412759ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
412859ac0c16Sdavemq 
412959ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
413059ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
413159ac0c16Sdavemq 		if (status != NXGE_OK)
413259ac0c16Sdavemq 			goto fail;
413359ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
413459ac0c16Sdavemq 	}
413559ac0c16Sdavemq 
413659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
413759ac0c16Sdavemq 	    portn));
41386f45ec7bSml29623 	return (NXGE_OK);
41396f45ec7bSml29623 
41406f45ec7bSml29623 fail:
41416f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41426f45ec7bSml29623 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
41436f45ec7bSml29623 	    portn));
41446f45ec7bSml29623 	return (status);
41456f45ec7bSml29623 }
41466f45ec7bSml29623 
41472e59129aSraghus /* Look for transceiver type */
41482e59129aSraghus 
41492e59129aSraghus nxge_status_t
41502e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
41512e59129aSraghus {
4152d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
4153d81011f0Ssbehera 	    nxgep->mac.portnum));
41542e59129aSraghus 
41552e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
41562e59129aSraghus 		return (NXGE_ERROR);
41572e59129aSraghus 
41582e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
41592e59129aSraghus 		return (NXGE_ERROR);
41602e59129aSraghus 
41612e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
41622e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
41632e59129aSraghus 	return (NXGE_OK);
41642e59129aSraghus }
41656f45ec7bSml29623 
41666f45ec7bSml29623 /* Initialize the TxMAC sub-block */
41676f45ec7bSml29623 
41686f45ec7bSml29623 nxge_status_t
41696f45ec7bSml29623 nxge_tx_mac_init(p_nxge_t nxgep)
41706f45ec7bSml29623 {
41716f45ec7bSml29623 	npi_attr_t		ap;
41726f45ec7bSml29623 	uint8_t			portn;
41736f45ec7bSml29623 	nxge_port_mode_t	portmode;
41746f45ec7bSml29623 	nxge_port_t		portt;
41756f45ec7bSml29623 	npi_handle_t		handle;
41766f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
41776f45ec7bSml29623 
41786f45ec7bSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
41796f45ec7bSml29623 	portt    = nxgep->mac.porttype;
41806f45ec7bSml29623 	handle   = nxgep->npi_handle;
41816f45ec7bSml29623 	portmode = nxgep->mac.portmode;
41826f45ec7bSml29623 
41836f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
41846f45ec7bSml29623 	    portn));
41856f45ec7bSml29623 	/* Set Max and Min Frame Size */
41864202ea4bSsbehera 	/*
41871bd6825cSml29623 	 * Use maxframesize to configure the hardware maxframe size
418800161856Syc148097 	 * and minframesize to configure the hardware minframe size.
41894202ea4bSsbehera 	 */
41901bd6825cSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41911bd6825cSml29623 	    "==> nxge_tx_mac_init: port<%d> "
41921bd6825cSml29623 	    "min framesize %d max framesize %d ",
41931bd6825cSml29623 	    nxgep->mac.minframesize,
41941bd6825cSml29623 	    nxgep->mac.maxframesize,
41951bd6825cSml29623 	    portn));
41966f45ec7bSml29623 
41971bd6825cSml29623 	SET_MAC_ATTR2(handle, ap, portn,
41981bd6825cSml29623 	    MAC_PORT_FRAME_SIZE,
41991bd6825cSml29623 	    nxgep->mac.minframesize,
42001bd6825cSml29623 	    nxgep->mac.maxframesize,
42011bd6825cSml29623 	    rs);
42026f45ec7bSml29623 	if (rs != NPI_SUCCESS)
42036f45ec7bSml29623 		goto fail;
42046f45ec7bSml29623 
42056f45ec7bSml29623 	if (portt == PORT_TYPE_XMAC) {
42066f45ec7bSml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
42076f45ec7bSml29623 		    0)) != NPI_SUCCESS)
42086f45ec7bSml29623 			goto fail;
42096f45ec7bSml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
42106f45ec7bSml29623 		if ((portmode == PORT_10G_FIBER) ||
42112e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
421200161856Syc148097 		    (portmode == PORT_10G_TN1010) ||
42131c7408c9Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
42142e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
42156f45ec7bSml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
42166f45ec7bSml29623 			    XGMII_IPG_12_15, rs);
42176f45ec7bSml29623 			if (rs != NPI_SUCCESS)
42186f45ec7bSml29623 				goto fail;
42196f45ec7bSml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
42206f45ec7bSml29623 		} else {
42216f45ec7bSml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
42226f45ec7bSml29623 			    MII_GMII_IPG_12, rs);
42236f45ec7bSml29623 			if (rs != NPI_SUCCESS)
42246f45ec7bSml29623 				goto fail;
42256f45ec7bSml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
42266f45ec7bSml29623 		}
42276f45ec7bSml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
42286f45ec7bSml29623 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
42296f45ec7bSml29623 			goto fail;
42306f45ec7bSml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
42316f45ec7bSml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
42326f45ec7bSml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
42336f45ec7bSml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
42346f45ec7bSml29623 
42356f45ec7bSml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
42366f45ec7bSml29623 		    != NPI_SUCCESS)
42376f45ec7bSml29623 			goto fail;
42386f45ec7bSml29623 
42396f45ec7bSml29623 	} else {
42406f45ec7bSml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
42416f45ec7bSml29623 		    0)) != NPI_SUCCESS)
42426f45ec7bSml29623 			goto fail;
42436f45ec7bSml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
42446f45ec7bSml29623 
42456f45ec7bSml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
42466f45ec7bSml29623 		    rs);
42476f45ec7bSml29623 		if (rs != NPI_SUCCESS)
42486f45ec7bSml29623 			goto fail;
42496f45ec7bSml29623 		nxgep->mac.ctrltype = 0x8808;
42506f45ec7bSml29623 
42516f45ec7bSml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
42526f45ec7bSml29623 		if (rs != NPI_SUCCESS)
42536f45ec7bSml29623 			goto fail;
42546f45ec7bSml29623 		nxgep->mac.pa_size = 0x7;
42556f45ec7bSml29623 
42566f45ec7bSml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
42576f45ec7bSml29623 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
42586f45ec7bSml29623 			goto fail;
42596f45ec7bSml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
42606f45ec7bSml29623 	}
42616f45ec7bSml29623 
42626f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
42636f45ec7bSml29623 	    portn));
42646f45ec7bSml29623 
42656f45ec7bSml29623 	return (NXGE_OK);
42666f45ec7bSml29623 fail:
42676f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
426852ccf843Smisaki 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
42696f45ec7bSml29623 
42706f45ec7bSml29623 	return (NXGE_ERROR | rs);
42716f45ec7bSml29623 }
42726f45ec7bSml29623 
42730dc2366fSVenugopal Iyer static npi_status_t
42740dc2366fSVenugopal Iyer nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)
42750dc2366fSVenugopal Iyer {
42760dc2366fSVenugopal Iyer 	uint32_t		i;
42770dc2366fSVenugopal Iyer 	uint16_t		hashtab_e;
42780dc2366fSVenugopal Iyer 	p_hash_filter_t		hash_filter;
42790dc2366fSVenugopal Iyer 	uint8_t			portn;
42800dc2366fSVenugopal Iyer 	npi_handle_t		handle;
42810dc2366fSVenugopal Iyer 	npi_status_t		rs = NPI_SUCCESS;
4282678453a8Sspeer 
42830dc2366fSVenugopal Iyer 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
42840dc2366fSVenugopal Iyer 	handle = nxgep->npi_handle;
42856f45ec7bSml29623 
42860dc2366fSVenugopal Iyer 	/*
42870dc2366fSVenugopal Iyer 	 * Load the multicast hash filter bits.
42880dc2366fSVenugopal Iyer 	 */
42890dc2366fSVenugopal Iyer 	hash_filter = nxgep->hash_filter;
42900dc2366fSVenugopal Iyer 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
42910dc2366fSVenugopal Iyer 		if (hash_filter != NULL) {
42920dc2366fSVenugopal Iyer 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
42930dc2366fSVenugopal Iyer 			    (NMCFILTER_REGS - 1) - i];
42940dc2366fSVenugopal Iyer 		} else {
42950dc2366fSVenugopal Iyer 			hashtab_e = 0;
42960dc2366fSVenugopal Iyer 		}
42970dc2366fSVenugopal Iyer 
42980dc2366fSVenugopal Iyer 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
42990dc2366fSVenugopal Iyer 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
43000dc2366fSVenugopal Iyer 			return (rs);
43010dc2366fSVenugopal Iyer 	}
43020dc2366fSVenugopal Iyer 
43030dc2366fSVenugopal Iyer 	return (NPI_SUCCESS);
43040dc2366fSVenugopal Iyer }
43050dc2366fSVenugopal Iyer 
43060dc2366fSVenugopal Iyer /*
43070dc2366fSVenugopal Iyer  * Initialize the RxMAC sub-block
43080dc2366fSVenugopal Iyer  */
43096f45ec7bSml29623 nxge_status_t
43106f45ec7bSml29623 nxge_rx_mac_init(p_nxge_t nxgep)
43116f45ec7bSml29623 {
43126f45ec7bSml29623 	npi_attr_t		ap;
43136f45ec7bSml29623 	nxge_port_t		portt;
43146f45ec7bSml29623 	uint8_t			portn;
43156f45ec7bSml29623 	npi_handle_t		handle;
43166f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
43176f45ec7bSml29623 	uint16_t 		*addr16p;
43186f45ec7bSml29623 	uint16_t 		addr0, addr1, addr2;
43196f45ec7bSml29623 	xmac_rx_config_t	xconfig;
43206f45ec7bSml29623 	bmac_rx_config_t	bconfig;
43216f45ec7bSml29623 
43226f45ec7bSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
43236f45ec7bSml29623 
43246f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
43256f45ec7bSml29623 	    portn));
43266f45ec7bSml29623 	handle = nxgep->npi_handle;
43276f45ec7bSml29623 	portt = nxgep->mac.porttype;
43286f45ec7bSml29623 
43296f45ec7bSml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
43306f45ec7bSml29623 	addr0 = ntohs(addr16p[2]);
43316f45ec7bSml29623 	addr1 = ntohs(addr16p[1]);
43326f45ec7bSml29623 	addr2 = ntohs(addr16p[0]);
43330dc2366fSVenugopal Iyer 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR,
43340dc2366fSVenugopal Iyer 	    addr0, addr1, addr2, rs);
43356f45ec7bSml29623 	if (rs != NPI_SUCCESS)
43366f45ec7bSml29623 		goto fail;
43376f45ec7bSml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
43386f45ec7bSml29623 	if (rs != NPI_SUCCESS)
43396f45ec7bSml29623 		goto fail;
43406f45ec7bSml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
43416f45ec7bSml29623 	if (rs != NPI_SUCCESS)
43426f45ec7bSml29623 		goto fail;
43436f45ec7bSml29623 
43440dc2366fSVenugopal Iyer 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
43450dc2366fSVenugopal Iyer 	if (rs != NPI_SUCCESS)
43466f45ec7bSml29623 		goto fail;
43476f45ec7bSml29623 
43486f45ec7bSml29623 	if (portt == PORT_TYPE_XMAC) {
43496f45ec7bSml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
43506f45ec7bSml29623 		    0)) != NPI_SUCCESS)
43516f45ec7bSml29623 			goto fail;
43526f45ec7bSml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
43536f45ec7bSml29623 
43546f45ec7bSml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
43556f45ec7bSml29623 
43566f45ec7bSml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
43576f45ec7bSml29623 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
43586f45ec7bSml29623 		    ~CFG_XMAC_RX_STRIP_CRC;
43596f45ec7bSml29623 
43606f45ec7bSml29623 		if (nxgep->filter.all_phys_cnt != 0)
43616f45ec7bSml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
43626f45ec7bSml29623 		if (nxgep->filter.all_multicast_cnt != 0)
43636f45ec7bSml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
43646f45ec7bSml29623 
43656f45ec7bSml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
43666f45ec7bSml29623 
43670dc2366fSVenugopal Iyer 		if ((rs = npi_xmac_rx_config(handle, INIT,
43680dc2366fSVenugopal Iyer 		    portn, xconfig)) != NPI_SUCCESS)
43696f45ec7bSml29623 			goto fail;
43706f45ec7bSml29623 		nxgep->mac.rx_config = xconfig;
43716f45ec7bSml29623 
43720dc2366fSVenugopal Iyer 		/*
43730dc2366fSVenugopal Iyer 		 * Comparison of mac unique address is always
43740dc2366fSVenugopal Iyer 		 * enabled on XMAC
43750dc2366fSVenugopal Iyer 		 */
43766f45ec7bSml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
43776f45ec7bSml29623 		    != NPI_SUCCESS)
43786f45ec7bSml29623 			goto fail;
43796f45ec7bSml29623 	} else {
43806f45ec7bSml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
43816f45ec7bSml29623 		    0) != NPI_SUCCESS)
43826f45ec7bSml29623 			goto fail;
43830dc2366fSVenugopal Iyer 
43846f45ec7bSml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
43856f45ec7bSml29623 
43860dc2366fSVenugopal Iyer 		(void) nxge_fflp_init_hostinfo(nxgep);
43870dc2366fSVenugopal Iyer 
43886f45ec7bSml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
43896f45ec7bSml29623 		    ~CFG_BMAC_RX_STRIP_CRC;
43906f45ec7bSml29623 
43916f45ec7bSml29623 		if (nxgep->filter.all_phys_cnt != 0)
43926f45ec7bSml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
43936f45ec7bSml29623 		if (nxgep->filter.all_multicast_cnt != 0)
43946f45ec7bSml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
43956f45ec7bSml29623 
43966f45ec7bSml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
43970dc2366fSVenugopal Iyer 		if ((rs = npi_bmac_rx_config(handle, INIT,
43980dc2366fSVenugopal Iyer 		    portn, bconfig)) != NPI_SUCCESS)
43996f45ec7bSml29623 			goto fail;
44006f45ec7bSml29623 		nxgep->mac.rx_config = bconfig;
44016f45ec7bSml29623 
44020dc2366fSVenugopal Iyer 		/*
44030dc2366fSVenugopal Iyer 		 * Always enable comparison of mac unique address
44040dc2366fSVenugopal Iyer 		 */
44050dc2366fSVenugopal Iyer 		if ((rs = npi_mac_altaddr_enable(handle,
44060dc2366fSVenugopal Iyer 		    portn, 0)) != NPI_SUCCESS)
44076f45ec7bSml29623 			goto fail;
44086f45ec7bSml29623 	}
44096f45ec7bSml29623 
44106f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
44116f45ec7bSml29623 	    portn));
44126f45ec7bSml29623 
44136f45ec7bSml29623 	return (NXGE_OK);
44146f45ec7bSml29623 
44156f45ec7bSml29623 fail:
44166f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
441752ccf843Smisaki 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
44186f45ec7bSml29623 
44196f45ec7bSml29623 	return (NXGE_ERROR | rs);
44206f45ec7bSml29623 }
44216f45ec7bSml29623 
44226f45ec7bSml29623 /* Enable TXMAC */
44236f45ec7bSml29623 
44246f45ec7bSml29623 nxge_status_t
44256f45ec7bSml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
44266f45ec7bSml29623 {
44276f45ec7bSml29623 	npi_handle_t	handle;
44286f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
44296f45ec7bSml29623 	nxge_status_t	status = NXGE_OK;
44306f45ec7bSml29623 
44316f45ec7bSml29623 	handle = nxgep->npi_handle;
44326f45ec7bSml29623 
44336f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
44346f45ec7bSml29623 	    nxgep->mac.portnum));
44356f45ec7bSml29623 
44366f45ec7bSml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
44376f45ec7bSml29623 		goto fail;
44386f45ec7bSml29623 
44396f45ec7bSml29623 	/* based on speed */
44406f45ec7bSml29623 	nxgep->msg_min = ETHERMIN;
44416f45ec7bSml29623 
44426f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
44436f45ec7bSml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
44446f45ec7bSml29623 		    CFG_XMAC_TX)) != NPI_SUCCESS)
44456f45ec7bSml29623 			goto fail;
44466f45ec7bSml29623 	} else {
44476f45ec7bSml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
44486f45ec7bSml29623 		    CFG_BMAC_TX)) != NPI_SUCCESS)
44496f45ec7bSml29623 			goto fail;
44506f45ec7bSml29623 	}
44516f45ec7bSml29623 
44526f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
44536f45ec7bSml29623 	    nxgep->mac.portnum));
44546f45ec7bSml29623 
44556f45ec7bSml29623 	return (NXGE_OK);
44566f45ec7bSml29623 fail:
44576f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
44586f45ec7bSml29623 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
44596f45ec7bSml29623 	    nxgep->mac.portnum));
44606f45ec7bSml29623 	if (rs != NPI_SUCCESS)
44616f45ec7bSml29623 		return (NXGE_ERROR | rs);
44626f45ec7bSml29623 	else
44636f45ec7bSml29623 		return (status);
44646f45ec7bSml29623 }
44656f45ec7bSml29623 
44666f45ec7bSml29623 /* Disable TXMAC */
44676f45ec7bSml29623 
44686f45ec7bSml29623 nxge_status_t
44696f45ec7bSml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
44706f45ec7bSml29623 {
44716f45ec7bSml29623 	npi_handle_t	handle;
44726f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
44736f45ec7bSml29623 
4474678453a8Sspeer 	if (isLDOMguest(nxgep))
4475678453a8Sspeer 		return (NXGE_OK);
4476678453a8Sspeer 
44776f45ec7bSml29623 	handle = nxgep->npi_handle;
44786f45ec7bSml29623 
44796f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
44806f45ec7bSml29623 	    nxgep->mac.portnum));
44816f45ec7bSml29623 
44826f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
44836f45ec7bSml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
44846f45ec7bSml29623 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
44856f45ec7bSml29623 			goto fail;
44866f45ec7bSml29623 	} else {
44876f45ec7bSml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
44886f45ec7bSml29623 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
44896f45ec7bSml29623 			goto fail;
44906f45ec7bSml29623 	}
44916f45ec7bSml29623 
44926f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
44936f45ec7bSml29623 	    nxgep->mac.portnum));
44946f45ec7bSml29623 	return (NXGE_OK);
44956f45ec7bSml29623 fail:
44966f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
44976f45ec7bSml29623 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
44986f45ec7bSml29623 	    nxgep->mac.portnum));
44996f45ec7bSml29623 	return (NXGE_ERROR | rs);
45006f45ec7bSml29623 }
45016f45ec7bSml29623 
45026f45ec7bSml29623 /* Enable RXMAC */
45036f45ec7bSml29623 
45046f45ec7bSml29623 nxge_status_t
45056f45ec7bSml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
45066f45ec7bSml29623 {
45076f45ec7bSml29623 	npi_handle_t	handle;
45086f45ec7bSml29623 	uint8_t 	portn;
45096f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
45106f45ec7bSml29623 	nxge_status_t	status = NXGE_OK;
45116f45ec7bSml29623 
4512678453a8Sspeer 	/* This is a service-domain-only activity. */
4513678453a8Sspeer 	if (isLDOMguest(nxgep))
4514678453a8Sspeer 		return (status);
4515678453a8Sspeer 
45166f45ec7bSml29623 	handle = nxgep->npi_handle;
45176f45ec7bSml29623 	portn = nxgep->mac.portnum;
45186f45ec7bSml29623 
45196f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
45206f45ec7bSml29623 	    portn));
45216f45ec7bSml29623 
45226f45ec7bSml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
45236f45ec7bSml29623 		goto fail;
45246f45ec7bSml29623 
45256f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
45266f45ec7bSml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
45276f45ec7bSml29623 		    CFG_XMAC_RX)) != NPI_SUCCESS)
45286f45ec7bSml29623 			goto fail;
45296f45ec7bSml29623 	} else {
45306f45ec7bSml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
45316f45ec7bSml29623 		    CFG_BMAC_RX)) != NPI_SUCCESS)
45326f45ec7bSml29623 			goto fail;
45336f45ec7bSml29623 	}
45346f45ec7bSml29623 
4535678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4536678453a8Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
45376f45ec7bSml29623 
45386f45ec7bSml29623 	return (NXGE_OK);
45396f45ec7bSml29623 fail:
45406f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4541678453a8Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
45426f45ec7bSml29623 
45436f45ec7bSml29623 	if (rs != NPI_SUCCESS)
45446f45ec7bSml29623 		return (NXGE_ERROR | rs);
45456f45ec7bSml29623 	else
45466f45ec7bSml29623 		return (status);
45476f45ec7bSml29623 }
45486f45ec7bSml29623 
45496f45ec7bSml29623 /* Disable RXMAC */
45506f45ec7bSml29623 
45516f45ec7bSml29623 nxge_status_t
45526f45ec7bSml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
45536f45ec7bSml29623 {
45546f45ec7bSml29623 	npi_handle_t	handle;
45556f45ec7bSml29623 	uint8_t		portn;
45566f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
45576f45ec7bSml29623 
4558678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
4559678453a8Sspeer 	if (isLDOMguest(nxgep))
4560678453a8Sspeer 		return (NXGE_OK);
4561678453a8Sspeer 
45626f45ec7bSml29623 	handle = nxgep->npi_handle;
45636f45ec7bSml29623 	portn = nxgep->mac.portnum;
45646f45ec7bSml29623 
45656f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
45666f45ec7bSml29623 	    portn));
45676f45ec7bSml29623 
45686f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
45696f45ec7bSml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
45706f45ec7bSml29623 		    CFG_XMAC_RX)) != NPI_SUCCESS)
45716f45ec7bSml29623 			goto fail;
45726f45ec7bSml29623 	} else {
45736f45ec7bSml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
45746f45ec7bSml29623 		    CFG_BMAC_RX)) != NPI_SUCCESS)
45756f45ec7bSml29623 			goto fail;
45766f45ec7bSml29623 	}
45776f45ec7bSml29623 
45786f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
45796f45ec7bSml29623 	    portn));
45806f45ec7bSml29623 	return (NXGE_OK);
45816f45ec7bSml29623 fail:
45826f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
458352ccf843Smisaki 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
45846f45ec7bSml29623 
45856f45ec7bSml29623 	return (NXGE_ERROR | rs);
45866f45ec7bSml29623 }
45876f45ec7bSml29623 
45886f45ec7bSml29623 /* Reset TXMAC */
45896f45ec7bSml29623 
45906f45ec7bSml29623 nxge_status_t
45916f45ec7bSml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
45926f45ec7bSml29623 {
45936f45ec7bSml29623 	npi_handle_t	handle;
45946f45ec7bSml29623 	uint8_t		portn;
45956f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
45966f45ec7bSml29623 
45976f45ec7bSml29623 	handle = nxgep->npi_handle;
45986f45ec7bSml29623 	portn = nxgep->mac.portnum;
45996f45ec7bSml29623 
46006f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
46016f45ec7bSml29623 	    portn));
46026f45ec7bSml29623 
46036f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
46046f45ec7bSml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
46056f45ec7bSml29623 		    != NPI_SUCCESS)
46066f45ec7bSml29623 			goto fail;
46076f45ec7bSml29623 	} else {
46086f45ec7bSml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
46096f45ec7bSml29623 		    != NPI_SUCCESS)
46106f45ec7bSml29623 			goto fail;
46116f45ec7bSml29623 	}
46126f45ec7bSml29623 
46136f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
46146f45ec7bSml29623 	    portn));
46156f45ec7bSml29623 
46166f45ec7bSml29623 	return (NXGE_OK);
46176f45ec7bSml29623 fail:
46186f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
461952ccf843Smisaki 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
46206f45ec7bSml29623 
46216f45ec7bSml29623 	return (NXGE_ERROR | rs);
46226f45ec7bSml29623 }
46236f45ec7bSml29623 
46246f45ec7bSml29623 /* Reset RXMAC */
46256f45ec7bSml29623 
46266f45ec7bSml29623 nxge_status_t
46276f45ec7bSml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
46286f45ec7bSml29623 {
46296f45ec7bSml29623 	npi_handle_t	handle;
46306f45ec7bSml29623 	uint8_t		portn;
46316f45ec7bSml29623 	npi_status_t	rs = NPI_SUCCESS;
46326f45ec7bSml29623 
46336f45ec7bSml29623 	handle = nxgep->npi_handle;
46346f45ec7bSml29623 	portn = nxgep->mac.portnum;
46356f45ec7bSml29623 
46366f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
46376f45ec7bSml29623 	    portn));
46386f45ec7bSml29623 
46396f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
46406f45ec7bSml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
46416f45ec7bSml29623 		    != NPI_SUCCESS)
46426f45ec7bSml29623 		goto fail;
46436f45ec7bSml29623 	} else {
46446f45ec7bSml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
46456f45ec7bSml29623 		    != NPI_SUCCESS)
46466f45ec7bSml29623 		goto fail;
46476f45ec7bSml29623 	}
46486f45ec7bSml29623 
46496f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
46506f45ec7bSml29623 	    portn));
46516f45ec7bSml29623 
46526f45ec7bSml29623 	return (NXGE_OK);
46536f45ec7bSml29623 fail:
46546f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
465552ccf843Smisaki 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
46566f45ec7bSml29623 	return (NXGE_ERROR | rs);
46576f45ec7bSml29623 }
46586f45ec7bSml29623 
465959ac0c16Sdavemq /* 10G fiber link interrupt start routine */
46606f45ec7bSml29623 
466159ac0c16Sdavemq static nxge_status_t
466259ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
466359ac0c16Sdavemq {
466459ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
466559ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
466659ac0c16Sdavemq 
466759ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
466859ac0c16Sdavemq 
466959ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
467059ac0c16Sdavemq 		return (NXGE_ERROR | rs);
467159ac0c16Sdavemq 	else
467259ac0c16Sdavemq 		return (NXGE_OK);
467359ac0c16Sdavemq }
467459ac0c16Sdavemq 
467559ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
467659ac0c16Sdavemq 
467759ac0c16Sdavemq static nxge_status_t
467859ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
467959ac0c16Sdavemq {
468059ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
468159ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
468259ac0c16Sdavemq 
468359ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
468459ac0c16Sdavemq 
468559ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
468659ac0c16Sdavemq 		return (NXGE_ERROR | rs);
468759ac0c16Sdavemq 	else
468859ac0c16Sdavemq 		return (NXGE_OK);
468959ac0c16Sdavemq }
469059ac0c16Sdavemq 
469159ac0c16Sdavemq /* 1G fiber link interrupt start routine */
469259ac0c16Sdavemq 
469359ac0c16Sdavemq static nxge_status_t
469459ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
469559ac0c16Sdavemq {
469659ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
469759ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
469859ac0c16Sdavemq 
469959ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
470059ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
470159ac0c16Sdavemq 		return (NXGE_ERROR | rs);
470259ac0c16Sdavemq 	else
470359ac0c16Sdavemq 		return (NXGE_OK);
470459ac0c16Sdavemq }
470559ac0c16Sdavemq 
470659ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
470759ac0c16Sdavemq 
470859ac0c16Sdavemq static nxge_status_t
470959ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
471059ac0c16Sdavemq {
471159ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
471259ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
471359ac0c16Sdavemq 
471459ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
471559ac0c16Sdavemq 
471659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
471759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
471859ac0c16Sdavemq 	else
471959ac0c16Sdavemq 		return (NXGE_OK);
472059ac0c16Sdavemq }
472159ac0c16Sdavemq 
472259ac0c16Sdavemq /* 1G copper link interrupt start routine */
472359ac0c16Sdavemq 
472459ac0c16Sdavemq static nxge_status_t
472559ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
472659ac0c16Sdavemq {
472759ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
472859ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
472959ac0c16Sdavemq 
473059ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
47316b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
473259ac0c16Sdavemq 
473359ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
473459ac0c16Sdavemq 		return (NXGE_ERROR | rs);
473559ac0c16Sdavemq 	else
473659ac0c16Sdavemq 		return (NXGE_OK);
473759ac0c16Sdavemq }
473859ac0c16Sdavemq 
473959ac0c16Sdavemq /* 1G copper link interrupt stop routine */
474059ac0c16Sdavemq 
474159ac0c16Sdavemq static nxge_status_t
474259ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
474359ac0c16Sdavemq {
474459ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
474559ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
474659ac0c16Sdavemq 
474759ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
474859ac0c16Sdavemq 
474959ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
475059ac0c16Sdavemq 		return (NXGE_ERROR | rs);
475159ac0c16Sdavemq 	else
475259ac0c16Sdavemq 		return (NXGE_OK);
475359ac0c16Sdavemq }
475459ac0c16Sdavemq 
475559ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
47566f45ec7bSml29623 
47576f45ec7bSml29623 nxge_status_t
47586f45ec7bSml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
47596f45ec7bSml29623 {
47606f45ec7bSml29623 	uint8_t		portn;
476159ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
47626f45ec7bSml29623 
47636f45ec7bSml29623 	portn = nxgep->mac.portnum;
47646f45ec7bSml29623 
47656f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
476659ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
476759ac0c16Sdavemq 		return (NXGE_OK);
47686f45ec7bSml29623 
476959ac0c16Sdavemq 	if (enable == LINK_INTR_START)
477059ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
477159ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
477259ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
477359ac0c16Sdavemq 	if (status != NXGE_OK)
47746f45ec7bSml29623 		goto fail;
47756f45ec7bSml29623 
47766f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
47776f45ec7bSml29623 
47786f45ec7bSml29623 	return (NXGE_OK);
47796f45ec7bSml29623 fail:
47806f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
478152ccf843Smisaki 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
47826f45ec7bSml29623 
478359ac0c16Sdavemq 	return (status);
47846f45ec7bSml29623 }
47856f45ec7bSml29623 
47866f45ec7bSml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
47876f45ec7bSml29623 
47886f45ec7bSml29623 nxge_status_t
47896f45ec7bSml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
47906f45ec7bSml29623 {
47916f45ec7bSml29623 	p_nxge_param_t	param_arr;
47926f45ec7bSml29623 	p_nxge_stats_t	statsp;
47936f45ec7bSml29623 	uint8_t		xcvr_portn;
47946f45ec7bSml29623 	p_mii_regs_t	mii_regs;
47956f45ec7bSml29623 	mii_bmcr_t	bmcr;
47966f45ec7bSml29623 	mii_bmsr_t	bmsr;
47976f45ec7bSml29623 	mii_anar_t	anar;
47986f45ec7bSml29623 	mii_gcr_t	gcr;
47996f45ec7bSml29623 	mii_esr_t	esr;
48006f45ec7bSml29623 	mii_aux_ctl_t	bcm5464r_aux;
48016f45ec7bSml29623 	int		status = NXGE_OK;
48026f45ec7bSml29623 
48036f45ec7bSml29623 	uint_t delay;
48046f45ec7bSml29623 
48056f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
48066f45ec7bSml29623 
48076f45ec7bSml29623 	param_arr = nxgep->param_arr;
48086f45ec7bSml29623 	statsp = nxgep->statsp;
48096f45ec7bSml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
48106f45ec7bSml29623 
48116f45ec7bSml29623 	mii_regs = NULL;
48126f45ec7bSml29623 
48136f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48146f45ec7bSml29623 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
48156f45ec7bSml29623 
48166f45ec7bSml29623 	/*
4817d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
4818d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
4819d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
4820d81011f0Ssbehera 	 */
4821d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
4822d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4823d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
4824d81011f0Ssbehera 	}
4825d81011f0Ssbehera 
4826d81011f0Ssbehera 	/*
48276f45ec7bSml29623 	 * Reset the transceiver.
48286f45ec7bSml29623 	 */
48296f45ec7bSml29623 	delay = 0;
48306f45ec7bSml29623 	bmcr.value = 0;
48316f45ec7bSml29623 	bmcr.bits.reset = 1;
48326f45ec7bSml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4833adfcba55Sjoycey #if defined(__i386)
483452ccf843Smisaki 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
4835adfcba55Sjoycey #else
483652ccf843Smisaki 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
4837adfcba55Sjoycey #endif
483852ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
48396f45ec7bSml29623 		goto fail;
48406f45ec7bSml29623 	do {
48416f45ec7bSml29623 		drv_usecwait(500);
48426f45ec7bSml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4843adfcba55Sjoycey #if defined(__i386)
484452ccf843Smisaki 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
4845adfcba55Sjoycey #else
484652ccf843Smisaki 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
4847adfcba55Sjoycey #endif
484852ccf843Smisaki 		    &bmcr.value)) != NXGE_OK)
48496f45ec7bSml29623 			goto fail;
48506f45ec7bSml29623 		delay++;
48516f45ec7bSml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
48526f45ec7bSml29623 	if (delay == 1000) {
48536f45ec7bSml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
48546f45ec7bSml29623 		goto fail;
48556f45ec7bSml29623 	}
48566f45ec7bSml29623 
48576f45ec7bSml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4858adfcba55Sjoycey #if defined(__i386)
4859adfcba55Sjoycey 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4860adfcba55Sjoycey #else
48616f45ec7bSml29623 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4862adfcba55Sjoycey #endif
48636f45ec7bSml29623 	    &bmsr.value)) != NXGE_OK)
48646f45ec7bSml29623 		goto fail;
48656f45ec7bSml29623 
48666f45ec7bSml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
48676f45ec7bSml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
48686f45ec7bSml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
48696f45ec7bSml29623 	param_arr[param_anar_100hdx].value = 0;
48706f45ec7bSml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
48716f45ec7bSml29623 	param_arr[param_anar_10hdx].value = 0;
48726f45ec7bSml29623 
48736f45ec7bSml29623 	/*
48746f45ec7bSml29623 	 * Initialize the xcvr statistics.
48756f45ec7bSml29623 	 */
48766f45ec7bSml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
48776f45ec7bSml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
48786f45ec7bSml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
48796f45ec7bSml29623 	statsp->mac_stats.cap_100hdx = 0;
48806f45ec7bSml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
48816f45ec7bSml29623 	statsp->mac_stats.cap_10hdx = 0;
48826f45ec7bSml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
48836f45ec7bSml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
48846f45ec7bSml29623 
48856f45ec7bSml29623 	/*
488600161856Syc148097 	 * Initialize the xcvr advertised capability statistics.
48876f45ec7bSml29623 	 */
48886f45ec7bSml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
48896f45ec7bSml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
48906f45ec7bSml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
48916f45ec7bSml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
48926f45ec7bSml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
48936f45ec7bSml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
48946f45ec7bSml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
48956f45ec7bSml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
48966f45ec7bSml29623 	statsp->mac_stats.adv_cap_asmpause =
48976f45ec7bSml29623 	    param_arr[param_anar_asmpause].value;
48986f45ec7bSml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
48996f45ec7bSml29623 
49006f45ec7bSml29623 
49016f45ec7bSml29623 	/*
49026f45ec7bSml29623 	 * Check for extended status just in case we're
49036f45ec7bSml29623 	 * running a Gigibit phy.
49046f45ec7bSml29623 	 */
49056f45ec7bSml29623 	if (bmsr.bits.extend_status) {
49066f45ec7bSml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4907adfcba55Sjoycey #if defined(__i386)
490852ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->esr),
4909adfcba55Sjoycey #else
491052ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->esr),
4911adfcba55Sjoycey #endif
491252ccf843Smisaki 		    &esr.value)) != NXGE_OK)
49136f45ec7bSml29623 			goto fail;
491452ccf843Smisaki 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
49156f45ec7bSml29623 		param_arr[param_anar_1000hdx].value = 0;
49166f45ec7bSml29623 
49176f45ec7bSml29623 		statsp->mac_stats.cap_1000fdx =
491852ccf843Smisaki 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
49196f45ec7bSml29623 		statsp->mac_stats.cap_1000hdx = 0;
49206f45ec7bSml29623 	} else {
49216f45ec7bSml29623 		param_arr[param_anar_1000fdx].value = 0;
49226f45ec7bSml29623 		param_arr[param_anar_1000hdx].value = 0;
49236f45ec7bSml29623 	}
49246f45ec7bSml29623 
49256f45ec7bSml29623 	/*
49266f45ec7bSml29623 	 * Initialize 1G Statistics once the capability is established.
49276f45ec7bSml29623 	 */
49286f45ec7bSml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
49296f45ec7bSml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
49306f45ec7bSml29623 
49316f45ec7bSml29623 	/*
493200161856Syc148097 	 * Initialize the link statistics.
49336f45ec7bSml29623 	 */
49346f45ec7bSml29623 	statsp->mac_stats.link_T4 = 0;
49356f45ec7bSml29623 	statsp->mac_stats.link_asmpause = 0;
49366f45ec7bSml29623 	statsp->mac_stats.link_pause = 0;
49376f45ec7bSml29623 	statsp->mac_stats.link_speed = 0;
49386f45ec7bSml29623 	statsp->mac_stats.link_duplex = 0;
49396f45ec7bSml29623 	statsp->mac_stats.link_up = 0;
49406f45ec7bSml29623 
49416f45ec7bSml29623 	/*
49426f45ec7bSml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
49436f45ec7bSml29623 	 */
49446f45ec7bSml29623 	bmcr.value = 0;
49456f45ec7bSml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4946adfcba55Sjoycey #if defined(__i386)
494752ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4948adfcba55Sjoycey #else
494952ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4950adfcba55Sjoycey #endif
495152ccf843Smisaki 	    bmcr.value)) != NXGE_OK)
49526f45ec7bSml29623 		goto fail;
49536f45ec7bSml29623 
49546f45ec7bSml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
49556f45ec7bSml29623 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
49566f45ec7bSml29623 		bmcr.bits.loopback = 1;
49576f45ec7bSml29623 		bmcr.bits.enable_autoneg = 0;
49586f45ec7bSml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
49596f45ec7bSml29623 			bmcr.bits.speed_1000_sel = 1;
49606f45ec7bSml29623 		bmcr.bits.duplex_mode = 1;
49616f45ec7bSml29623 		param_arr[param_autoneg].value = 0;
49626f45ec7bSml29623 	} else {
49636f45ec7bSml29623 		bmcr.bits.loopback = 0;
49646f45ec7bSml29623 	}
49656f45ec7bSml29623 
49666f45ec7bSml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
49676f45ec7bSml29623 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
49686f45ec7bSml29623 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
49696f45ec7bSml29623 		param_arr[param_autoneg].value = 0;
49706f45ec7bSml29623 		bcm5464r_aux.value = 0;
49716f45ec7bSml29623 		bcm5464r_aux.bits.ext_lb = 1;
49726f45ec7bSml29623 		bcm5464r_aux.bits.write_1 = 1;
49736f45ec7bSml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
497452ccf843Smisaki 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
49756f45ec7bSml29623 			goto fail;
49766f45ec7bSml29623 	}
49776f45ec7bSml29623 
497800161856Syc148097 	/* If auto-negotiation is desired */
49796f45ec7bSml29623 	if (param_arr[param_autoneg].value) {
49806f45ec7bSml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49816f45ec7bSml29623 		    "Restarting Auto-negotiation."));
49826f45ec7bSml29623 		/*
49836f45ec7bSml29623 		 * Setup our Auto-negotiation advertisement register.
49846f45ec7bSml29623 		 */
49856f45ec7bSml29623 		anar.value = 0;
49866f45ec7bSml29623 		anar.bits.selector = 1;
49876f45ec7bSml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
49886f45ec7bSml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
49896f45ec7bSml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
49906f45ec7bSml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
49916f45ec7bSml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
49926f45ec7bSml29623 		anar.bits.cap_asmpause = 0;
49936f45ec7bSml29623 		anar.bits.cap_pause = 0;
49946f45ec7bSml29623 		if (param_arr[param_anar_1000fdx].value ||
49956f45ec7bSml29623 		    param_arr[param_anar_100fdx].value ||
49966f45ec7bSml29623 		    param_arr[param_anar_10fdx].value) {
49976f45ec7bSml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
49986f45ec7bSml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
49996f45ec7bSml29623 		}
50006f45ec7bSml29623 
500100161856Syc148097 		/* Write to the auto-negotiation advertisement register */
50026f45ec7bSml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5003adfcba55Sjoycey #if defined(__i386)
500452ccf843Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->anar),
5005adfcba55Sjoycey #else
500652ccf843Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->anar),
5007adfcba55Sjoycey #endif
500852ccf843Smisaki 		    anar.value)) != NXGE_OK)
50096f45ec7bSml29623 			goto fail;
50106f45ec7bSml29623 		if (bmsr.bits.extend_status) {
50116f45ec7bSml29623 			gcr.value = 0;
50126f45ec7bSml29623 			gcr.bits.ms_mode_en =
50136f45ec7bSml29623 			    param_arr[param_master_cfg_enable].value;
50146f45ec7bSml29623 			gcr.bits.master =
50156f45ec7bSml29623 			    param_arr[param_master_cfg_value].value;
50166f45ec7bSml29623 			gcr.bits.link_1000fdx =
50176f45ec7bSml29623 			    param_arr[param_anar_1000fdx].value;
50186f45ec7bSml29623 			gcr.bits.link_1000hdx =
50196f45ec7bSml29623 			    param_arr[param_anar_1000hdx].value;
50206f45ec7bSml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
5021adfcba55Sjoycey #if defined(__i386)
502252ccf843Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
5023adfcba55Sjoycey #else
502452ccf843Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
5025adfcba55Sjoycey #endif
502652ccf843Smisaki 			    gcr.value)) != NXGE_OK)
50276f45ec7bSml29623 				goto fail;
50286f45ec7bSml29623 		}
50296f45ec7bSml29623 
50306f45ec7bSml29623 		bmcr.bits.enable_autoneg = 1;
50316f45ec7bSml29623 		bmcr.bits.restart_autoneg = 1;
50326f45ec7bSml29623 
50336f45ec7bSml29623 	} else {
50346f45ec7bSml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
50356f45ec7bSml29623 		bmcr.bits.speed_1000_sel =
50366f45ec7bSml29623 		    param_arr[param_anar_1000fdx].value |
50376f45ec7bSml29623 		    param_arr[param_anar_1000hdx].value;
50386f45ec7bSml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
50396f45ec7bSml29623 		    (param_arr[param_anar_100fdx].value |
50406f45ec7bSml29623 		    param_arr[param_anar_100hdx].value);
504100161856Syc148097 
504200161856Syc148097 		/* Force to 1G */
50436f45ec7bSml29623 		if (bmcr.bits.speed_1000_sel) {
50446f45ec7bSml29623 			statsp->mac_stats.link_speed = 1000;
50456f45ec7bSml29623 			gcr.value = 0;
50466f45ec7bSml29623 			gcr.bits.ms_mode_en =
50476f45ec7bSml29623 			    param_arr[param_master_cfg_enable].value;
50486f45ec7bSml29623 			gcr.bits.master =
50496f45ec7bSml29623 			    param_arr[param_master_cfg_value].value;
50506f45ec7bSml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
5051adfcba55Sjoycey #if defined(__i386)
5052adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
5053adfcba55Sjoycey #else
50546f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
5055adfcba55Sjoycey #endif
505652ccf843Smisaki 			    gcr.value)) != NXGE_OK)
50576f45ec7bSml29623 				goto fail;
50586f45ec7bSml29623 			if (param_arr[param_anar_1000fdx].value) {
50596f45ec7bSml29623 				bmcr.bits.duplex_mode = 1;
50606f45ec7bSml29623 				statsp->mac_stats.link_duplex = 2;
50616f45ec7bSml29623 			} else
50626f45ec7bSml29623 				statsp->mac_stats.link_duplex = 1;
506300161856Syc148097 
506400161856Syc148097 		/* Force to 100M */
50656f45ec7bSml29623 		} else if (bmcr.bits.speed_sel) {
50666f45ec7bSml29623 			statsp->mac_stats.link_speed = 100;
50676f45ec7bSml29623 			if (param_arr[param_anar_100fdx].value) {
50686f45ec7bSml29623 				bmcr.bits.duplex_mode = 1;
50696f45ec7bSml29623 				statsp->mac_stats.link_duplex = 2;
50706f45ec7bSml29623 			} else
50716f45ec7bSml29623 				statsp->mac_stats.link_duplex = 1;
507200161856Syc148097 
507300161856Syc148097 		/* Force to 10M */
50746f45ec7bSml29623 		} else {
50756f45ec7bSml29623 			statsp->mac_stats.link_speed = 10;
50766f45ec7bSml29623 			if (param_arr[param_anar_10fdx].value) {
50776f45ec7bSml29623 				bmcr.bits.duplex_mode = 1;
50786f45ec7bSml29623 				statsp->mac_stats.link_duplex = 2;
50796f45ec7bSml29623 			} else
50806f45ec7bSml29623 				statsp->mac_stats.link_duplex = 1;
50816f45ec7bSml29623 		}
50826f45ec7bSml29623 		if (statsp->mac_stats.link_duplex != 1) {
50836f45ec7bSml29623 			statsp->mac_stats.link_asmpause =
50846f45ec7bSml29623 			    statsp->mac_stats.cap_asmpause;
50856f45ec7bSml29623 			statsp->mac_stats.link_pause =
50866f45ec7bSml29623 			    statsp->mac_stats.cap_pause;
50876f45ec7bSml29623 		}
50886f45ec7bSml29623 
50896f45ec7bSml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
50906f45ec7bSml29623 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
50916f45ec7bSml29623 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
50926f45ec7bSml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
50936f45ec7bSml29623 				/* BCM5464R 1000mbps external loopback mode */
50946f45ec7bSml29623 				gcr.value = 0;
50956f45ec7bSml29623 				gcr.bits.ms_mode_en = 1;
50966f45ec7bSml29623 				gcr.bits.master = 1;
50976f45ec7bSml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
5098adfcba55Sjoycey #if defined(__i386)
5099adfcba55Sjoycey 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
5100adfcba55Sjoycey #else
51016f45ec7bSml29623 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
5102adfcba55Sjoycey #endif
510352ccf843Smisaki 				    gcr.value)) != NXGE_OK)
51046f45ec7bSml29623 					goto fail;
51056f45ec7bSml29623 				bmcr.value = 0;
51066f45ec7bSml29623 				bmcr.bits.speed_1000_sel = 1;
51076f45ec7bSml29623 				statsp->mac_stats.link_speed = 1000;
51086f45ec7bSml29623 			} else if (statsp->port_stats.lb_mode
51096f45ec7bSml29623 			    == nxge_lb_ext100) {
51106f45ec7bSml29623 				/* BCM5464R 100mbps external loopback mode */
51116f45ec7bSml29623 				bmcr.value = 0;
51126f45ec7bSml29623 				bmcr.bits.speed_sel = 1;
51136f45ec7bSml29623 				bmcr.bits.duplex_mode = 1;
51146f45ec7bSml29623 				statsp->mac_stats.link_speed = 100;
51156f45ec7bSml29623 			} else if (statsp->port_stats.lb_mode
51166f45ec7bSml29623 			    == nxge_lb_ext10) {
51176f45ec7bSml29623 				/* BCM5464R 10mbps external loopback mode */
51186f45ec7bSml29623 				bmcr.value = 0;
51196f45ec7bSml29623 				bmcr.bits.duplex_mode = 1;
51206f45ec7bSml29623 				statsp->mac_stats.link_speed = 10;
51216f45ec7bSml29623 			}
51226f45ec7bSml29623 		}
51236f45ec7bSml29623 	}
51246f45ec7bSml29623 
51256f45ec7bSml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5126adfcba55Sjoycey #if defined(__i386)
5127adfcba55Sjoycey 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5128adfcba55Sjoycey #else
51296f45ec7bSml29623 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5130adfcba55Sjoycey #endif
51316f45ec7bSml29623 	    bmcr.value)) != NXGE_OK)
51326f45ec7bSml29623 		goto fail;
51336f45ec7bSml29623 
51346f45ec7bSml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5135adfcba55Sjoycey #if defined(__i386)
513652ccf843Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5137adfcba55Sjoycey #else
513852ccf843Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5139adfcba55Sjoycey #endif
514052ccf843Smisaki 	    &bmcr.value)) != NXGE_OK)
51416f45ec7bSml29623 		goto fail;
51426f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
51436f45ec7bSml29623 
51446f45ec7bSml29623 	/*
51456f45ec7bSml29623 	 * Initialize the xcvr status kept in the context structure.
51466f45ec7bSml29623 	 */
51476f45ec7bSml29623 	nxgep->soft_bmsr.value = 0;
51486f45ec7bSml29623 
51496f45ec7bSml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5150adfcba55Sjoycey #if defined(__i386)
5151adfcba55Sjoycey 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5152adfcba55Sjoycey #else
51536f45ec7bSml29623 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5154adfcba55Sjoycey #endif
51556f45ec7bSml29623 	    &nxgep->bmsr.value)) != NXGE_OK)
51566f45ec7bSml29623 		goto fail;
51576f45ec7bSml29623 
51586f45ec7bSml29623 	statsp->mac_stats.xcvr_inits++;
51596f45ec7bSml29623 	nxgep->bmsr.value = 0;
51606f45ec7bSml29623 
51616f45ec7bSml29623 fail:
51626f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51636f45ec7bSml29623 	    "<== nxge_mii_xcvr_init status 0x%x", status));
51646f45ec7bSml29623 	return (status);
51656f45ec7bSml29623 }
51666f45ec7bSml29623 
5167d81011f0Ssbehera nxge_status_t
5168d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
5169d81011f0Ssbehera {
5170d81011f0Ssbehera 	p_nxge_param_t	param_arr;
5171d81011f0Ssbehera 	p_nxge_stats_t	statsp;
5172d81011f0Ssbehera 	uint8_t		xcvr_portn;
5173d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
5174d81011f0Ssbehera 	mii_bmcr_t	bmcr;
5175d81011f0Ssbehera 	mii_bmsr_t	bmsr;
5176d81011f0Ssbehera 	mii_gcr_t	gcr;
5177d81011f0Ssbehera 	mii_esr_t	esr;
5178d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
5179d81011f0Ssbehera 	int		status = NXGE_OK;
5180d81011f0Ssbehera 
5181d81011f0Ssbehera 	uint_t delay;
5182d81011f0Ssbehera 
5183d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
5184d81011f0Ssbehera 
5185d81011f0Ssbehera 	param_arr = nxgep->param_arr;
5186d81011f0Ssbehera 	statsp = nxgep->statsp;
5187d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
5188d81011f0Ssbehera 
5189d81011f0Ssbehera 	mii_regs = NULL;
5190d81011f0Ssbehera 
5191d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5192d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
5193d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
5194d81011f0Ssbehera 
5195d81011f0Ssbehera 	/*
5196d81011f0Ssbehera 	 * Reset the transceiver.
5197d81011f0Ssbehera 	 */
5198d81011f0Ssbehera 	delay = 0;
5199d81011f0Ssbehera 	bmcr.value = 0;
5200d81011f0Ssbehera 	bmcr.bits.reset = 1;
5201d81011f0Ssbehera 
5202d81011f0Ssbehera #if defined(__i386)
5203d81011f0Ssbehera 
5204d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5205d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5206d81011f0Ssbehera 		goto fail;
5207d81011f0Ssbehera #else
5208d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5209d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5210d81011f0Ssbehera 		goto fail;
5211d81011f0Ssbehera #endif
5212d81011f0Ssbehera 	do {
5213d81011f0Ssbehera 		drv_usecwait(500);
5214d81011f0Ssbehera #if defined(__i386)
5215d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5216d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
5217d81011f0Ssbehera 		    != NXGE_OK)
5218d81011f0Ssbehera 			goto fail;
5219d81011f0Ssbehera #else
5220d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5221d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
5222d81011f0Ssbehera 		    != NXGE_OK)
5223d81011f0Ssbehera 			goto fail;
5224d81011f0Ssbehera #endif
5225d81011f0Ssbehera 		delay++;
5226d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
5227d81011f0Ssbehera 	if (delay == 1000) {
5228d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
5229d81011f0Ssbehera 		goto fail;
5230d81011f0Ssbehera 	}
5231d81011f0Ssbehera 
5232d81011f0Ssbehera #if defined(__i386)
5233d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5234d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5235d81011f0Ssbehera 		goto fail;
5236d81011f0Ssbehera #else
5237d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5238d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
5239d81011f0Ssbehera 		goto fail;
5240d81011f0Ssbehera #endif
5241d81011f0Ssbehera 
5242d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
5243d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
5244d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
5245d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
5246d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
5247d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
5248d81011f0Ssbehera 
5249d81011f0Ssbehera 	/*
5250d81011f0Ssbehera 	 * Initialize the xcvr statistics.
5251d81011f0Ssbehera 	 */
5252d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
5253d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
5254d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
5255d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
5256d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
5257d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
5258d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
5259d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
5260d81011f0Ssbehera 
5261d81011f0Ssbehera 	/*
5262d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
5263d81011f0Ssbehera 	 */
5264d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
5265d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5266d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5267d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
5268d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
5269d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
5270d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
5271d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
5272d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
5273d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
5274d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
5275d81011f0Ssbehera 
5276d81011f0Ssbehera 	/*
5277d81011f0Ssbehera 	 * Check for extended status just in case we're
5278d81011f0Ssbehera 	 * running a Gigibit phy.
5279d81011f0Ssbehera 	 */
5280d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
5281d81011f0Ssbehera #if defined(__i386)
5282d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5283d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
5284d81011f0Ssbehera 		    NXGE_OK)
5285d81011f0Ssbehera 			goto fail;
5286d81011f0Ssbehera #else
5287d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
5288d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
5289d81011f0Ssbehera 		    NXGE_OK)
5290d81011f0Ssbehera 			goto fail;
5291d81011f0Ssbehera #endif
5292d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
5293d81011f0Ssbehera 		    esr.bits.link_1000fdx;
5294d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
5295d81011f0Ssbehera 
5296d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
5297d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
5298d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
5299d81011f0Ssbehera 	} else {
5300d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
5301d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
5302d81011f0Ssbehera 	}
5303d81011f0Ssbehera 
5304d81011f0Ssbehera 	/*
5305d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
5306d81011f0Ssbehera 	 */
5307d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
5308d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
5309d81011f0Ssbehera 
5310d81011f0Ssbehera 	/*
5311d81011f0Ssbehera 	 * Initialize the link statistics.
5312d81011f0Ssbehera 	 */
5313d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
5314d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
5315d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
5316d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
5317d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
5318d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
5319d81011f0Ssbehera 
5320d81011f0Ssbehera 	/*
5321d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
5322d81011f0Ssbehera 	 */
5323d81011f0Ssbehera 	bmcr.value = 0;
5324d81011f0Ssbehera #if defined(__i386)
5325d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5326d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5327d81011f0Ssbehera 		goto fail;
5328d81011f0Ssbehera #else
5329d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5330d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
5331d81011f0Ssbehera 		goto fail;
5332d81011f0Ssbehera #endif
5333d81011f0Ssbehera 
5334d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
5335d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
5336d81011f0Ssbehera 		bmcr.bits.loopback = 1;
5337d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
5338d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
5339d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
5340d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
5341d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
5342d81011f0Ssbehera 	} else {
5343d81011f0Ssbehera 		bmcr.bits.loopback = 0;
5344d81011f0Ssbehera 	}
5345d81011f0Ssbehera 
5346d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
5347d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
5348d81011f0Ssbehera 		bcm5464r_aux.value = 0;
5349d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
5350d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
5351d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5352d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
5353d81011f0Ssbehera 			goto fail;
5354d81011f0Ssbehera 	}
5355d81011f0Ssbehera 
5356d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
5357d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
5358d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
5359d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
5360d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
5361d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
5362d81011f0Ssbehera 
5363d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
5364d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
5365d81011f0Ssbehera 		gcr.value = 0;
5366d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
5367d81011f0Ssbehera 		gcr.bits.master = 1;
5368d81011f0Ssbehera #if defined(__i386)
5369d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5370d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
5371d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
5372d81011f0Ssbehera 			goto fail;
5373d81011f0Ssbehera #else
5374d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
5375d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
5376d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
5377d81011f0Ssbehera 			goto fail;
5378d81011f0Ssbehera #endif
5379d81011f0Ssbehera 		bmcr.value = 0;
5380d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
5381d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
5382d81011f0Ssbehera 	}
5383d81011f0Ssbehera 
5384d81011f0Ssbehera #if defined(__i386)
5385d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5386d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
5387d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
5388d81011f0Ssbehera 		goto fail;
5389d81011f0Ssbehera #else
5390d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
5391d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
5392d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
5393d81011f0Ssbehera 		goto fail;
5394d81011f0Ssbehera #endif
5395d81011f0Ssbehera 
5396d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5397d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
5398d81011f0Ssbehera 	    bmcr.value));
5399d81011f0Ssbehera 
5400d81011f0Ssbehera #if defined(__i386)
5401d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5402d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5403d81011f0Ssbehera 		goto fail;
5404d81011f0Ssbehera #else
5405d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5406d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
5407d81011f0Ssbehera 		goto fail;
5408d81011f0Ssbehera #endif
5409d81011f0Ssbehera 
5410d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5411d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
5412d81011f0Ssbehera 
5413d81011f0Ssbehera 	/*
5414d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
5415d81011f0Ssbehera 	 */
5416d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
5417d81011f0Ssbehera #if defined(__i386)
5418d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5419d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5420d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
5421d81011f0Ssbehera 		goto fail;
5422d81011f0Ssbehera #else
5423d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
5424d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5425d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
5426d81011f0Ssbehera 		goto fail;
5427d81011f0Ssbehera #endif
5428d81011f0Ssbehera 
5429d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
5430d81011f0Ssbehera 	nxgep->bmsr.value = 0;
5431d81011f0Ssbehera 
5432d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5433d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5434d81011f0Ssbehera 	return (status);
5435d81011f0Ssbehera 
5436d81011f0Ssbehera fail:
5437d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5438d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
5439d81011f0Ssbehera 	return (status);
5440d81011f0Ssbehera }
5441d81011f0Ssbehera 
54426f45ec7bSml29623 /* Read from a MII compliant register */
54436f45ec7bSml29623 
54446f45ec7bSml29623 nxge_status_t
54456f45ec7bSml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
54466f45ec7bSml29623 		uint16_t *value)
54476f45ec7bSml29623 {
54486f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
54496f45ec7bSml29623 
54506f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
54516f45ec7bSml29623 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
54526f45ec7bSml29623 
5453321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
54546f45ec7bSml29623 
5455d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5456d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
54576f45ec7bSml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
54586f45ec7bSml29623 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
54596f45ec7bSml29623 			goto fail;
54602e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
54612e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
54626f45ec7bSml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
54636f45ec7bSml29623 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
54646f45ec7bSml29623 			goto fail;
54656f45ec7bSml29623 	} else
54666f45ec7bSml29623 		goto fail;
54676f45ec7bSml29623 
5468321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
54696f45ec7bSml29623 
54706f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
547152ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
54726f45ec7bSml29623 	return (NXGE_OK);
54736f45ec7bSml29623 fail:
5474321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
54756f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
547652ccf843Smisaki 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
54776f45ec7bSml29623 
54786f45ec7bSml29623 	return (NXGE_ERROR | rs);
54796f45ec7bSml29623 }
54806f45ec7bSml29623 
54816f45ec7bSml29623 /* Write to a MII compliant Register */
54826f45ec7bSml29623 
54836f45ec7bSml29623 nxge_status_t
54846f45ec7bSml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
54856f45ec7bSml29623 		uint16_t value)
54866f45ec7bSml29623 {
54876f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
54886f45ec7bSml29623 
54896f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
549052ccf843Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
54916f45ec7bSml29623 
5492321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
54936f45ec7bSml29623 
5494d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
5495d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
54966f45ec7bSml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
54976f45ec7bSml29623 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
54986f45ec7bSml29623 			goto fail;
54992e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
55002e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
55016f45ec7bSml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
55026f45ec7bSml29623 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
55036f45ec7bSml29623 			goto fail;
55046f45ec7bSml29623 	} else
55056f45ec7bSml29623 		goto fail;
55066f45ec7bSml29623 
5507321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55086f45ec7bSml29623 
55096f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
55106f45ec7bSml29623 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
55116f45ec7bSml29623 	return (NXGE_OK);
55126f45ec7bSml29623 fail:
5513321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55146f45ec7bSml29623 
55156f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
551652ccf843Smisaki 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
55176f45ec7bSml29623 
55186f45ec7bSml29623 	return (NXGE_ERROR | rs);
55196f45ec7bSml29623 }
55206f45ec7bSml29623 
552100161856Syc148097 /*
552200161856Syc148097  * Perform write to Clause45 serdes / transceiver device
552300161856Syc148097  * Arguments:
552400161856Syc148097  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
552500161856Syc148097  *			number if nxge_mdio_write is used for accessing the
552600161856Syc148097  *			internal LSIL serdes. Otherwise PHYAD is different
552700161856Syc148097  * 			for different platforms.
552800161856Syc148097  *	device:		With each PHYAD, the driver can use MDIO to control
552900161856Syc148097  *			multiple devices inside the PHY, here "device" is an
553000161856Syc148097  *			MMD (MDIO managable device).
553100161856Syc148097  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
553200161856Syc148097  *			the register which the driver will write value to.
553300161856Syc148097  *	value:		The register value will be filled in.
553400161856Syc148097  */
55356f45ec7bSml29623 nxge_status_t
55366f45ec7bSml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
55376f45ec7bSml29623 		uint16_t xcvr_reg, uint16_t *value)
55386f45ec7bSml29623 {
55396f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
55406f45ec7bSml29623 
55416f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
55426f45ec7bSml29623 	    xcvr_portn));
55436f45ec7bSml29623 
554453560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
55456f45ec7bSml29623 
55466f45ec7bSml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
55476f45ec7bSml29623 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
55486f45ec7bSml29623 		goto fail;
55496f45ec7bSml29623 
555053560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55516f45ec7bSml29623 
55526f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
55536f45ec7bSml29623 	    xcvr_portn));
55546f45ec7bSml29623 	return (NXGE_OK);
55556f45ec7bSml29623 fail:
555653560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55576f45ec7bSml29623 
55586f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
555952ccf843Smisaki 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
55606f45ec7bSml29623 
55616f45ec7bSml29623 	return (NXGE_ERROR | rs);
55626f45ec7bSml29623 }
55636f45ec7bSml29623 
55646f45ec7bSml29623 /* Perform write to Clause45 serdes / transceiver device */
55656f45ec7bSml29623 
55666f45ec7bSml29623 nxge_status_t
55676f45ec7bSml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
55686f45ec7bSml29623 		uint16_t xcvr_reg, uint16_t value)
55696f45ec7bSml29623 {
55706f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
55716f45ec7bSml29623 
55726f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
55736f45ec7bSml29623 	    xcvr_portn));
55746f45ec7bSml29623 
557553560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
55766f45ec7bSml29623 
55776f45ec7bSml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
55786f45ec7bSml29623 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
55796f45ec7bSml29623 		goto fail;
55806f45ec7bSml29623 
558153560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55826f45ec7bSml29623 
55836f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
55846f45ec7bSml29623 	    xcvr_portn));
55856f45ec7bSml29623 	return (NXGE_OK);
55866f45ec7bSml29623 fail:
558753560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
55886f45ec7bSml29623 
55896f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
559052ccf843Smisaki 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
55916f45ec7bSml29623 
55926f45ec7bSml29623 	return (NXGE_ERROR | rs);
55936f45ec7bSml29623 }
55946f45ec7bSml29623 
55956f45ec7bSml29623 
55966f45ec7bSml29623 /* Check MII to see if there is any link status change */
55976f45ec7bSml29623 
55986f45ec7bSml29623 nxge_status_t
55996f45ec7bSml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
56006f45ec7bSml29623 		nxge_link_state_t *link_up)
56016f45ec7bSml29623 {
56026f45ec7bSml29623 	p_nxge_param_t	param_arr;
56036f45ec7bSml29623 	p_nxge_stats_t	statsp;
56046f45ec7bSml29623 	p_mii_regs_t	mii_regs;
56056f45ec7bSml29623 	p_mii_bmsr_t	soft_bmsr;
56066f45ec7bSml29623 	mii_anar_t	anar;
56076f45ec7bSml29623 	mii_anlpar_t	anlpar;
56086f45ec7bSml29623 	mii_anar_t	an_common;
56096f45ec7bSml29623 	mii_aner_t	aner;
56106f45ec7bSml29623 	mii_gsr_t	gsr;
56116f45ec7bSml29623 	nxge_status_t	status = NXGE_OK;
56126f45ec7bSml29623 
56136f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
56146f45ec7bSml29623 
56156f45ec7bSml29623 	mii_regs = NULL;
56166f45ec7bSml29623 	param_arr = nxgep->param_arr;
56176f45ec7bSml29623 	statsp = nxgep->statsp;
56186f45ec7bSml29623 	soft_bmsr = &nxgep->soft_bmsr;
56196f45ec7bSml29623 	*link_up = LINK_NO_CHANGE;
56206f45ec7bSml29623 
5621d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5622d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
5623d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
5624d81011f0Ssbehera 
56256f45ec7bSml29623 	if (bmsr_ints.bits.link_status) {
5626d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5627d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
5628d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
56296f45ec7bSml29623 		if (bmsr.bits.link_status) {
56306f45ec7bSml29623 			soft_bmsr->bits.link_status = 1;
5631d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5632d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
5633d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
56346f45ec7bSml29623 		} else {
5635774da109Stc99174@train 			/* Only status change will update *link_up */
5636774da109Stc99174@train 			if (statsp->mac_stats.link_up == 1) {
5637774da109Stc99174@train 				*link_up = LINK_IS_DOWN;
5638774da109Stc99174@train 				/* Will notify, turn off further msg */
5639774da109Stc99174@train 				nxgep->link_notify = B_FALSE;
5640774da109Stc99174@train 			}
56416f45ec7bSml29623 			statsp->mac_stats.link_up = 0;
56426f45ec7bSml29623 			soft_bmsr->bits.link_status = 0;
56436f45ec7bSml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
56446f45ec7bSml29623 			    "Link down cable problem"));
56456f45ec7bSml29623 		}
56466f45ec7bSml29623 	}
56476f45ec7bSml29623 
5648d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
5649d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
56506f45ec7bSml29623 		if (bmsr_ints.bits.auto_neg_complete) {
56516f45ec7bSml29623 			if (bmsr.bits.auto_neg_complete)
56526f45ec7bSml29623 				soft_bmsr->bits.auto_neg_complete = 1;
56536f45ec7bSml29623 			else
56546f45ec7bSml29623 				soft_bmsr->bits.auto_neg_complete = 0;
56556f45ec7bSml29623 		}
56566f45ec7bSml29623 		if (soft_bmsr->bits.link_status == 0) {
56576f45ec7bSml29623 			statsp->mac_stats.link_T4 = 0;
56586f45ec7bSml29623 			statsp->mac_stats.link_speed = 0;
56596f45ec7bSml29623 			statsp->mac_stats.link_duplex = 0;
56606f45ec7bSml29623 			statsp->mac_stats.link_asmpause = 0;
56616f45ec7bSml29623 			statsp->mac_stats.link_pause = 0;
56626f45ec7bSml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
56636f45ec7bSml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
56646f45ec7bSml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
56656f45ec7bSml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
56666f45ec7bSml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
56676f45ec7bSml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
56686f45ec7bSml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
56696f45ec7bSml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
56706f45ec7bSml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
56716f45ec7bSml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
56726f45ec7bSml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
56736f45ec7bSml29623 			statsp->mac_stats.lp_cap_pause = 0;
56746f45ec7bSml29623 		}
56756f45ec7bSml29623 	} else
56766f45ec7bSml29623 		soft_bmsr->bits.auto_neg_complete = 1;
56776f45ec7bSml29623 
56786f45ec7bSml29623 	if ((bmsr_ints.bits.link_status ||
56796f45ec7bSml29623 	    bmsr_ints.bits.auto_neg_complete) &&
56806f45ec7bSml29623 	    soft_bmsr->bits.link_status &&
56816f45ec7bSml29623 	    soft_bmsr->bits.auto_neg_complete) {
5682774da109Stc99174@train 		if (statsp->mac_stats.link_up == 0) {
5683774da109Stc99174@train 			*link_up = LINK_IS_UP;
5684774da109Stc99174@train 			nxgep->link_notify = B_FALSE;
5685774da109Stc99174@train 		}
56866f45ec7bSml29623 		statsp->mac_stats.link_up = 1;
5687d81011f0Ssbehera 
5688d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5689d81011f0Ssbehera 		    "==> nxge_mii_check "
5690d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
5691d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
5692d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
5693d81011f0Ssbehera 
5694d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
5695d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
56966f45ec7bSml29623 			if ((status = nxge_mii_read(nxgep,
56976f45ec7bSml29623 			    statsp->mac_stats.xcvr_portn,
5698adfcba55Sjoycey #if defined(__i386)
5699adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->anar),
5700adfcba55Sjoycey #else
57016f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->anar),
5702adfcba55Sjoycey #endif
57036f45ec7bSml29623 			    &anar.value)) != NXGE_OK)
57046f45ec7bSml29623 				goto fail;
57056f45ec7bSml29623 			if ((status = nxge_mii_read(nxgep,
57066f45ec7bSml29623 			    statsp->mac_stats.xcvr_portn,
5707adfcba55Sjoycey #if defined(__i386)
5708adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
5709adfcba55Sjoycey #else
57106f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
5711adfcba55Sjoycey #endif
57126f45ec7bSml29623 			    &anlpar.value)) != NXGE_OK)
57136f45ec7bSml29623 				goto fail;
57146f45ec7bSml29623 			if ((status = nxge_mii_read(nxgep,
57156f45ec7bSml29623 			    statsp->mac_stats.xcvr_portn,
5716adfcba55Sjoycey #if defined(__i386)
5717adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->aner),
5718adfcba55Sjoycey #else
57196f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->aner),
5720adfcba55Sjoycey #endif
57216f45ec7bSml29623 			    &aner.value)) != NXGE_OK)
57226f45ec7bSml29623 				goto fail;
57236f45ec7bSml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
57246f45ec7bSml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
57256f45ec7bSml29623 			statsp->mac_stats.lp_cap_100fdx =
57266f45ec7bSml29623 			    anlpar.bits.cap_100fdx;
57276f45ec7bSml29623 			statsp->mac_stats.lp_cap_100hdx =
57286f45ec7bSml29623 			    anlpar.bits.cap_100hdx;
57296f45ec7bSml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
57306f45ec7bSml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
57316f45ec7bSml29623 			statsp->mac_stats.lp_cap_asmpause =
57326f45ec7bSml29623 			    anlpar.bits.cap_asmpause;
57336f45ec7bSml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
57346f45ec7bSml29623 			an_common.value = anar.value & anlpar.value;
57356f45ec7bSml29623 			if (param_arr[param_anar_1000fdx].value ||
57366f45ec7bSml29623 			    param_arr[param_anar_1000hdx].value) {
57376f45ec7bSml29623 				if ((status = nxge_mii_read(nxgep,
57386f45ec7bSml29623 				    statsp->mac_stats.xcvr_portn,
5739adfcba55Sjoycey #if defined(__i386)
5740adfcba55Sjoycey 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
5741adfcba55Sjoycey #else
57426f45ec7bSml29623 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
5743adfcba55Sjoycey #endif
574452ccf843Smisaki 				    &gsr.value)) != NXGE_OK)
57456f45ec7bSml29623 					goto fail;
57466f45ec7bSml29623 				statsp->mac_stats.lp_cap_1000fdx =
57476f45ec7bSml29623 				    gsr.bits.link_1000fdx;
57486f45ec7bSml29623 				statsp->mac_stats.lp_cap_1000hdx =
57496f45ec7bSml29623 				    gsr.bits.link_1000hdx;
57506f45ec7bSml29623 				if (param_arr[param_anar_1000fdx].value &&
57516f45ec7bSml29623 				    gsr.bits.link_1000fdx) {
57526f45ec7bSml29623 					statsp->mac_stats.link_speed = 1000;
57536f45ec7bSml29623 					statsp->mac_stats.link_duplex = 2;
57546f45ec7bSml29623 				} else if (
57556f45ec7bSml29623 				    param_arr[param_anar_1000hdx].value &&
57566f45ec7bSml29623 				    gsr.bits.link_1000hdx) {
57576f45ec7bSml29623 					statsp->mac_stats.link_speed = 1000;
57586f45ec7bSml29623 					statsp->mac_stats.link_duplex = 1;
57596f45ec7bSml29623 				}
57606f45ec7bSml29623 			}
57616f45ec7bSml29623 			if ((an_common.value != 0) &&
57626f45ec7bSml29623 			    !(statsp->mac_stats.link_speed)) {
57636f45ec7bSml29623 				if (an_common.bits.cap_100T4) {
57646f45ec7bSml29623 					statsp->mac_stats.link_T4 = 1;
57656f45ec7bSml29623 					statsp->mac_stats.link_speed = 100;
57666f45ec7bSml29623 					statsp->mac_stats.link_duplex = 1;
57676f45ec7bSml29623 				} else if (an_common.bits.cap_100fdx) {
57686f45ec7bSml29623 					statsp->mac_stats.link_speed = 100;
57696f45ec7bSml29623 					statsp->mac_stats.link_duplex = 2;
57706f45ec7bSml29623 				} else if (an_common.bits.cap_100hdx) {
57716f45ec7bSml29623 					statsp->mac_stats.link_speed = 100;
57726f45ec7bSml29623 					statsp->mac_stats.link_duplex = 1;
57736f45ec7bSml29623 				} else if (an_common.bits.cap_10fdx) {
57746f45ec7bSml29623 					statsp->mac_stats.link_speed = 10;
57756f45ec7bSml29623 					statsp->mac_stats.link_duplex = 2;
57766f45ec7bSml29623 				} else if (an_common.bits.cap_10hdx) {
57776f45ec7bSml29623 					statsp->mac_stats.link_speed = 10;
57786f45ec7bSml29623 					statsp->mac_stats.link_duplex = 1;
57796f45ec7bSml29623 				} else {
57806f45ec7bSml29623 					goto fail;
57816f45ec7bSml29623 				}
57826f45ec7bSml29623 			}
57836f45ec7bSml29623 			if (statsp->mac_stats.link_duplex != 1) {
578452ccf843Smisaki 				int	link_pause;
578552ccf843Smisaki 				int	cp, lcp;
578652ccf843Smisaki 
57876f45ec7bSml29623 				statsp->mac_stats.link_asmpause =
57886f45ec7bSml29623 				    an_common.bits.cap_asmpause;
578952ccf843Smisaki 				cp = statsp->mac_stats.cap_pause;
579052ccf843Smisaki 				lcp = statsp->mac_stats.lp_cap_pause;
579152ccf843Smisaki 				if (statsp->mac_stats.link_asmpause) {
579252ccf843Smisaki 					if ((cp == 0) && (lcp == 1)) {
579352ccf843Smisaki 						link_pause = 0;
579452ccf843Smisaki 					} else {
579552ccf843Smisaki 						link_pause = 1;
579652ccf843Smisaki 					}
579752ccf843Smisaki 				} else {
579852ccf843Smisaki 					link_pause = an_common.bits.cap_pause;
579952ccf843Smisaki 				}
580052ccf843Smisaki 				statsp->mac_stats.link_pause = link_pause;
58016f45ec7bSml29623 			}
5802d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
5803d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
5804d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
58056f45ec7bSml29623 		}
58066f45ec7bSml29623 	}
5807774da109Stc99174@train 	/* Initial link_notify, delay link down msg */
5808774da109Stc99174@train 	if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
5809774da109Stc99174@train 	    (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) {
58106f45ec7bSml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
58116f45ec7bSml29623 		    LINK_IS_DOWN);
58126f45ec7bSml29623 		nxgep->link_notify = B_FALSE;
58136f45ec7bSml29623 	}
58146f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
58156f45ec7bSml29623 	return (NXGE_OK);
58166f45ec7bSml29623 fail:
58176f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
58186f45ec7bSml29623 	    "nxge_mii_check: Unable to check MII"));
58196f45ec7bSml29623 	return (status);
58206f45ec7bSml29623 }
58216f45ec7bSml29623 
582200161856Syc148097 /*
582300161856Syc148097  * Check PCS to see if there is any link status change.
582400161856Syc148097  * This function is called by PORT_1G_SERDES only.
582500161856Syc148097  */
582600161856Syc148097 void
58272e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
58282e59129aSraghus {
58292e59129aSraghus 	p_nxge_stats_t	statsp;
58302e59129aSraghus 	boolean_t	linkup;
58312e59129aSraghus 
58322e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
58332e59129aSraghus 
58342e59129aSraghus 	statsp = nxgep->statsp;
58352e59129aSraghus 	*link_up = LINK_NO_CHANGE;
58362e59129aSraghus 
58372e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
58382e59129aSraghus 	if (linkup) {
5839774da109Stc99174@train 		if ((nxgep->link_notify &&
5840774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
58412e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
58422e59129aSraghus 			statsp->mac_stats.link_up = 1;
58432e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
58442e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
58452e59129aSraghus 			*link_up = LINK_IS_UP;
58462e59129aSraghus 			nxgep->link_notify = B_FALSE;
58472e59129aSraghus 		}
58482e59129aSraghus 	} else {
5849774da109Stc99174@train 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
5850774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
58512e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
58522e59129aSraghus 			statsp->mac_stats.link_up = 0;
58532e59129aSraghus 			statsp->mac_stats.link_speed = 0;
58542e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
58552e59129aSraghus 			*link_up = LINK_IS_DOWN;
58562e59129aSraghus 			nxgep->link_notify = B_FALSE;
58572e59129aSraghus 		}
58582e59129aSraghus 	}
58592e59129aSraghus 
58602e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
58612e59129aSraghus }
58622e59129aSraghus 
58636f45ec7bSml29623 /* Add a multicast address entry into the HW hash table */
58646f45ec7bSml29623 
58656f45ec7bSml29623 nxge_status_t
58666f45ec7bSml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
58676f45ec7bSml29623 {
58686f45ec7bSml29623 	uint32_t mchash;
58696f45ec7bSml29623 	p_hash_filter_t hash_filter;
58706f45ec7bSml29623 	uint16_t hash_bit;
58716f45ec7bSml29623 	uint_t j;
58726f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
58730dc2366fSVenugopal Iyer 	npi_status_t rs;
58746f45ec7bSml29623 
58756f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
58766f45ec7bSml29623 
58776f45ec7bSml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
58786f45ec7bSml29623 	mchash = crc32_mchash(addrp);
58796f45ec7bSml29623 	if (nxgep->hash_filter == NULL) {
58806f45ec7bSml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
58816f45ec7bSml29623 		    "Allocating hash filter storage."));
58826f45ec7bSml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
58836f45ec7bSml29623 		    KM_SLEEP);
58846f45ec7bSml29623 	}
58850dc2366fSVenugopal Iyer 
58866f45ec7bSml29623 	hash_filter = nxgep->hash_filter;
58876f45ec7bSml29623 	j = mchash / HASH_REG_WIDTH;
58886f45ec7bSml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
58896f45ec7bSml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
58906f45ec7bSml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
58916f45ec7bSml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
58926f45ec7bSml29623 		hash_filter->hash_ref_cnt++;
58936f45ec7bSml29623 	}
58940dc2366fSVenugopal Iyer 
58950dc2366fSVenugopal Iyer 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
58960dc2366fSVenugopal Iyer 	if (rs != NPI_SUCCESS)
58976f45ec7bSml29623 		goto fail;
58986f45ec7bSml29623 
58996f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
59006f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
59016f45ec7bSml29623 	return (NXGE_OK);
59026f45ec7bSml29623 fail:
59036f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
59046f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
59056f45ec7bSml29623 	    "Unable to add multicast address"));
59066f45ec7bSml29623 	return (status);
59076f45ec7bSml29623 }
59086f45ec7bSml29623 
59096f45ec7bSml29623 /* Remove a multicast address entry from the HW hash table */
59106f45ec7bSml29623 
59116f45ec7bSml29623 nxge_status_t
59126f45ec7bSml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
59136f45ec7bSml29623 {
59146f45ec7bSml29623 	uint32_t mchash;
59156f45ec7bSml29623 	p_hash_filter_t hash_filter;
59166f45ec7bSml29623 	uint16_t hash_bit;
59176f45ec7bSml29623 	uint_t j;
59186f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
59190dc2366fSVenugopal Iyer 	npi_status_t rs;
59206f45ec7bSml29623 
59216f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
59226f45ec7bSml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
59236f45ec7bSml29623 	mchash = crc32_mchash(addrp);
59246f45ec7bSml29623 	if (nxgep->hash_filter == NULL) {
59256f45ec7bSml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
59266f45ec7bSml29623 		    "Hash filter already de_allocated."));
59276f45ec7bSml29623 		RW_EXIT(&nxgep->filter_lock);
59286f45ec7bSml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
59296f45ec7bSml29623 		return (NXGE_OK);
59306f45ec7bSml29623 	}
59316f45ec7bSml29623 	hash_filter = nxgep->hash_filter;
59326f45ec7bSml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
59336f45ec7bSml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
59346f45ec7bSml29623 		j = mchash / HASH_REG_WIDTH;
59356f45ec7bSml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
59366f45ec7bSml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
59376f45ec7bSml29623 		hash_filter->hash_ref_cnt--;
59386f45ec7bSml29623 	}
59390dc2366fSVenugopal Iyer 
59406f45ec7bSml29623 	if (hash_filter->hash_ref_cnt == 0) {
59416f45ec7bSml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
59426f45ec7bSml29623 		    "De-allocating hash filter storage."));
59436f45ec7bSml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
59446f45ec7bSml29623 		nxgep->hash_filter = NULL;
59456f45ec7bSml29623 	}
59466f45ec7bSml29623 
59470dc2366fSVenugopal Iyer 	rs = nxge_rx_mac_mcast_hash_table(nxgep);
59480dc2366fSVenugopal Iyer 	if (rs != NPI_SUCCESS)
59496f45ec7bSml29623 		goto fail;
59500dc2366fSVenugopal Iyer 
59516f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
59526f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
59536f45ec7bSml29623 
59546f45ec7bSml29623 	return (NXGE_OK);
59556f45ec7bSml29623 fail:
59566f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
59576f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
59586f45ec7bSml29623 	    "Unable to remove multicast address"));
59596f45ec7bSml29623 
59606f45ec7bSml29623 	return (status);
59616f45ec7bSml29623 }
59626f45ec7bSml29623 
59636f45ec7bSml29623 /* Set MAC address into MAC address HW registers */
59646f45ec7bSml29623 
59656f45ec7bSml29623 nxge_status_t
59666f45ec7bSml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
59676f45ec7bSml29623 {
59686f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
59696f45ec7bSml29623 
59706f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
59716f45ec7bSml29623 
59726f45ec7bSml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
59736f45ec7bSml29623 	/*
59746f45ec7bSml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
59756f45ec7bSml29623 	 */
59766f45ec7bSml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
59776f45ec7bSml29623 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
59786f45ec7bSml29623 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
59796f45ec7bSml29623 		goto nxge_set_mac_addr_exit;
59806f45ec7bSml29623 	}
59816f45ec7bSml29623 	nxgep->ouraddr = *addrp;
59826f45ec7bSml29623 	/*
59836f45ec7bSml29623 	 * Set new interface local address and re-init device.
59846f45ec7bSml29623 	 * This is destructive to any other streams attached
59856f45ec7bSml29623 	 * to this device.
59866f45ec7bSml29623 	 */
59876f45ec7bSml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
59886f45ec7bSml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
59896f45ec7bSml29623 		goto fail;
59906f45ec7bSml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
59916f45ec7bSml29623 		goto fail;
59926f45ec7bSml29623 
59936f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
59946f45ec7bSml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
59956f45ec7bSml29623 	goto nxge_set_mac_addr_end;
59966f45ec7bSml29623 nxge_set_mac_addr_exit:
59976f45ec7bSml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
59986f45ec7bSml29623 nxge_set_mac_addr_end:
59996f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
60006f45ec7bSml29623 
60016f45ec7bSml29623 	return (NXGE_OK);
60026f45ec7bSml29623 fail:
60036f45ec7bSml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
60046f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
60056f45ec7bSml29623 	    "Unable to set mac address"));
60066f45ec7bSml29623 	return (status);
60076f45ec7bSml29623 }
60086f45ec7bSml29623 
600998ecde52Stm144005 static
601098ecde52Stm144005 check_link_state_t
601100161856Syc148097 nxge_check_link_stop(nxge_t *nxge)
601298ecde52Stm144005 {
601398ecde52Stm144005 	/* If the poll has been cancelled, return STOP. */
601498ecde52Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
601598ecde52Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
601698ecde52Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
601798ecde52Stm144005 		nxge->nxge_link_poll_timerid = 0;
601898ecde52Stm144005 		cv_broadcast(&nxge->poll_cv);
601998ecde52Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
602098ecde52Stm144005 
602198ecde52Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
602298ecde52Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
602398ecde52Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
602498ecde52Stm144005 		    nxge->mac.portnum));
602598ecde52Stm144005 		return (CHECK_LINK_STOP);
602698ecde52Stm144005 	}
602798ecde52Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
602898ecde52Stm144005 
602998ecde52Stm144005 	return (CHECK_LINK_RESCHEDULE);
603098ecde52Stm144005 }
603198ecde52Stm144005 
603200161856Syc148097 /*
603300161856Syc148097  * Check status of MII (MIF or PCS) link.
603400161856Syc148097  * This function is called once per second, that is because this function
603500161856Syc148097  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
603600161856Syc148097  * call this function recursively.
603700161856Syc148097  */
603859ac0c16Sdavemq static nxge_status_t
60396f45ec7bSml29623 nxge_check_mii_link(p_nxge_t nxgep)
60406f45ec7bSml29623 {
60416f45ec7bSml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
60426f45ec7bSml29623 	mii_anlpar_t anlpar;
60436f45ec7bSml29623 	mii_gsr_t gsr;
60446f45ec7bSml29623 	p_mii_regs_t mii_regs;
60456f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
60466f45ec7bSml29623 	uint8_t portn;
60476f45ec7bSml29623 	nxge_link_state_t link_up;
60486f45ec7bSml29623 
604998ecde52Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
605098ecde52Stm144005 		return (NXGE_ERROR);
605198ecde52Stm144005 
605298ecde52Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
605398ecde52Stm144005 		return (NXGE_OK);
605498ecde52Stm144005 
60556f45ec7bSml29623 	portn = nxgep->mac.portnum;
60566f45ec7bSml29623 
60576f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
60586f45ec7bSml29623 	    portn));
60596f45ec7bSml29623 
60606f45ec7bSml29623 	mii_regs = NULL;
60616f45ec7bSml29623 
60626f45ec7bSml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
60636f45ec7bSml29623 
60646f45ec7bSml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
60656f45ec7bSml29623 		goto nxge_check_mii_link_exit;
60666f45ec7bSml29623 
60672e59129aSraghus 	switch (nxgep->mac.portmode) {
60682e59129aSraghus 	default:
6069d81011f0Ssbehera 		bmsr_data.value = 0;
60702e59129aSraghus 		if ((status = nxge_mii_read(nxgep,
60712e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
6072adfcba55Sjoycey #if defined(__i386)
6073adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
6074adfcba55Sjoycey #else
60756f45ec7bSml29623 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
6076adfcba55Sjoycey #endif
60772e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
60786f45ec7bSml29623 			goto fail;
60792e59129aSraghus 		}
60806f45ec7bSml29623 
6081d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6082d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
6083d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
60842d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
6085d81011f0Ssbehera 
60866f45ec7bSml29623 		if (nxgep->param_arr[param_autoneg].value) {
60876f45ec7bSml29623 			if ((status = nxge_mii_read(nxgep,
60886f45ec7bSml29623 			    nxgep->statsp->mac_stats.xcvr_portn,
6089adfcba55Sjoycey #if defined(__i386)
6090adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
6091adfcba55Sjoycey #else
60926f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
6093adfcba55Sjoycey #endif
60946f45ec7bSml29623 			    &gsr.value)) != NXGE_OK)
60956f45ec7bSml29623 				goto fail;
60966f45ec7bSml29623 			if ((status = nxge_mii_read(nxgep,
60976f45ec7bSml29623 			    nxgep->statsp->mac_stats.xcvr_portn,
6098adfcba55Sjoycey #if defined(__i386)
6099adfcba55Sjoycey 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
6100adfcba55Sjoycey #else
61016f45ec7bSml29623 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
6102adfcba55Sjoycey #endif
61036f45ec7bSml29623 			    &anlpar.value)) != NXGE_OK)
61046f45ec7bSml29623 				goto fail;
6105d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
6106d81011f0Ssbehera 
61076f45ec7bSml29623 				if (nxgep->statsp->mac_stats.link_up &&
61086f45ec7bSml29623 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
61096f45ec7bSml29623 				    gsr.bits.link_1000fdx) ||
61106f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
61116f45ec7bSml29623 				    gsr.bits.link_1000hdx) ||
61126f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
61136f45ec7bSml29623 				    anlpar.bits.cap_100T4) ||
61146f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
61156f45ec7bSml29623 				    anlpar.bits.cap_100fdx) ||
61166f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
61176f45ec7bSml29623 				    anlpar.bits.cap_100hdx) ||
61186f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
61196f45ec7bSml29623 				    anlpar.bits.cap_10fdx) ||
61206f45ec7bSml29623 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
61216f45ec7bSml29623 				    anlpar.bits.cap_10hdx))) {
61226f45ec7bSml29623 					bmsr_data.bits.link_status = 0;
61236f45ec7bSml29623 				}
61246f45ec7bSml29623 			}
6125d81011f0Ssbehera 		}
61266f45ec7bSml29623 
61276f45ec7bSml29623 		/* Workaround for link down issue */
61286f45ec7bSml29623 		if (bmsr_data.value == 0) {
61292e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
61306f45ec7bSml29623 			goto nxge_check_mii_link_exit;
61316f45ec7bSml29623 		}
61326f45ec7bSml29623 
6133d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6134d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
6135d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
61362d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
6137d81011f0Ssbehera 
61386f45ec7bSml29623 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
61396f45ec7bSml29623 		nxgep->bmsr.value = bmsr_data.value;
6140d81011f0Ssbehera 
6141d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6142d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
6143d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
61442d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
6145d81011f0Ssbehera 
61462e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
61472e59129aSraghus 		    &link_up)) != NXGE_OK) {
61486f45ec7bSml29623 			goto fail;
61492e59129aSraghus 		}
61502e59129aSraghus 		break;
61512e59129aSraghus 
61522e59129aSraghus 	case PORT_1G_SERDES:
615300161856Syc148097 		/*
615400161856Syc148097 		 * Above default is for all cases except PORT_1G_SERDES.
615500161856Syc148097 		 * The default case gets information from the PHY, but a
615600161856Syc148097 		 * nxge whose portmode equals PORT_1G_SERDES does not
615700161856Syc148097 		 * have a PHY.
615800161856Syc148097 		 */
61592e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61602e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
616100161856Syc148097 		nxge_pcs_check(nxgep, portn, &link_up);
61622e59129aSraghus 		break;
61632e59129aSraghus 	}
61646f45ec7bSml29623 
61656f45ec7bSml29623 nxge_check_mii_link_exit:
61666f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
61676f45ec7bSml29623 	if (link_up == LINK_IS_UP) {
61686f45ec7bSml29623 		nxge_link_is_up(nxgep);
61696f45ec7bSml29623 	} else if (link_up == LINK_IS_DOWN) {
61706f45ec7bSml29623 		nxge_link_is_down(nxgep);
61716f45ec7bSml29623 	}
61726f45ec7bSml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
61736f45ec7bSml29623 
61746f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
61756f45ec7bSml29623 	    portn));
61766f45ec7bSml29623 	return (NXGE_OK);
61776f45ec7bSml29623 
61786f45ec7bSml29623 fail:
61796f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
61806f45ec7bSml29623 
61816f45ec7bSml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
61826f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
618352ccf843Smisaki 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
61846f45ec7bSml29623 	return (status);
61856f45ec7bSml29623 }
61866f45ec7bSml29623 
61876f45ec7bSml29623 /*ARGSUSED*/
618859ac0c16Sdavemq static nxge_status_t
61896f45ec7bSml29623 nxge_check_10g_link(p_nxge_t nxgep)
61906f45ec7bSml29623 {
61916f45ec7bSml29623 	uint8_t		portn;
61926f45ec7bSml29623 	nxge_status_t	status = NXGE_OK;
6193763fcc44Ssbehera 	boolean_t	link_up;
61942e59129aSraghus 	uint32_t	val;
61952e59129aSraghus 	npi_status_t	rs;
61966f45ec7bSml29623 
619798ecde52Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
619898ecde52Stm144005 		return (NXGE_ERROR);
619998ecde52Stm144005 
620098ecde52Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
620198ecde52Stm144005 		return (NXGE_OK);
620298ecde52Stm144005 
62036f45ec7bSml29623 	portn = nxgep->mac.portnum;
6204d81011f0Ssbehera 	val = 0;
6205d81011f0Ssbehera 	rs = NPI_SUCCESS;
62066f45ec7bSml29623 
62076f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
62086f45ec7bSml29623 	    portn));
62096f45ec7bSml29623 
62102e59129aSraghus 	switch (nxgep->mac.portmode) {
62112e59129aSraghus 	default:
62122d17280bSsbehera 		/*
62132d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
62142d17280bSsbehera 		 */
62152d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
62162d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
62172d17280bSsbehera 
621889282175SSantwona Behera 			if (nxge_hswap_phy_present(nxgep, portn))
62192d17280bSsbehera 				phy_present_now = B_TRUE;
62202d17280bSsbehera 
62211c7408c9Stc99174@train 			/* Check back-to-back XAUI connect to detect Opus NEM */
62221c7408c9Stc99174@train 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
62231c7408c9Stc99174@train 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
62241c7408c9Stc99174@train 			if (rs != 0)
62251c7408c9Stc99174@train 				goto fail;
62261c7408c9Stc99174@train 
62271c7408c9Stc99174@train 			link_up = B_FALSE;
62281c7408c9Stc99174@train 			if (val & XPCS_STATUS_LANE_ALIGN) {
62291c7408c9Stc99174@train 				link_up = B_TRUE;
62301c7408c9Stc99174@train 			}
62311c7408c9Stc99174@train 
62322d17280bSsbehera 			if (nxgep->phy_absent) {
62332d17280bSsbehera 				if (phy_present_now) {
62342d17280bSsbehera 				/*
62352d17280bSsbehera 				 * Detect, Initialize phy and do link up
62362d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
62372d17280bSsbehera 				 */
62382d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62392d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
62402d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
62412d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
62422d17280bSsbehera 					(void) nxge_link_init(nxgep);
62432d17280bSsbehera 					if (!(nxgep->drv_state &
62442d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
62452d17280bSsbehera 						status = nxge_init(nxgep);
62462d17280bSsbehera 						if (status != NXGE_OK) {
62472d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
62482d17280bSsbehera 							    NXGE_ERR_CTL,
62492d17280bSsbehera 							    "Hot swappable "
62502d17280bSsbehera 							    "phy present, but"
62512d17280bSsbehera 							    " driver init"
62522d17280bSsbehera 							    "  failed..."));
62532d17280bSsbehera 							goto fail;
62542d17280bSsbehera 						}
62552d17280bSsbehera 					}
62561c7408c9Stc99174@train 				} else if (link_up) { /* XAUI linkup, no PHY */
62571c7408c9Stc99174@train 					/*
62581c7408c9Stc99174@train 					 * This is the back-to-back XAUI
62591c7408c9Stc99174@train 					 * connect case for Opus NEM.
62601c7408c9Stc99174@train 					 */
62611c7408c9Stc99174@train 					nxgep->statsp->mac_stats.xcvr_inuse =
62621c7408c9Stc99174@train 					    XPCS_XCVR;
62631c7408c9Stc99174@train 					nxgep->mac.portmode = PORT_10G_SERDES;
62641c7408c9Stc99174@train 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62651c7408c9Stc99174@train 					    "HSP 10G Serdes DETECTED!!"));
62661c7408c9Stc99174@train 					break;
62672d17280bSsbehera 				}
62682d17280bSsbehera 
6269774da109Stc99174@train 				if (nxgep->link_notify &&
6270774da109Stc99174@train 				    nxgep->link_check_count > 3 &&
6271774da109Stc99174@train 				    nxgep->nxge_mac_state == NXGE_MAC_STARTED ||
6272774da109Stc99174@train 				    nxgep->statsp->mac_stats.link_up == 1) {
6273774da109Stc99174@train 					nxgep->statsp->mac_stats.link_up = 0;
6274774da109Stc99174@train 					nxgep->statsp->mac_stats.link_speed = 0;
6275774da109Stc99174@train 					nxgep->statsp->mac_stats.link_duplex =
6276774da109Stc99174@train 					    0;
6277774da109Stc99174@train 
6278774da109Stc99174@train 					nxge_link_is_down(nxgep);
6279774da109Stc99174@train 					nxgep->link_notify = B_FALSE;
6280774da109Stc99174@train 				}
6281774da109Stc99174@train 
62822d17280bSsbehera 				goto start_link_check;
62832d17280bSsbehera 
62842d17280bSsbehera 			} else if (!phy_present_now) {
62852d17280bSsbehera 				/*
62862d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
62872d17280bSsbehera 				 */
62882d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62892d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
62902d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
62912d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
62922d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
62932d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
62942d17280bSsbehera 				nxge_link_is_down(nxgep);
62952d17280bSsbehera 				nxgep->link_notify = B_FALSE;
62962d17280bSsbehera 
62972d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
62982d17280bSsbehera 
62992d17280bSsbehera 				goto start_link_check;
63002d17280bSsbehera 
63012d17280bSsbehera 			}
63022d17280bSsbehera 		}
630389282175SSantwona Behera 
630489282175SSantwona Behera 		switch (nxgep->chip_id) {
630589282175SSantwona Behera 		case MRVL88X201X_CHIP_ID:
630600161856Syc148097 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
630789282175SSantwona Behera 			break;
630889282175SSantwona Behera 		case NLP2020_CHIP_ID:
630989282175SSantwona Behera 			status = nxge_check_nlp2020_link(nxgep, &link_up);
631089282175SSantwona Behera 			break;
631189282175SSantwona Behera 		default:
63126f45ec7bSml29623 			status = nxge_check_bcm8704_link(nxgep, &link_up);
631389282175SSantwona Behera 			break;
631452cdd236Ssbehera 		}
631589282175SSantwona Behera 
63166f45ec7bSml29623 		if (status != NXGE_OK)
63176f45ec7bSml29623 			goto fail;
63182e59129aSraghus 		break;
63192e59129aSraghus 	case PORT_10G_SERDES:
63202e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
6321763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
63222e59129aSraghus 		if (rs != 0)
63232e59129aSraghus 			goto fail;
63242e59129aSraghus 
63252e59129aSraghus 		link_up = B_FALSE;
6326763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
63272e59129aSraghus 			link_up = B_TRUE;
63282e59129aSraghus 		}
6329763fcc44Ssbehera 
6330763fcc44Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6331763fcc44Ssbehera 		    "==> nxge_check_10g_link port<%d> "
6332763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
6333763fcc44Ssbehera 		    portn, val, link_up));
6334763fcc44Ssbehera 
63352e59129aSraghus 		break;
63362e59129aSraghus 	}
63376f45ec7bSml29623 
63386f45ec7bSml29623 	if (link_up) {
6339774da109Stc99174@train 		if ((nxgep->link_notify &&
6340774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
63416f45ec7bSml29623 		    nxgep->statsp->mac_stats.link_up == 0) {
63426f45ec7bSml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
63436f45ec7bSml29623 				goto fail;
63446f45ec7bSml29623 			nxgep->statsp->mac_stats.link_up = 1;
63456f45ec7bSml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
63466f45ec7bSml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
63476f45ec7bSml29623 
63486f45ec7bSml29623 			nxge_link_is_up(nxgep);
63496f45ec7bSml29623 			nxgep->link_notify = B_FALSE;
63506f45ec7bSml29623 		}
63516f45ec7bSml29623 	} else {
6352774da109Stc99174@train 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6353774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
63546f45ec7bSml29623 		    nxgep->statsp->mac_stats.link_up == 1) {
63556f45ec7bSml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
63566f45ec7bSml29623 				goto fail;
63576f45ec7bSml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63586f45ec7bSml29623 			    "Link down cable problem"));
63596f45ec7bSml29623 			nxgep->statsp->mac_stats.link_up = 0;
63606f45ec7bSml29623 			nxgep->statsp->mac_stats.link_speed = 0;
63616f45ec7bSml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
63626f45ec7bSml29623 
63636f45ec7bSml29623 			nxge_link_is_down(nxgep);
63646f45ec7bSml29623 			nxgep->link_notify = B_FALSE;
63651c7408c9Stc99174@train 
63661c7408c9Stc99174@train 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
63671c7408c9Stc99174@train 				/*
63681c7408c9Stc99174@train 				 * NEM was unplugged, set up xcvr table
63691c7408c9Stc99174@train 				 * to find another xcvr in the future.
63701c7408c9Stc99174@train 				 */
63711c7408c9Stc99174@train 				(void) nxge_xcvr_find(nxgep);
63721c7408c9Stc99174@train 			}
63736f45ec7bSml29623 		}
63746f45ec7bSml29623 	}
63756f45ec7bSml29623 
63762d17280bSsbehera start_link_check:
63776f45ec7bSml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
63786f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
63796f45ec7bSml29623 	    portn));
63806f45ec7bSml29623 	return (NXGE_OK);
63816f45ec7bSml29623 
63826f45ec7bSml29623 fail:
638398ecde52Stm144005 	(void) nxge_check_link_stop(nxgep);
638498ecde52Stm144005 
63856f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
63866f45ec7bSml29623 	    "nxge_check_10g_link: Failed to check link port<%d>",
63876f45ec7bSml29623 	    portn));
63886f45ec7bSml29623 	return (status);
63896f45ec7bSml29623 }
63906f45ec7bSml29623 
63916f45ec7bSml29623 
63926f45ec7bSml29623 /* Declare link down */
63936f45ec7bSml29623 
63946f45ec7bSml29623 void
63956f45ec7bSml29623 nxge_link_is_down(p_nxge_t nxgep)
63966f45ec7bSml29623 {
639759ac0c16Sdavemq 	p_nxge_stats_t statsp;
639859ac0c16Sdavemq 	char link_stat_msg[64];
639959ac0c16Sdavemq 
64006f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
64016f45ec7bSml29623 
640259ac0c16Sdavemq 	statsp = nxgep->statsp;
640359ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
640459ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
640559ac0c16Sdavemq 
640659ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
640759ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
640859ac0c16Sdavemq 	}
640959ac0c16Sdavemq 
64106f45ec7bSml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
64116f45ec7bSml29623 
64126f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
64136f45ec7bSml29623 }
64146f45ec7bSml29623 
64156f45ec7bSml29623 /* Declare link up */
64166f45ec7bSml29623 
64176f45ec7bSml29623 void
64186f45ec7bSml29623 nxge_link_is_up(p_nxge_t nxgep)
64196f45ec7bSml29623 {
642059ac0c16Sdavemq 	p_nxge_stats_t statsp;
642159ac0c16Sdavemq 	char link_stat_msg[64];
64226f45ec7bSml29623 	uint32_t val;
64236f45ec7bSml29623 
64246f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
64256f45ec7bSml29623 
642659ac0c16Sdavemq 	statsp = nxgep->statsp;
642759ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
642859ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
642959ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
643059ac0c16Sdavemq 
643159ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
643259ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
643359ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
643459ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
643559ac0c16Sdavemq 	else
643659ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
643759ac0c16Sdavemq 
64386f45ec7bSml29623 
64396f45ec7bSml29623 	/* Clean up symbol errors incurred during link transition */
64402e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
644189282175SSantwona Behera 	    (nxgep->mac.portmode == PORT_10G_COPPER) ||
64422e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
64436f45ec7bSml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
64446f45ec7bSml29623 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
64456f45ec7bSml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
64466f45ec7bSml29623 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
64476f45ec7bSml29623 	}
64486f45ec7bSml29623 
644900161856Syc148097 	/*
645000161856Syc148097 	 * If the driver was plumbed without a link (therefore auto-negotiation
645100161856Syc148097 	 * could not complete), the driver will detect a link up when a cable
645200161856Syc148097 	 * conneting to a link partner is plugged into the port. By the time
645300161856Syc148097 	 * link-up is detected, auto-negotiation should have completed (The
645400161856Syc148097 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
645500161856Syc148097 	 * configure the Neptune/NIU according to the newly negotiated speed.
645600161856Syc148097 	 * This is necessary only for the TN1010 basad device because only the
645700161856Syc148097 	 * TN1010 supports dual speeds.
645800161856Syc148097 	 */
645900161856Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
646000161856Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
646100161856Syc148097 
646200161856Syc148097 		(void) nxge_set_tn1010_param(nxgep);
646300161856Syc148097 
646400161856Syc148097 		/*
646500161856Syc148097 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
646600161856Syc148097 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
646700161856Syc148097 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
646800161856Syc148097 		 */
646900161856Syc148097 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
647000161856Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
647100161856Syc148097 			    "nxge_link_is_up: nxge_xcvr_find failed"));
647200161856Syc148097 		}
647300161856Syc148097 
647400161856Syc148097 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
647500161856Syc148097 		if (nxge_link_init(nxgep) != NXGE_OK) {
647600161856Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
647700161856Syc148097 			    "nxge_link_is_up: nxge_link_init failed"));
647800161856Syc148097 		}
647900161856Syc148097 
648000161856Syc148097 		/*
648100161856Syc148097 		 * nxge_mac_init calls many subroutines including
648200161856Syc148097 		 * nxge_xif_init which sets XGMII or GMII mode
648300161856Syc148097 		 */
648400161856Syc148097 		if (nxge_mac_init(nxgep) != NXGE_OK) {
648500161856Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
648600161856Syc148097 			    "nxge_link_is_up: nxge_mac_init failed"));
648700161856Syc148097 		}
648800161856Syc148097 	} else {
648900161856Syc148097 		(void) nxge_xif_init(nxgep);
649000161856Syc148097 	}
649100161856Syc148097 
649259ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
649359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
649459ac0c16Sdavemq 	}
649559ac0c16Sdavemq 
64966f45ec7bSml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
64976f45ec7bSml29623 
64986f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
64996f45ec7bSml29623 }
65006f45ec7bSml29623 
650100161856Syc148097 #ifdef NXGE_DEBUG
650200161856Syc148097 /* Dump all TN1010 Status registers */
650300161856Syc148097 static void
650400161856Syc148097 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
650500161856Syc148097 {
650600161856Syc148097 	uint16_t val;
650700161856Syc148097 
650800161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
650900161856Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
651000161856Syc148097 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
651100161856Syc148097 
651200161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
651300161856Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
651400161856Syc148097 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
651500161856Syc148097 
651600161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
651700161856Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
651800161856Syc148097 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
651900161856Syc148097 
652000161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
652100161856Syc148097 	    TN1010_PCS_DEV_ADDR, 1, &val);
652200161856Syc148097 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
652300161856Syc148097 
652400161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
652500161856Syc148097 	    TN1010_PCS_DEV_ADDR, 8, &val);
652600161856Syc148097 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
652700161856Syc148097 
652800161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
652900161856Syc148097 	    TN1010_PCS_DEV_ADDR, 32, &val);
653000161856Syc148097 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
653100161856Syc148097 
653200161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
653300161856Syc148097 	    TN1010_PCS_DEV_ADDR, 33, &val);
653400161856Syc148097 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
653500161856Syc148097 
653600161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
653700161856Syc148097 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
653800161856Syc148097 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
653900161856Syc148097 
654000161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
654100161856Syc148097 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
654200161856Syc148097 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
654300161856Syc148097 
654400161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
654500161856Syc148097 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
654600161856Syc148097 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
654700161856Syc148097 
654800161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
654900161856Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
655000161856Syc148097 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
655100161856Syc148097 
655200161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
655300161856Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
655400161856Syc148097 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
655500161856Syc148097 
655600161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
655700161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
655800161856Syc148097 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
655900161856Syc148097 
656000161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
656100161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
656200161856Syc148097 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
656300161856Syc148097 
656400161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
656500161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
656600161856Syc148097 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
656700161856Syc148097 
656800161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
656900161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
657000161856Syc148097 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
657100161856Syc148097 
657200161856Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
657300161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
657400161856Syc148097 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
657500161856Syc148097 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
657600161856Syc148097 }
657700161856Syc148097 #endif
657800161856Syc148097 
65796f45ec7bSml29623 /*
65806f45ec7bSml29623  * Calculate the bit in the multicast address filter
65816f45ec7bSml29623  * that selects the given * address.
65826f45ec7bSml29623  * Note: For GEM, the last 8-bits are used.
65836f45ec7bSml29623  */
65846f45ec7bSml29623 uint32_t
65856f45ec7bSml29623 crc32_mchash(p_ether_addr_t addr)
65866f45ec7bSml29623 {
65876f45ec7bSml29623 	uint8_t *cp;
65886f45ec7bSml29623 	uint32_t crc;
65896f45ec7bSml29623 	uint32_t c;
65906f45ec7bSml29623 	int byte;
65916f45ec7bSml29623 	int bit;
65926f45ec7bSml29623 
65936f45ec7bSml29623 	cp = (uint8_t *)addr;
65946f45ec7bSml29623 	crc = (uint32_t)0xffffffff;
65956f45ec7bSml29623 	for (byte = 0; byte < 6; byte++) {
65966f45ec7bSml29623 		c = (uint32_t)cp[byte];
65976f45ec7bSml29623 		for (bit = 0; bit < 8; bit++) {
65986f45ec7bSml29623 			if ((c & 0x1) ^ (crc & 0x1))
65996f45ec7bSml29623 				crc = (crc >> 1)^0xedb88320;
66006f45ec7bSml29623 			else
66016f45ec7bSml29623 				crc = (crc >> 1);
66026f45ec7bSml29623 			c >>= 1;
66036f45ec7bSml29623 		}
66046f45ec7bSml29623 	}
66056f45ec7bSml29623 	return ((~crc) >> (32 - HASH_BITS));
66066f45ec7bSml29623 }
66076f45ec7bSml29623 
66086f45ec7bSml29623 /* Reset serdes */
66096f45ec7bSml29623 
66106f45ec7bSml29623 nxge_status_t
66116f45ec7bSml29623 nxge_serdes_reset(p_nxge_t nxgep)
66126f45ec7bSml29623 {
66136f45ec7bSml29623 	npi_handle_t		handle;
66146f45ec7bSml29623 
66156f45ec7bSml29623 	handle = nxgep->npi_handle;
66166f45ec7bSml29623 
66176f45ec7bSml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
66186f45ec7bSml29623 	drv_usecwait(500);
66196f45ec7bSml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
66206f45ec7bSml29623 
66216f45ec7bSml29623 	return (NXGE_OK);
66226f45ec7bSml29623 }
66236f45ec7bSml29623 
662400161856Syc148097 /*
662500161856Syc148097  * This function monitors link status using interrupt or polling.
662600161856Syc148097  * It calls nxgep->xcvr.check_link, a member function of
662700161856Syc148097  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
662800161856Syc148097  * function back, that is why the check_link routine is
662900161856Syc148097  * executed periodically.
663000161856Syc148097  */
66316f45ec7bSml29623 nxge_status_t
66326f45ec7bSml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
66336f45ec7bSml29623 {
66346f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
66356f45ec7bSml29623 
6636678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
6637678453a8Sspeer 	if (isLDOMguest(nxgep))
6638678453a8Sspeer 		return (status);
6639678453a8Sspeer 
66406f45ec7bSml29623 	/*
664198ecde52Stm144005 	 * Return immediately if this is an imaginary XMAC port.
664298ecde52Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
66436f45ec7bSml29623 	 */
66442e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
664589282175SSantwona Behera 	    nxgep->mac.portmode == PORT_10G_COPPER ||
66462e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
66472e59129aSraghus 	    (nxgep->mac.portnum > 1))
66486f45ec7bSml29623 		return (NXGE_OK);
66496f45ec7bSml29623 
66506f45ec7bSml29623 	if (nxgep->statsp == NULL) {
66516f45ec7bSml29623 		/* stats has not been allocated. */
66526f45ec7bSml29623 		return (NXGE_OK);
66536f45ec7bSml29623 	}
6654321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
6655321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
66566f45ec7bSml29623 		return (NXGE_OK);
66576f45ec7bSml29623 
66586f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66596f45ec7bSml29623 	    "==> nxge_link_monitor port<%d> enable=%d",
66606f45ec7bSml29623 	    nxgep->mac.portnum, enable));
66616f45ec7bSml29623 	if (enable == LINK_MONITOR_START) {
66626f45ec7bSml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
66636f45ec7bSml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
66646f45ec7bSml29623 			    != NXGE_OK)
66656f45ec7bSml29623 				goto fail;
66666f45ec7bSml29623 		} else {
666798ecde52Stm144005 			timeout_id_t timerid;
666800161856Syc148097 			/*
666900161856Syc148097 			 * check_link_stop means "Stop the link check", so
667000161856Syc148097 			 * we return without starting the timer.
667100161856Syc148097 			 */
667298ecde52Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
667398ecde52Stm144005 				return (NXGE_OK);
667498ecde52Stm144005 
667500161856Syc148097 			/*
667600161856Syc148097 			 * Otherwise fire the timer for the nxge to check
667700161856Syc148097 			 * the link using the check_link function
667800161856Syc148097 			 * of the nxge_xcvr_table and pass "nxgep" as the
667900161856Syc148097 			 * argument to the check_link function.
668000161856Syc148097 			 */
668159ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
668259ac0c16Sdavemq 				timerid = timeout(
668359ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
66846f45ec7bSml29623 				    nxgep,
668598ecde52Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
668698ecde52Stm144005 				MUTEX_ENTER(&nxgep->poll_lock);
668798ecde52Stm144005 				nxgep->nxge_link_poll_timerid = timerid;
668898ecde52Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
6689774da109Stc99174@train 				nxgep->link_check_count ++;
669059ac0c16Sdavemq 			} else {
669159ac0c16Sdavemq 				return (NXGE_ERROR);
669259ac0c16Sdavemq 			}
66936f45ec7bSml29623 		}
66946f45ec7bSml29623 	} else {
66956f45ec7bSml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
66966f45ec7bSml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
66976f45ec7bSml29623 			    != NXGE_OK)
66986f45ec7bSml29623 				goto fail;
66996f45ec7bSml29623 		} else {
670098ecde52Stm144005 			clock_t rv;
670198ecde52Stm144005 
670298ecde52Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
670398ecde52Stm144005 
670498ecde52Stm144005 			/* If <timerid> == 0, the link monitor has */
670598ecde52Stm144005 			/* never been started, or just now stopped. */
670698ecde52Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
670798ecde52Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
670898ecde52Stm144005 				return (NXGE_OK);
670998ecde52Stm144005 			}
671098ecde52Stm144005 
671198ecde52Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
6712d3d50737SRafael Vanoni 			rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
671398ecde52Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
6714d3d50737SRafael Vanoni 			    LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
671598ecde52Stm144005 			if (rv == -1) {
671698ecde52Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
671798ecde52Stm144005 				    "==> stopping port %d: "
671898ecde52Stm144005 				    "cv_timedwait(%d) timed out",
671998ecde52Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
672098ecde52Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
67216f45ec7bSml29623 				nxgep->nxge_link_poll_timerid = 0;
67226f45ec7bSml29623 			}
672398ecde52Stm144005 
672498ecde52Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
67256f45ec7bSml29623 		}
67266f45ec7bSml29623 	}
67276f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67286f45ec7bSml29623 	    "<== nxge_link_monitor port<%d> enable=%d",
67296f45ec7bSml29623 	    nxgep->mac.portnum, enable));
6730678453a8Sspeer 
67316f45ec7bSml29623 	return (NXGE_OK);
67326f45ec7bSml29623 fail:
67336f45ec7bSml29623 	return (status);
673400161856Syc148097 
67356f45ec7bSml29623 }
67366f45ec7bSml29623 
673700161856Syc148097 nxge_status_t
673800161856Syc148097 nxge_check_tn1010_link(p_nxge_t nxgep)
673900161856Syc148097 {
674000161856Syc148097 	nxge_status_t	status = NXGE_OK;
674100161856Syc148097 	nxge_link_state_t link_up;
674200161856Syc148097 
674300161856Syc148097 	if (nxgep->nxge_magic != NXGE_MAGIC) {
674400161856Syc148097 		/* magic is 0 if driver is not attached */
674500161856Syc148097 		return (NXGE_ERROR);
674600161856Syc148097 	}
674700161856Syc148097 
674800161856Syc148097 	/* Link has been stopped, no need to continue */
674900161856Syc148097 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
675000161856Syc148097 		return (NXGE_OK);
675100161856Syc148097 	}
675200161856Syc148097 
675300161856Syc148097 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
675400161856Syc148097 		goto nxge_check_tn1010_link_exit;
675500161856Syc148097 
675600161856Syc148097 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
675700161856Syc148097 		goto fail;
675800161856Syc148097 
675900161856Syc148097 nxge_check_tn1010_link_exit:
676000161856Syc148097 	if (link_up == LINK_IS_UP)
676100161856Syc148097 		nxge_link_is_up(nxgep);
676200161856Syc148097 	else if (link_up == LINK_IS_DOWN)
676300161856Syc148097 		nxge_link_is_down(nxgep);
676400161856Syc148097 
676500161856Syc148097 	/*
676600161856Syc148097 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
676700161856Syc148097 	 * which could be THIS function.
676800161856Syc148097 	 */
676900161856Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
677000161856Syc148097 
677100161856Syc148097 	return (NXGE_OK);
677200161856Syc148097 
677300161856Syc148097 fail:
677400161856Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
677500161856Syc148097 
677600161856Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
677700161856Syc148097 	    "nxge_check_tn1010_link: Failed to check link"));
677800161856Syc148097 	return (status);
677900161856Syc148097 }
678000161856Syc148097 
678100161856Syc148097 
678200161856Syc148097 /*
678300161856Syc148097  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
678400161856Syc148097  */
678500161856Syc148097 static nxge_status_t
678600161856Syc148097 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
678700161856Syc148097 {
678800161856Syc148097 	nxge_status_t	status = NXGE_OK;
678900161856Syc148097 	p_nxge_stats_t	statsp;
679000161856Syc148097 	uint8_t		phy_port_addr, portn;
679100161856Syc148097 	uint16_t	val;
679200161856Syc148097 
679300161856Syc148097 	*link_up = LINK_NO_CHANGE;
679400161856Syc148097 
679500161856Syc148097 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
679600161856Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
679700161856Syc148097 	statsp = nxgep->statsp;
679800161856Syc148097 
679900161856Syc148097 	/* Check if link is up */
680000161856Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
680100161856Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
680200161856Syc148097 	    != NXGE_OK) {
680300161856Syc148097 		goto fail;
680400161856Syc148097 	}
680500161856Syc148097 	/*
680600161856Syc148097 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
680700161856Syc148097 	 * portmode and link_speed
680800161856Syc148097 	 */
680900161856Syc148097 	if (val & TN1010_AN_LINK_STAT_BIT) {
6810774da109Stc99174@train 		if ((nxgep->link_notify &&
6811774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
681200161856Syc148097 		    nxgep->statsp->mac_stats.link_up == 0) {
681300161856Syc148097 			statsp->mac_stats.link_up = 1;
681400161856Syc148097 			statsp->mac_stats.link_duplex = 2;
681500161856Syc148097 			*link_up = LINK_IS_UP;
681600161856Syc148097 			nxgep->link_notify = B_FALSE;
681700161856Syc148097 		}
681800161856Syc148097 	} else {
6819774da109Stc99174@train 		if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
6820774da109Stc99174@train 		    nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
682100161856Syc148097 		    nxgep->statsp->mac_stats.link_up == 1) {
682200161856Syc148097 			statsp->mac_stats.link_up = 0;
682300161856Syc148097 			statsp->mac_stats.link_speed = 0;
682400161856Syc148097 			statsp->mac_stats.link_duplex = 0;
682500161856Syc148097 			*link_up = LINK_IS_DOWN;
682600161856Syc148097 			nxgep->link_notify = B_FALSE;
682700161856Syc148097 		}
682800161856Syc148097 	}
682900161856Syc148097 	return (NXGE_OK);
683000161856Syc148097 
683100161856Syc148097 fail:
683200161856Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
683300161856Syc148097 	    "nxge_tn1010_check: Unable to check TN1010"));
683400161856Syc148097 	return (status);
683500161856Syc148097 }
683600161856Syc148097 
683700161856Syc148097 
68386f45ec7bSml29623 /* Set promiscous mode */
68396f45ec7bSml29623 
68406f45ec7bSml29623 nxge_status_t
68416f45ec7bSml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
68426f45ec7bSml29623 {
68436f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
68446f45ec7bSml29623 
684559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
68466f45ec7bSml29623 
68476f45ec7bSml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
68486f45ec7bSml29623 
68496f45ec7bSml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
68506f45ec7bSml29623 
68516f45ec7bSml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
68526f45ec7bSml29623 		goto fail;
68536f45ec7bSml29623 	}
68546f45ec7bSml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
68556f45ec7bSml29623 		goto fail;
68566f45ec7bSml29623 	}
68576f45ec7bSml29623 
68586f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
68596f45ec7bSml29623 
68606f45ec7bSml29623 	if (on)
68616f45ec7bSml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
68626f45ec7bSml29623 	else
68636f45ec7bSml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
68646f45ec7bSml29623 
68656f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
68666f45ec7bSml29623 
68676f45ec7bSml29623 	return (NXGE_OK);
68686f45ec7bSml29623 fail:
68696f45ec7bSml29623 	RW_EXIT(&nxgep->filter_lock);
68706f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
68716f45ec7bSml29623 	    "Unable to set promisc (%d)", on));
68726f45ec7bSml29623 
68736f45ec7bSml29623 	return (status);
68746f45ec7bSml29623 }
68756f45ec7bSml29623 
68766f45ec7bSml29623 /*ARGSUSED*/
68776f45ec7bSml29623 uint_t
68786f45ec7bSml29623 nxge_mif_intr(void *arg1, void *arg2)
68796f45ec7bSml29623 {
68806f45ec7bSml29623 #ifdef	NXGE_DEBUG
68816f45ec7bSml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
68826f45ec7bSml29623 #endif
68836f45ec7bSml29623 #if NXGE_MIF
68846f45ec7bSml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
68856f45ec7bSml29623 	uint32_t		status;
68866f45ec7bSml29623 	npi_handle_t		handle;
68876f45ec7bSml29623 	uint8_t			portn;
68886f45ec7bSml29623 	p_nxge_stats_t		statsp;
68896f45ec7bSml29623 #endif
68906f45ec7bSml29623 
68916f45ec7bSml29623 #ifdef	NXGE_MIF
68926f45ec7bSml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
68936f45ec7bSml29623 		nxgep = ldvp->nxgep;
68946f45ec7bSml29623 	}
68956f45ec7bSml29623 	nxgep = ldvp->nxgep;
68966f45ec7bSml29623 #endif
68976f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
68986f45ec7bSml29623 
68996f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
69006f45ec7bSml29623 	return (DDI_INTR_CLAIMED);
69016f45ec7bSml29623 
69026f45ec7bSml29623 mif_intr_fail:
69036f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
69046f45ec7bSml29623 	return (DDI_INTR_UNCLAIMED);
69056f45ec7bSml29623 }
69066f45ec7bSml29623 
69076f45ec7bSml29623 /*ARGSUSED*/
69086f45ec7bSml29623 uint_t
69096f45ec7bSml29623 nxge_mac_intr(void *arg1, void *arg2)
69106f45ec7bSml29623 {
69116f45ec7bSml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
69126f45ec7bSml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
69136f45ec7bSml29623 	p_nxge_ldg_t		ldgp;
69146f45ec7bSml29623 	uint32_t		status;
69156f45ec7bSml29623 	npi_handle_t		handle;
69166f45ec7bSml29623 	uint8_t			portn;
69176f45ec7bSml29623 	p_nxge_stats_t		statsp;
69186f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
69196f45ec7bSml29623 
69206f45ec7bSml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
69216f45ec7bSml29623 		nxgep = ldvp->nxgep;
69226f45ec7bSml29623 	}
69236f45ec7bSml29623 
69246f45ec7bSml29623 	ldgp = ldvp->ldgp;
69256f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
69266f45ec7bSml29623 	    "group %d", ldgp->ldg));
69276f45ec7bSml29623 
69286f45ec7bSml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
69296f45ec7bSml29623 	/*
69306f45ec7bSml29623 	 * This interrupt handler is for a specific
69316f45ec7bSml29623 	 * mac port.
69326f45ec7bSml29623 	 */
69336f45ec7bSml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
69346f45ec7bSml29623 	portn = nxgep->mac.portnum;
69356f45ec7bSml29623 
69366f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
69376f45ec7bSml29623 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
69386f45ec7bSml29623 
69396f45ec7bSml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
69406f45ec7bSml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
69416f45ec7bSml29623 		    (xmac_tx_iconfig_t *)&status);
69426f45ec7bSml29623 		if (rs != NPI_SUCCESS)
69436f45ec7bSml29623 			goto npi_fail;
69446f45ec7bSml29623 		if (status & ICFG_XMAC_TX_ALL) {
69456f45ec7bSml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
69466f45ec7bSml29623 				statsp->xmac_stats.tx_underflow_err++;
69476f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
69486f45ec7bSml29623 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
69496f45ec7bSml29623 			}
69506f45ec7bSml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
69516f45ec7bSml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
6952f6485eecSyc148097 				/*
6953f6485eecSyc148097 				 * Do not send FMA ereport because this
6954f6485eecSyc148097 				 * error does not indicate HW failure.
6955f6485eecSyc148097 				 */
69566f45ec7bSml29623 			}
69576f45ec7bSml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
69586f45ec7bSml29623 				statsp->xmac_stats.tx_overflow_err++;
69596f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
69606f45ec7bSml29623 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
69616f45ec7bSml29623 			}
69626f45ec7bSml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
69636f45ec7bSml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
69646f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
69656f45ec7bSml29623 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
69666f45ec7bSml29623 			}
69676f45ec7bSml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
69686f45ec7bSml29623 				statsp->xmac_stats.tx_byte_cnt +=
69696f45ec7bSml29623 				    XTXMAC_BYTE_CNT_MASK;
69706f45ec7bSml29623 			}
69716f45ec7bSml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
69726f45ec7bSml29623 				statsp->xmac_stats.tx_frame_cnt +=
69736f45ec7bSml29623 				    XTXMAC_FRM_CNT_MASK;
69746f45ec7bSml29623 			}
69756f45ec7bSml29623 		}
69766f45ec7bSml29623 
69776f45ec7bSml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
69786f45ec7bSml29623 		    (xmac_rx_iconfig_t *)&status);
69796f45ec7bSml29623 		if (rs != NPI_SUCCESS)
69806f45ec7bSml29623 			goto npi_fail;
69816f45ec7bSml29623 		if (status & ICFG_XMAC_RX_ALL) {
69826f45ec7bSml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
69836f45ec7bSml29623 				statsp->xmac_stats.rx_overflow_err++;
69846f45ec7bSml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
69856f45ec7bSml29623 				statsp->xmac_stats.rx_underflow_err++;
69866f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
69876f45ec7bSml29623 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
69886f45ec7bSml29623 			}
6989f6485eecSyc148097 			/*
6990f6485eecSyc148097 			 * Do not send FMA ereport for the following 3 errors
6991f6485eecSyc148097 			 * because they do not indicate HW failures.
6992f6485eecSyc148097 			 */
69936f45ec7bSml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
69946f45ec7bSml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
69956f45ec7bSml29623 				    XRXMAC_CRC_ER_CNT_MASK;
69966f45ec7bSml29623 			}
69976f45ec7bSml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
69986f45ec7bSml29623 				statsp->xmac_stats.rx_len_err_cnt +=
69996f45ec7bSml29623 				    MAC_LEN_ER_CNT_MASK;
70006f45ec7bSml29623 			}
70016f45ec7bSml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
70026f45ec7bSml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
70036f45ec7bSml29623 				    XRXMAC_CD_VIO_CNT_MASK;
70046f45ec7bSml29623 			}
70056f45ec7bSml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
70066f45ec7bSml29623 				statsp->xmac_stats.rx_byte_cnt +=
70076f45ec7bSml29623 				    XRXMAC_BT_CNT_MASK;
70086f45ec7bSml29623 			}
70096f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
70106f45ec7bSml29623 				statsp->xmac_stats.rx_hist1_cnt +=
70116f45ec7bSml29623 				    XRXMAC_HIST_CNT1_MASK;
70126f45ec7bSml29623 			}
70136f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
70146f45ec7bSml29623 				statsp->xmac_stats.rx_hist2_cnt +=
70156f45ec7bSml29623 				    XRXMAC_HIST_CNT2_MASK;
70166f45ec7bSml29623 			}
70176f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
70186f45ec7bSml29623 				statsp->xmac_stats.rx_hist3_cnt +=
70196f45ec7bSml29623 				    XRXMAC_HIST_CNT3_MASK;
70206f45ec7bSml29623 			}
70216f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
70226f45ec7bSml29623 				statsp->xmac_stats.rx_hist4_cnt +=
70236f45ec7bSml29623 				    XRXMAC_HIST_CNT4_MASK;
70246f45ec7bSml29623 			}
70256f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
70266f45ec7bSml29623 				statsp->xmac_stats.rx_hist5_cnt +=
70276f45ec7bSml29623 				    XRXMAC_HIST_CNT5_MASK;
70286f45ec7bSml29623 			}
70296f45ec7bSml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
70306f45ec7bSml29623 				statsp->xmac_stats.rx_hist6_cnt +=
70316f45ec7bSml29623 				    XRXMAC_HIST_CNT6_MASK;
70326f45ec7bSml29623 			}
70336f45ec7bSml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
70346f45ec7bSml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
70356f45ec7bSml29623 				    XRXMAC_BC_FRM_CNT_MASK;
70366f45ec7bSml29623 			}
70376f45ec7bSml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
70386f45ec7bSml29623 				statsp->xmac_stats.rx_mult_cnt +=
70396f45ec7bSml29623 				    XRXMAC_MC_FRM_CNT_MASK;
70406f45ec7bSml29623 			}
7041f6485eecSyc148097 			/*
7042f6485eecSyc148097 			 * Do not send FMA ereport for the following 3 errors
7043f6485eecSyc148097 			 * because they do not indicate HW failures.
7044f6485eecSyc148097 			 */
70456f45ec7bSml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
70466f45ec7bSml29623 				statsp->xmac_stats.rx_frag_cnt +=
70476f45ec7bSml29623 				    XRXMAC_FRAG_CNT_MASK;
70486f45ec7bSml29623 			}
70496f45ec7bSml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
70506f45ec7bSml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
70516f45ec7bSml29623 				    XRXMAC_AL_ER_CNT_MASK;
70526f45ec7bSml29623 			}
70536f45ec7bSml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
70546f45ec7bSml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
70556f45ec7bSml29623 				    XMAC_LINK_FLT_CNT_MASK;
70566f45ec7bSml29623 			}
70576f45ec7bSml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
70586f45ec7bSml29623 				statsp->xmac_stats.rx_remotefault_err++;
70596f45ec7bSml29623 			}
70606f45ec7bSml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
70616f45ec7bSml29623 				statsp->xmac_stats.rx_localfault_err++;
70626f45ec7bSml29623 			}
70636f45ec7bSml29623 		}
70646f45ec7bSml29623 
70656f45ec7bSml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
70666f45ec7bSml29623 		    (xmac_ctl_iconfig_t *)&status);
70676f45ec7bSml29623 		if (rs != NPI_SUCCESS)
70686f45ec7bSml29623 			goto npi_fail;
70696f45ec7bSml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
70706f45ec7bSml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
70716f45ec7bSml29623 				statsp->xmac_stats.rx_pause_cnt++;
70726f45ec7bSml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
70736f45ec7bSml29623 				statsp->xmac_stats.tx_pause_state++;
70746f45ec7bSml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
70756f45ec7bSml29623 				statsp->xmac_stats.tx_nopause_state++;
70766f45ec7bSml29623 		}
70776f45ec7bSml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
70786f45ec7bSml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
70796f45ec7bSml29623 		    (bmac_tx_iconfig_t *)&status);
70806f45ec7bSml29623 		if (rs != NPI_SUCCESS)
70816f45ec7bSml29623 			goto npi_fail;
70826f45ec7bSml29623 		if (status & ICFG_BMAC_TX_ALL) {
70836f45ec7bSml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
70846f45ec7bSml29623 				statsp->bmac_stats.tx_underrun_err++;
70856f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
70866f45ec7bSml29623 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
70876f45ec7bSml29623 			}
70886f45ec7bSml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
70896f45ec7bSml29623 				statsp->bmac_stats.tx_max_pkt_err++;
70906f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
70916f45ec7bSml29623 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
70926f45ec7bSml29623 			}
70936f45ec7bSml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
70946f45ec7bSml29623 				statsp->bmac_stats.tx_byte_cnt +=
70956f45ec7bSml29623 				    BTXMAC_BYTE_CNT_MASK;
70966f45ec7bSml29623 			}
70976f45ec7bSml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
70986f45ec7bSml29623 				statsp->bmac_stats.tx_frame_cnt +=
70996f45ec7bSml29623 				    BTXMAC_FRM_CNT_MASK;
71006f45ec7bSml29623 			}
71016f45ec7bSml29623 		}
71026f45ec7bSml29623 
71036f45ec7bSml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
71046f45ec7bSml29623 		    (bmac_rx_iconfig_t *)&status);
71056f45ec7bSml29623 		if (rs != NPI_SUCCESS)
71066f45ec7bSml29623 			goto npi_fail;
71076f45ec7bSml29623 		if (status & ICFG_BMAC_RX_ALL) {
71086f45ec7bSml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
71096f45ec7bSml29623 				statsp->bmac_stats.rx_overflow_err++;
71106f45ec7bSml29623 			}
71116f45ec7bSml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
71126f45ec7bSml29623 				statsp->bmac_stats.rx_frame_cnt +=
71136f45ec7bSml29623 				    RXMAC_FRM_CNT_MASK;
71146f45ec7bSml29623 			}
71156f45ec7bSml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
71166f45ec7bSml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
71176f45ec7bSml29623 				    BMAC_CRC_ER_CNT_MASK;
71186f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
71196f45ec7bSml29623 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
71206f45ec7bSml29623 			}
71216f45ec7bSml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
71226f45ec7bSml29623 				statsp->bmac_stats.rx_len_err_cnt +=
71236f45ec7bSml29623 				    MAC_LEN_ER_CNT_MASK;
71246f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
71256f45ec7bSml29623 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
71266f45ec7bSml29623 			}
71276f45ec7bSml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
71286f45ec7bSml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
71296f45ec7bSml29623 				    BMAC_CD_VIO_CNT_MASK;
71306f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
71316f45ec7bSml29623 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
71326f45ec7bSml29623 			}
71336f45ec7bSml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
71346f45ec7bSml29623 				statsp->bmac_stats.rx_byte_cnt +=
71356f45ec7bSml29623 				    BRXMAC_BYTE_CNT_MASK;
71366f45ec7bSml29623 			}
71376f45ec7bSml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
71386f45ec7bSml29623 				statsp->bmac_stats.rx_align_err_cnt +=
71396f45ec7bSml29623 				    BMAC_AL_ER_CNT_MASK;
71406f45ec7bSml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
71416f45ec7bSml29623 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
71426f45ec7bSml29623 			}
71436f45ec7bSml29623 
71446f45ec7bSml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
71456f45ec7bSml29623 			    (bmac_ctl_iconfig_t *)&status);
71466f45ec7bSml29623 			if (rs != NPI_SUCCESS)
71476f45ec7bSml29623 				goto npi_fail;
71486f45ec7bSml29623 
71496f45ec7bSml29623 			if (status & ICFG_BMAC_CTL_ALL) {
71506f45ec7bSml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
71516f45ec7bSml29623 					statsp->bmac_stats.rx_pause_cnt++;
71526f45ec7bSml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
71536f45ec7bSml29623 					statsp->bmac_stats.tx_pause_state++;
71546f45ec7bSml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
71556f45ec7bSml29623 					statsp->bmac_stats.tx_nopause_state++;
71566f45ec7bSml29623 			}
71576f45ec7bSml29623 		}
71586f45ec7bSml29623 
71596f45ec7bSml29623 	if (ldgp->nldvs == 1) {
71606f45ec7bSml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
71616f45ec7bSml29623 		    B_TRUE, ldgp->ldg_timer);
71626f45ec7bSml29623 	}
71636f45ec7bSml29623 
71646f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
71656f45ec7bSml29623 	return (DDI_INTR_CLAIMED);
71666f45ec7bSml29623 
71676f45ec7bSml29623 npi_fail:
71686f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
71696f45ec7bSml29623 	return (DDI_INTR_UNCLAIMED);
71706f45ec7bSml29623 }
71716f45ec7bSml29623 
71726f45ec7bSml29623 nxge_status_t
71736f45ec7bSml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
71746f45ec7bSml29623 {
71756f45ec7bSml29623 	uint8_t		phy_port_addr;
71766f45ec7bSml29623 	nxge_status_t	status = NXGE_OK;
71776f45ec7bSml29623 	boolean_t	rx_sig_ok;
71786f45ec7bSml29623 	boolean_t	pcs_blk_lock;
71796f45ec7bSml29623 	boolean_t	link_align;
71806f45ec7bSml29623 	uint16_t	val1, val2, val3;
71816f45ec7bSml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
71826f45ec7bSml29623 	uint16_t	val_debug;
71834df55fdeSJanie Lu 	uint32_t	val;
71846f45ec7bSml29623 #endif
71856f45ec7bSml29623 
71866f45ec7bSml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
71876f45ec7bSml29623 
71886f45ec7bSml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
71896f45ec7bSml29623 	/* Check Device 3 Register Device 3 0xC809 */
71906f45ec7bSml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
71916f45ec7bSml29623 	if ((val_debug & ~0x200) != 0) {
71926f45ec7bSml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
71936f45ec7bSml29623 		    nxgep->mac.portnum, val_debug);
71946f45ec7bSml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
71956f45ec7bSml29623 		    &val_debug);
71966f45ec7bSml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
71976f45ec7bSml29623 		    nxgep->mac.portnum, val_debug);
71986f45ec7bSml29623 	}
71996f45ec7bSml29623 
72006f45ec7bSml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
72016f45ec7bSml29623 	    XPCS_REG_DESCWERR_COUNTER, &val);
72026f45ec7bSml29623 	if (val != 0)
72036f45ec7bSml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
72046f45ec7bSml29623 
72056f45ec7bSml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
72066f45ec7bSml29623 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
72076f45ec7bSml29623 	if (val != 0)
72086f45ec7bSml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
72096f45ec7bSml29623 
72106f45ec7bSml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
72116f45ec7bSml29623 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
72126f45ec7bSml29623 	if (val != 0)
72136f45ec7bSml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
72146f45ec7bSml29623 #endif
72156f45ec7bSml29623 
72166f45ec7bSml29623 	/* Check from BCM8704 if 10G link is up or down */
72176f45ec7bSml29623 
72186f45ec7bSml29623 	/* Check Device 1 Register 0xA bit0 */
721952ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
722052ccf843Smisaki 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
72216f45ec7bSml29623 	if (status != NXGE_OK)
72226f45ec7bSml29623 		goto fail;
72236f45ec7bSml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
72246f45ec7bSml29623 
72256f45ec7bSml29623 	/* Check Device 3 Register 0x20 bit0 */
722652ccf843Smisaki 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
722752ccf843Smisaki 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
72286f45ec7bSml29623 		goto fail;
72296f45ec7bSml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
72306f45ec7bSml29623 
72316f45ec7bSml29623 	/* Check Device 4 Register 0x18 bit12 */
723252ccf843Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
723352ccf843Smisaki 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
72346f45ec7bSml29623 	if (status != NXGE_OK)
72356f45ec7bSml29623 		goto fail;
72362d17280bSsbehera 
72372d17280bSsbehera 	switch (nxgep->chip_id) {
72382d17280bSsbehera 	case BCM8704_CHIP_ID:
72392d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
72402d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
72416f45ec7bSml29623 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
72422d17280bSsbehera 		break;
72432d17280bSsbehera 	case BCM8706_CHIP_ID:
72442d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
72452d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
72462d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
72472d17280bSsbehera 		    B_TRUE : B_FALSE;
72482d17280bSsbehera 		break;
72492d17280bSsbehera 	default:
72502d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
72512d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
72522d17280bSsbehera 		goto fail;
72532d17280bSsbehera 	}
72542d17280bSsbehera 
72556f45ec7bSml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
72566f45ec7bSml29623 	/* Temp workaround for link down issue */
72576f45ec7bSml29623 	if (pcs_blk_lock == B_FALSE) {
72586f45ec7bSml29623 		if (val2 != 0x4) {
72596f45ec7bSml29623 			pcs_blk_lock = B_TRUE;
726052ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
726152ccf843Smisaki 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
72626f45ec7bSml29623 		}
72636f45ec7bSml29623 	}
72646f45ec7bSml29623 
72656f45ec7bSml29623 	if (link_align == B_FALSE) {
72666f45ec7bSml29623 		if (val3 != 0x140f) {
72676f45ec7bSml29623 			link_align = B_TRUE;
726852ccf843Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
726952ccf843Smisaki 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
72706f45ec7bSml29623 		}
72716f45ec7bSml29623 	}
72726f45ec7bSml29623 
72736f45ec7bSml29623 	if (rx_sig_ok == B_FALSE) {
72746f45ec7bSml29623 		if ((val2 == 0) || (val3 == 0)) {
72756f45ec7bSml29623 			rx_sig_ok = B_TRUE;
72766f45ec7bSml29623 			cmn_err(CE_NOTE,
72776f45ec7bSml29623 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
72786f45ec7bSml29623 			    nxgep->mac.portnum);
72796f45ec7bSml29623 		}
72806f45ec7bSml29623 	}
72816f45ec7bSml29623 #endif
72826f45ec7bSml29623 
72836f45ec7bSml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
72846f45ec7bSml29623 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
72856f45ec7bSml29623 
72866f45ec7bSml29623 	return (NXGE_OK);
72876f45ec7bSml29623 fail:
72886f45ec7bSml29623 	return (status);
72896f45ec7bSml29623 }
72906f45ec7bSml29623 
729152cdd236Ssbehera static nxge_status_t
729200161856Syc148097 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
729352cdd236Ssbehera {
729452cdd236Ssbehera 	uint8_t		phy;
729552cdd236Ssbehera 	nxge_status_t   status = NXGE_OK;
729652cdd236Ssbehera 	boolean_t	pma_status;
729752cdd236Ssbehera 	boolean_t	pcs_status;
729852cdd236Ssbehera 	boolean_t	xgxs_status;
729952cdd236Ssbehera 	uint16_t	val;
730052cdd236Ssbehera 
730152cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
730252cdd236Ssbehera 
730352cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
730452cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
730552cdd236Ssbehera 
730652cdd236Ssbehera 	*link_up = B_FALSE;
730752cdd236Ssbehera 
730852cdd236Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
730952cdd236Ssbehera 
731052cdd236Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
731152cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
731252cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
731352cdd236Ssbehera 
731452cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
731552cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
731652cdd236Ssbehera 
731752cdd236Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
731852cdd236Ssbehera 
731952cdd236Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
732052cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
732152cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
732252cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
732352cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
732452cdd236Ssbehera 
732552cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
732652cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
732752cdd236Ssbehera 
732852cdd236Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
732952cdd236Ssbehera 
733052cdd236Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
733152cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
733252cdd236Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
733352cdd236Ssbehera 
733452cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
733552cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
733652cdd236Ssbehera 
733752cdd236Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
733852cdd236Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
733952cdd236Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
734052cdd236Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
734152cdd236Ssbehera 
734252cdd236Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
734352cdd236Ssbehera 	    B_TRUE : B_FALSE;
734452cdd236Ssbehera 
734552cdd236Ssbehera fail:
734652cdd236Ssbehera 
734752cdd236Ssbehera 	if (*link_up == B_FALSE) {
734852cdd236Ssbehera 		/* PCS OFF */
734952cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
735052cdd236Ssbehera 	} else {
735152cdd236Ssbehera 		/* PCS Activity */
735252cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
735352cdd236Ssbehera 	}
735452cdd236Ssbehera 
735552cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
735652cdd236Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
735752cdd236Ssbehera 
735852cdd236Ssbehera 	return (status);
735952cdd236Ssbehera }
736052cdd236Ssbehera 
736189282175SSantwona Behera static nxge_status_t
736289282175SSantwona Behera nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up)
736389282175SSantwona Behera {
736489282175SSantwona Behera 	uint8_t		phy;
736589282175SSantwona Behera 	nxge_status_t   status = NXGE_OK;
736689282175SSantwona Behera 	uint16_t	pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat;
736789282175SSantwona Behera 	uint8_t		connector = 0;
736889282175SSantwona Behera 
736989282175SSantwona Behera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
737089282175SSantwona Behera 	*link_up = B_FALSE;
737189282175SSantwona Behera 
737289282175SSantwona Behera 	/* Check from Netlogic AEL2020 if 10G link is up or down */
737389282175SSantwona Behera 
737489282175SSantwona Behera 	status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR,
737589282175SSantwona Behera 	    NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig);
737689282175SSantwona Behera 	if (status != NXGE_OK)
737789282175SSantwona Behera 		goto fail;
737889282175SSantwona Behera 
737989282175SSantwona Behera 	status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR,
738089282175SSantwona Behera 	    NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1);
738189282175SSantwona Behera 	if (status != NXGE_OK)
738289282175SSantwona Behera 		goto fail;
738389282175SSantwona Behera 
738489282175SSantwona Behera 	status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR,
738589282175SSantwona Behera 	    NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat);
738689282175SSantwona Behera 	if (status != NXGE_OK)
738789282175SSantwona Behera 		goto fail;
738889282175SSantwona Behera 
738989282175SSantwona Behera 	if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) &&
739089282175SSantwona Behera 	    (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) &&
739189282175SSantwona Behera 	    (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC))
739289282175SSantwona Behera 		*link_up = B_TRUE;
739389282175SSantwona Behera 	/*
739489282175SSantwona Behera 	 * If previously link was down, check the connector type as
739589282175SSantwona Behera 	 * it might have been changed.
739689282175SSantwona Behera 	 */
739789282175SSantwona Behera 	if (nxgep->statsp->mac_stats.link_up == 0) {
739889282175SSantwona Behera 		(void) nxge_nlp2020_i2c_read(nxgep, phy,
739989282175SSantwona Behera 		    NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector);
740089282175SSantwona Behera 
740189282175SSantwona Behera 		switch (connector) {
740289282175SSantwona Behera 		case SFPP_FIBER:
740389282175SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
740489282175SSantwona Behera 			    "nxge_check_nlp2020_link: SFPP_FIBER"));
740589282175SSantwona Behera 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
740689282175SSantwona Behera 				nxgep->mac.portmode = PORT_10G_FIBER;
740789282175SSantwona Behera 				(void) nxge_nlp2020_xcvr_init(nxgep);
740889282175SSantwona Behera 			}
740989282175SSantwona Behera 			break;
741089282175SSantwona Behera 		case QSFP_FIBER:
741189282175SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
741289282175SSantwona Behera 			    "nxge_check_nlp2020_link: QSFP_FIBER"));
741389282175SSantwona Behera 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
741489282175SSantwona Behera 				nxgep->mac.portmode = PORT_10G_FIBER;
741589282175SSantwona Behera 				(void) nxge_nlp2020_xcvr_init(nxgep);
741689282175SSantwona Behera 			}
741789282175SSantwona Behera 			break;
741889282175SSantwona Behera 		case QSFP_COPPER_TWINAX:
741989282175SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
742089282175SSantwona Behera 			    "nxge_check_nlp2020_link: "
742189282175SSantwona Behera 			    "QSFP_COPPER_TWINAX/"
742289282175SSantwona Behera 			    "SFPP_COPPER_TWINAX"));
742389282175SSantwona Behera 			if (nxgep->mac.portmode != PORT_10G_COPPER) {
742489282175SSantwona Behera 				nxgep->mac.portmode = PORT_10G_COPPER;
742589282175SSantwona Behera 				(void) nxge_nlp2020_xcvr_init(nxgep);
742689282175SSantwona Behera 			} else {
742789282175SSantwona Behera 				uint8_t len = 0;
742889282175SSantwona Behera 				(void) nxge_nlp2020_i2c_read(nxgep, phy,
742989282175SSantwona Behera 				    NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG,
743089282175SSantwona Behera 				    &len);
743189282175SSantwona Behera 				if (((len < 7) &&
743289282175SSantwona Behera 				    (nxgep->nlp_conn ==
743389282175SSantwona Behera 				    NXGE_NLP_CONN_COPPER_7M_ABOVE)) ||
743489282175SSantwona Behera 				    ((len >= 7) &&
743589282175SSantwona Behera 				    (nxgep->nlp_conn ==
743689282175SSantwona Behera 				    NXGE_NLP_CONN_COPPER_LT_7M))) {
743789282175SSantwona Behera 					(void) nxge_nlp2020_xcvr_init(nxgep);
743889282175SSantwona Behera 				}
743989282175SSantwona Behera 			}
744089282175SSantwona Behera 			break;
744189282175SSantwona Behera 		default:
744289282175SSantwona Behera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
744389282175SSantwona Behera 			    "nxge_check_nlp2020_link: Unknown type [0x%x] "
744489282175SSantwona Behera 			    "detected...setting to QSFP_FIBER",
744589282175SSantwona Behera 			    connector));
744689282175SSantwona Behera 			if (nxgep->mac.portmode != PORT_10G_FIBER) {
744789282175SSantwona Behera 				nxgep->mac.portmode = PORT_10G_FIBER;
744889282175SSantwona Behera 				(void) nxge_nlp2020_xcvr_init(nxgep);
744989282175SSantwona Behera 			}
745089282175SSantwona Behera 			break;
745189282175SSantwona Behera 		}
745289282175SSantwona Behera 	}
745389282175SSantwona Behera fail:
745489282175SSantwona Behera 	if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) {
745589282175SSantwona Behera 		/* Turn link LED OFF */
745689282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy,
745789282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000);
745889282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy,
745989282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0);
746089282175SSantwona Behera 	} else if (*link_up == B_TRUE &&
746189282175SSantwona Behera 	    nxgep->statsp->mac_stats.link_up == 0) {
746289282175SSantwona Behera 		/* Turn link LED ON */
746389282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy,
746489282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000);
746589282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy,
746689282175SSantwona Behera 		    NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff);
746789282175SSantwona Behera 		(void) nxge_mdio_write(nxgep, phy,
746889282175SSantwona Behera 		    NLP2020_GPIO_ADDR, 0xff2a, 0x004a);
746989282175SSantwona Behera 	}
747089282175SSantwona Behera 
747189282175SSantwona Behera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
747289282175SSantwona Behera 	    " <== nxge_check_nlp2020_link: up=%d", *link_up));
747389282175SSantwona Behera 	return (status);
747489282175SSantwona Behera }
747589282175SSantwona Behera 
747689282175SSantwona Behera 
74776f45ec7bSml29623 nxge_status_t
74786f45ec7bSml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
74796f45ec7bSml29623 {
74806f45ec7bSml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
74816f45ec7bSml29623 	    != NPI_SUCCESS)
74826f45ec7bSml29623 		return (NXGE_ERROR);
74836f45ec7bSml29623 	else
74846f45ec7bSml29623 		return (NXGE_OK);
74856f45ec7bSml29623 }
74866f45ec7bSml29623 
74876f45ec7bSml29623 nxge_status_t
74886f45ec7bSml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
74896f45ec7bSml29623 {
74906f45ec7bSml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
74916f45ec7bSml29623 	    != NPI_SUCCESS)
74926f45ec7bSml29623 		return (NXGE_ERROR);
74936f45ec7bSml29623 	else
74946f45ec7bSml29623 		return (NXGE_OK);
74956f45ec7bSml29623 }
749656d930aeSspeer 
74972d17280bSsbehera static boolean_t
749889282175SSantwona Behera nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn)
749989282175SSantwona Behera {
750089282175SSantwona Behera 	/*
750189282175SSantwona Behera 	 * check for BCM PHY (GOA NEM)
750289282175SSantwona Behera 	 */
750389282175SSantwona Behera 	/*
750489282175SSantwona Behera 	 * If this is the 2nd NIU port, then check 2 addresses
750589282175SSantwona Behera 	 * to take care of the Goa NEM card. Port 1 can have addr 17
750689282175SSantwona Behera 	 * (in the eval board) or 20 (in the P0 board).
750789282175SSantwona Behera 	 */
750889282175SSantwona Behera 	if (portn == 1) {
750989282175SSantwona Behera 		if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR,
751089282175SSantwona Behera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
751189282175SSantwona Behera 			nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR;
751289282175SSantwona Behera 			goto found_phy;
751389282175SSantwona Behera 		}
751489282175SSantwona Behera 	}
751589282175SSantwona Behera 	if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn,
751689282175SSantwona Behera 	    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
751789282175SSantwona Behera 		nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn;
751889282175SSantwona Behera 			goto found_phy;
751989282175SSantwona Behera 	}
752089282175SSantwona Behera 
752189282175SSantwona Behera 	/*
752289282175SSantwona Behera 	 * check for NLP2020 PHY on C4 NEM
752389282175SSantwona Behera 	 */
752489282175SSantwona Behera 	switch (portn) {
752589282175SSantwona Behera 	case 0:
752689282175SSantwona Behera 		if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0,
752789282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
752889282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0;
752989282175SSantwona Behera 			goto found_phy;
753089282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1,
753189282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
753289282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1;
753389282175SSantwona Behera 			goto found_phy;
753489282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2,
753589282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
753689282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2;
753789282175SSantwona Behera 			goto found_phy;
753889282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3,
753989282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
754089282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3;
754189282175SSantwona Behera 			goto found_phy;
754289282175SSantwona Behera 		}
754389282175SSantwona Behera 		break;
754489282175SSantwona Behera 
754589282175SSantwona Behera 	case 1:
754689282175SSantwona Behera 		if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0,
754789282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
754889282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0;
754989282175SSantwona Behera 			goto found_phy;
755089282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1,
755189282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
755289282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1;
755389282175SSantwona Behera 			goto found_phy;
755489282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2,
755589282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
755689282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2;
755789282175SSantwona Behera 			goto found_phy;
755889282175SSantwona Behera 		} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3,
755989282175SSantwona Behera 		    NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
756089282175SSantwona Behera 			nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3;
756189282175SSantwona Behera 			goto found_phy;
756289282175SSantwona Behera 		}
756389282175SSantwona Behera 		break;
756489282175SSantwona Behera 	default:
756589282175SSantwona Behera 		break;
756689282175SSantwona Behera 	}
756789282175SSantwona Behera 
756889282175SSantwona Behera 	return (B_FALSE);
756989282175SSantwona Behera found_phy:
757089282175SSantwona Behera 	return (B_TRUE);
757189282175SSantwona Behera 
757289282175SSantwona Behera }
757389282175SSantwona Behera 
757489282175SSantwona Behera static boolean_t
75752d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
75762d17280bSsbehera {
75772d17280bSsbehera 	uint32_t pma_pmd_id = 0;
75782d17280bSsbehera 	uint32_t pcs_id = 0;
75792d17280bSsbehera 	uint32_t phy_id = 0;
75802d17280bSsbehera 
75812d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
75822d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75832d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
75842d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
75852d17280bSsbehera 		goto found_phy;
75862d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
75872d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75882d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
75892d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
75902d17280bSsbehera 		goto found_phy;
75912d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
75922d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75932d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
75942d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
75952d17280bSsbehera 		goto found_phy;
75962d17280bSsbehera 
75972d17280bSsbehera 	return (B_FALSE);
75982d17280bSsbehera 
75992d17280bSsbehera found_phy:
76002d17280bSsbehera 	return (B_TRUE);
76012d17280bSsbehera }
76022d17280bSsbehera 
760359ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
760459ac0c16Sdavemq 
760559ac0c16Sdavemq static boolean_t
760659ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
760759ac0c16Sdavemq {
760859ac0c16Sdavemq 	int		i;
760959ac0c16Sdavemq 	boolean_t	found = B_FALSE;
761059ac0c16Sdavemq 
761159ac0c16Sdavemq 	switch (type) {
761259ac0c16Sdavemq 	case CLAUSE_45_TYPE:
761300161856Syc148097 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
761400161856Syc148097 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
761500161856Syc148097 			    (id & BCM_PHY_ID_MASK)) ||
761689282175SSantwona Behera 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) ||
761789282175SSantwona Behera 			    (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) {
761859ac0c16Sdavemq 				found = B_TRUE;
761959ac0c16Sdavemq 				break;
762059ac0c16Sdavemq 			}
762159ac0c16Sdavemq 		}
762259ac0c16Sdavemq 		break;
762359ac0c16Sdavemq 	case CLAUSE_22_TYPE:
762400161856Syc148097 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
762530505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
762630505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
762759ac0c16Sdavemq 				found = B_TRUE;
762859ac0c16Sdavemq 				break;
762959ac0c16Sdavemq 			}
763059ac0c16Sdavemq 		}
763159ac0c16Sdavemq 		break;
763259ac0c16Sdavemq 	default:
763359ac0c16Sdavemq 		break;
763459ac0c16Sdavemq 	}
763559ac0c16Sdavemq 
763659ac0c16Sdavemq 	return (found);
763759ac0c16Sdavemq }
763859ac0c16Sdavemq 
76392e59129aSraghus static uint32_t
76402e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
76412e59129aSraghus {
76422e59129aSraghus 	uint16_t	val1 = 0;
76432e59129aSraghus 	uint16_t	val2 = 0;
76442e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
76452e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
76462e59129aSraghus 
764753560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
76482e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
76492e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
76502e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
76512e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
765253560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
76532e59129aSraghus 
765400161856Syc148097 	/* Concatenate the Device ID stored in two registers. */
76552e59129aSraghus 	pma_pmd_dev_id = val1;
76562e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
76572e59129aSraghus 	pma_pmd_dev_id |= val2;
76582e59129aSraghus 
76592e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
76602e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
76612e59129aSraghus 
76622e59129aSraghus 	return (pma_pmd_dev_id);
76632e59129aSraghus }
76642e59129aSraghus 
76652e59129aSraghus static uint32_t
76662e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
76672e59129aSraghus {
76682e59129aSraghus 	uint16_t	val1 = 0;
76692e59129aSraghus 	uint16_t	val2 = 0;
76702e59129aSraghus 	uint32_t	pcs_dev_id = 0;
76712e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
76722e59129aSraghus 
767353560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
76742e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
76752e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
76762e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
76772e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
767853560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
76792e59129aSraghus 
76802e59129aSraghus 	pcs_dev_id = val1;
76812e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
76822e59129aSraghus 	pcs_dev_id |= val2;
76832e59129aSraghus 
76842e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
76852e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
76862e59129aSraghus 
76872e59129aSraghus 	return (pcs_dev_id);
76882e59129aSraghus }
76892e59129aSraghus 
76902e59129aSraghus static uint32_t
76912e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
76922e59129aSraghus {
76932e59129aSraghus 	uint16_t	val1 = 0;
76942e59129aSraghus 	uint16_t	val2 = 0;
76952e59129aSraghus 	uint32_t	phy_id = 0;
76962e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
76972e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
76982e59129aSraghus 
7699321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
77002e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
77012e59129aSraghus 	    &val1);
77022e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
77032e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
77042e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
77052e59129aSraghus 		goto exit;
77062e59129aSraghus 	}
77072e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
77082e59129aSraghus 	    &val2);
77092e59129aSraghus 	if (npi_status != 0) {
77102e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
77112e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
77122e59129aSraghus 		goto exit;
77132e59129aSraghus 	}
77142e59129aSraghus 	phy_id = val1;
77152e59129aSraghus 	phy_id = (phy_id << 16);
77162e59129aSraghus 	phy_id |= val2;
77172e59129aSraghus 
77182e59129aSraghus exit:
7719321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
77202e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
77212e59129aSraghus 	    phy_port, phy_id));
77222e59129aSraghus 
77232e59129aSraghus 	return (phy_id);
77242e59129aSraghus }
77252e59129aSraghus 
772659ac0c16Sdavemq /*
772759ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
772859ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
772959ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
773059ac0c16Sdavemq  * and the Neptune type.
773100161856Syc148097  *
773200161856Syc148097  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
773300161856Syc148097  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
773400161856Syc148097  * in case the portmode information is not available via OBP, nxge.conf,
773500161856Syc148097  * VPD or SEEPROM.
773659ac0c16Sdavemq  */
773759ac0c16Sdavemq nxge_status_t
773859ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
773959ac0c16Sdavemq {
774059a835ddSjoycey 	int		i, j, l;
774159ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
774259ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
774359ac0c16Sdavemq 	uint32_t	phy_id = 0;
774430505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
774530505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
774630505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
774759ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
774859ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
77492d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
77502d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
775159ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
775200161856Syc148097 	uint8_t		num_xaui;
775359ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
775459ac0c16Sdavemq 
775559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
775659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
775759ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
775859ac0c16Sdavemq 	    nxgep->niu_type));
775959ac0c16Sdavemq 
7760678453a8Sspeer 	if (isLDOMguest(nxgep)) {
7761678453a8Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
7762678453a8Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
7763678453a8Sspeer 		return (NXGE_OK);
7764678453a8Sspeer 	}
7765678453a8Sspeer 
776659a835ddSjoycey 	j = l = 0;
776759ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
776859ac0c16Sdavemq 	/*
776923b952a3SSantwona Behera 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
777023b952a3SSantwona Behera 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
777159ac0c16Sdavemq 	 */
777259ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
77732e59129aSraghus 
77742e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
777559ac0c16Sdavemq 
777659ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
777759ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
777859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
777952cdd236Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
778030505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
778100161856Syc148097 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
778200161856Syc148097 				    == TN1010_DEV_ID) {
778300161856Syc148097 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
778489282175SSantwona Behera 				} else if ((pma_pmd_dev_id &
778589282175SSantwona Behera 				    NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) {
778689282175SSantwona Behera 					port_pma_pmd_dev_id[j] =
778789282175SSantwona Behera 					    NLP2020_DEV_ID;
778800161856Syc148097 				} else {
778900161856Syc148097 					port_pma_pmd_dev_id[j] =
779000161856Syc148097 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
779100161856Syc148097 				}
77922d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
779359ac0c16Sdavemq 				j++;
779459ac0c16Sdavemq 			}
779559ac0c16Sdavemq 		} else {
779659ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
779759ac0c16Sdavemq 		}
779859ac0c16Sdavemq 
77992e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
780059ac0c16Sdavemq 
780159ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
780259ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
780359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
780452cdd236Ssbehera 			    "dev %x found", i, pcs_dev_id));
780559a835ddSjoycey 			if (pma_pmd_dev_fd[i] == 1) {
780600161856Syc148097 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
780700161856Syc148097 				    == TN1010_DEV_ID) {
780800161856Syc148097 					port_pcs_dev_id[j - 1] =
780900161856Syc148097 					    TN1010_DEV_ID;
781089282175SSantwona Behera 				} else if ((pcs_dev_id & NLP2020_DEV_ID_MASK)
781189282175SSantwona Behera 				    == NLP2020_DEV_ID) {
781289282175SSantwona Behera 					port_pcs_dev_id[j - 1] =
781389282175SSantwona Behera 					    NLP2020_DEV_ID;
781400161856Syc148097 				} else {
781500161856Syc148097 					port_pcs_dev_id[j - 1] =
781600161856Syc148097 					    pcs_dev_id &
781730505775Ssbehera 					    BCM_PHY_ID_MASK;
781800161856Syc148097 				}
781959a835ddSjoycey 			} else {
782059a835ddSjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
782100161856Syc148097 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
782200161856Syc148097 					    == TN1010_DEV_ID) {
782300161856Syc148097 						port_pcs_dev_id[j] =
782400161856Syc148097 						    TN1010_DEV_ID;
782589282175SSantwona Behera 					} else if ((pcs_dev_id &
782689282175SSantwona Behera 					    NLP2020_DEV_ID_MASK)
782789282175SSantwona Behera 					    == NLP2020_DEV_ID) {
782889282175SSantwona Behera 						port_pcs_dev_id[j] =
782989282175SSantwona Behera 						    NLP2020_DEV_ID;
783000161856Syc148097 					} else {
783100161856Syc148097 						port_pcs_dev_id[j] =
783200161856Syc148097 						    pcs_dev_id &
783359a835ddSjoycey 						    BCM_PHY_ID_MASK;
783400161856Syc148097 					}
783559a835ddSjoycey 					port_fd_arr[j] = (uint8_t)i;
783659a835ddSjoycey 					j++;
783759a835ddSjoycey 				}
783859ac0c16Sdavemq 			}
783959ac0c16Sdavemq 		} else {
784059ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
784159ac0c16Sdavemq 		}
784259ac0c16Sdavemq 
78432d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
78442d17280bSsbehera 			total_port_fd ++;
78452d17280bSsbehera 		}
784659ac0c16Sdavemq 
78472e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
784859ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
78492d17280bSsbehera 			total_phy_fd ++;
785059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
785152cdd236Ssbehera 			    "%x found", i, phy_id));
785230505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
785300161856Syc148097 				if ((phy_id & TN1010_DEV_ID_MASK)
785400161856Syc148097 				    == TN1010_DEV_ID) {
785500161856Syc148097 					port_phy_id[l] = TN1010_DEV_ID;
785600161856Syc148097 				} else {
785700161856Syc148097 					port_phy_id[l]
785800161856Syc148097 					    = phy_id & BCM_PHY_ID_MASK;
785900161856Syc148097 				}
78602d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
786159ac0c16Sdavemq 				l++;
786259ac0c16Sdavemq 			}
786359ac0c16Sdavemq 		}
786459ac0c16Sdavemq 	}
786559ac0c16Sdavemq 
786659ac0c16Sdavemq 	switch (total_port_fd) {
786759ac0c16Sdavemq 	case 2:
786859ac0c16Sdavemq 		switch (total_phy_fd) {
786959ac0c16Sdavemq 		case 2:
787023b952a3SSantwona Behera 			/* 2 10G, 2 1G RGMII Fiber / copper */
787159a835ddSjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
787259a835ddSjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
787359a835ddSjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
787459a835ddSjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
787559a835ddSjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
787659a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
787759a835ddSjoycey 
787823b952a3SSantwona Behera 				switch (hw_p->platform_type) {
787923b952a3SSantwona Behera 				case P_NEPTUNE_ROCK:
788023b952a3SSantwona Behera 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
788123b952a3SSantwona Behera 					/*
788223b952a3SSantwona Behera 					 * ROCK platform has assigned a lower
788323b952a3SSantwona Behera 					 * addr to port 1. (port 0 = 0x9 and
788423b952a3SSantwona Behera 					 * port 1 = 0x8).
788523b952a3SSantwona Behera 					 */
788623b952a3SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
788723b952a3SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[1];
788859a835ddSjoycey 
788923b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
789023b952a3SSantwona Behera 					    "Rock with 2 10G, 2 1GC"));
789123b952a3SSantwona Behera 					break;
789223b952a3SSantwona Behera 
789323b952a3SSantwona Behera 				case P_NEPTUNE_NONE:
789423b952a3SSantwona Behera 				default:
789523b952a3SSantwona Behera 					hw_p->platform_type =
789623b952a3SSantwona Behera 					    P_NEPTUNE_GENERIC;
789759a835ddSjoycey 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
789859a835ddSjoycey 
789959a835ddSjoycey 					hw_p->xcvr_addr[0] = port_fd_arr[0];
790059a835ddSjoycey 					hw_p->xcvr_addr[1] = port_fd_arr[1];
790123b952a3SSantwona Behera 
790223b952a3SSantwona Behera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
790323b952a3SSantwona Behera 					    "ARTM card with 2 10G, 2 1GF"));
790423b952a3SSantwona Behera 					break;
790523b952a3SSantwona Behera 				}
790623b952a3SSantwona Behera 
790759a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
790859a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
790959a835ddSjoycey 
791059a835ddSjoycey 			} else {
791159a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
791259ac0c16Sdavemq 				    "Unsupported neptune type 1"));
791359ac0c16Sdavemq 				goto error_exit;
791459a835ddSjoycey 			}
791559a835ddSjoycey 			break;
791659a835ddSjoycey 
791759ac0c16Sdavemq 		case 1:
791859ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
791959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
792059ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
792159ac0c16Sdavemq 			goto error_exit;
792259ac0c16Sdavemq 		case 0:
792300161856Syc148097 			/*
792400161856Syc148097 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
792500161856Syc148097 			 * cards, etc.
792600161856Syc148097 			 */
792730505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
792830505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
792930505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
793052cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
793152cdd236Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
793252cdd236Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
793352cdd236Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
793452cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
793552cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] ==
793652cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
79372e59129aSraghus 
79382e59129aSraghus 				/*
79392e59129aSraghus 				 * Check the first phy port address against
79402e59129aSraghus 				 * the known phy start addresses to determine
79412e59129aSraghus 				 * the platform type.
79422e59129aSraghus 				 */
79432d17280bSsbehera 
79442d17280bSsbehera 				switch (port_fd_arr[0]) {
794500161856Syc148097 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
794652cdd236Ssbehera 					/*
794752cdd236Ssbehera 					 * The Marvell case also falls into
794852cdd236Ssbehera 					 * this case as
794952cdd236Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
795000161856Syc148097 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
795152cdd236Ssbehera 					 * This is OK for the 2 10G case.
795252cdd236Ssbehera 					 */
79532e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
79542e59129aSraghus 					hw_p->platform_type =
79552e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
79562d17280bSsbehera 					break;
795700161856Syc148097 				case GOA_CLAUSE45_PORT_ADDR_BASE:
79582d17280bSsbehera 					if (hw_p->platform_type !=
79592d17280bSsbehera 					    P_NEPTUNE_NIU) {
79602d17280bSsbehera 						hw_p->platform_type =
79612d17280bSsbehera 						    P_NEPTUNE_GENERIC;
79622d17280bSsbehera 						hw_p->niu_type =
79632d17280bSsbehera 						    NEPTUNE_2_10GF;
79642d17280bSsbehera 					}
79652d17280bSsbehera 					break;
79662d17280bSsbehera 				default:
79672d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
79682e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
79692e59129aSraghus 					goto error_exit;
79702e59129aSraghus 				}
79712d17280bSsbehera 
79722d17280bSsbehera 				for (i = 0; i < 2; i++) {
79732d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
79742d17280bSsbehera 				}
797500161856Syc148097 
797689282175SSantwona Behera 			/* 2 10G optical Netlogic AEL2020 ports */
797789282175SSantwona Behera 			} else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) &&
797889282175SSantwona Behera 			    (port_pcs_dev_id[1]  == NLP2020_DEV_ID)) ||
797989282175SSantwona Behera 			    ((port_pma_pmd_dev_id[0]  == NLP2020_DEV_ID) &&
798089282175SSantwona Behera 			    (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) {
798189282175SSantwona Behera 				if (hw_p->platform_type != P_NEPTUNE_NIU) {
798289282175SSantwona Behera 					hw_p->platform_type =
798389282175SSantwona Behera 					    P_NEPTUNE_GENERIC;
798489282175SSantwona Behera 					hw_p->niu_type =
798589282175SSantwona Behera 					    NEPTUNE_2_10GF;
798689282175SSantwona Behera 				}
798789282175SSantwona Behera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
798889282175SSantwona Behera 				    "Found 2 NL PHYs at addrs 0x%x and 0x%x",
798989282175SSantwona Behera 				    port_fd_arr[0], port_fd_arr[1]));
799089282175SSantwona Behera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
799189282175SSantwona Behera 				hw_p->xcvr_addr[1] = port_fd_arr[1];
799289282175SSantwona Behera 
799300161856Syc148097 			/* Both XAUI slots have copper XAUI cards */
799400161856Syc148097 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
799500161856Syc148097 			    == TN1010_DEV_ID) &&
799600161856Syc148097 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
799700161856Syc148097 			    == TN1010_DEV_ID)) ||
799800161856Syc148097 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
799900161856Syc148097 			    == TN1010_DEV_ID) &&
800000161856Syc148097 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
800100161856Syc148097 			    == TN1010_DEV_ID))) {
800200161856Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010;
800300161856Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
800400161856Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
800500161856Syc148097 
800600161856Syc148097 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
800700161856Syc148097 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
800800161856Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
800900161856Syc148097 			    == TN1010_DEV_ID) ||
801000161856Syc148097 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
801100161856Syc148097 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
801200161856Syc148097 			    TN1010_DEV_ID)) {
801300161856Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
801400161856Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
801500161856Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
801600161856Syc148097 
801700161856Syc148097 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
801800161856Syc148097 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
801900161856Syc148097 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
802000161856Syc148097 			    == TN1010_DEV_ID) ||
802100161856Syc148097 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
802200161856Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
802300161856Syc148097 			    == TN1010_DEV_ID)) {
802400161856Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
802500161856Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
802600161856Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
802700161856Syc148097 
802859ac0c16Sdavemq 			} else {
802959ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
803059ac0c16Sdavemq 				    "Unsupported neptune type 2"));
803159ac0c16Sdavemq 				goto error_exit;
803259ac0c16Sdavemq 			}
803359ac0c16Sdavemq 			break;
803400161856Syc148097 
803559ac0c16Sdavemq 		case 4:
803600161856Syc148097 			if (nxge_get_num_of_xaui(
803700161856Syc148097 			    port_pma_pmd_dev_id, port_pcs_dev_id,
803800161856Syc148097 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
803900161856Syc148097 				goto error_exit;
804000161856Syc148097 			}
804100161856Syc148097 			if (num_xaui != 2)
804200161856Syc148097 				goto error_exit;
804359ac0c16Sdavemq 
804459ac0c16Sdavemq 			/*
804500161856Syc148097 			 *  Maramba with 2 XAUIs (either fiber or copper)
804600161856Syc148097 			 *
804759ac0c16Sdavemq 			 * Check the first phy port address against
804859ac0c16Sdavemq 			 * the known phy start addresses to determine
804959ac0c16Sdavemq 			 * the platform type.
805059ac0c16Sdavemq 			 */
80512d17280bSsbehera 			switch (phy_fd_arr[0]) {
805200161856Syc148097 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
805359ac0c16Sdavemq 				hw_p->platform_type =
805459ac0c16Sdavemq 				    P_NEPTUNE_MARAMBA_P0;
80552d17280bSsbehera 				break;
805600161856Syc148097 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
805759ac0c16Sdavemq 				hw_p->platform_type =
805859ac0c16Sdavemq 				    P_NEPTUNE_MARAMBA_P1;
80592d17280bSsbehera 				break;
80602d17280bSsbehera 			default:
806159ac0c16Sdavemq 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
806259ac0c16Sdavemq 				    "Unknown port %d...Cannot "
806359ac0c16Sdavemq 				    "determine platform type", i));
80642e59129aSraghus 				goto error_exit;
806559ac0c16Sdavemq 			}
80662d17280bSsbehera 
80672d17280bSsbehera 			hw_p->xcvr_addr[0] = port_fd_arr[0];
80682d17280bSsbehera 			hw_p->xcvr_addr[1] = port_fd_arr[1];
80692d17280bSsbehera 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
80702d17280bSsbehera 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
80712d17280bSsbehera 
807200161856Syc148097 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
807300161856Syc148097 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
807400161856Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
807500161856Syc148097 			    == TN1010_DEV_ID) {
807600161856Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
807700161856Syc148097 
807800161856Syc148097 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
807900161856Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
808000161856Syc148097 			    == TN1010_DEV_ID) &&
808100161856Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
808200161856Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
808300161856Syc148097 
808400161856Syc148097 			/* Both slots have fiber XAUI */
808500161856Syc148097 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
808600161856Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
808700161856Syc148097 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
808800161856Syc148097 
808900161856Syc148097 			/* Both slots have copper XAUI */
809000161856Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
809100161856Syc148097 			    == TN1010_DEV_ID) &&
809200161856Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
809300161856Syc148097 			    == TN1010_DEV_ID) {
809400161856Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
809500161856Syc148097 
809659ac0c16Sdavemq 			} else {
809759ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
809859ac0c16Sdavemq 				    "Unsupported neptune type 3"));
809959ac0c16Sdavemq 				goto error_exit;
810059ac0c16Sdavemq 			}
810159ac0c16Sdavemq 			break;
810259ac0c16Sdavemq 		default:
810359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
810459ac0c16Sdavemq 			    "Unsupported neptune type 5"));
810559ac0c16Sdavemq 			goto error_exit;
810659ac0c16Sdavemq 		}
810730505775Ssbehera 		break;
810800161856Syc148097 	case 1: 	/* Only one clause45 port */
810900161856Syc148097 		switch (total_phy_fd) {	/* Number of clause22 ports */
811059ac0c16Sdavemq 		case 3:
81112e59129aSraghus 			/*
81122e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
81132e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
81142e59129aSraghus 			 * 1_10G_3_1G
81152e59129aSraghus 			 */
811659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
811759ac0c16Sdavemq 			    "Unsupported neptune type 7"));
811859ac0c16Sdavemq 			goto error_exit;
811959ac0c16Sdavemq 		case 2:
812059ac0c16Sdavemq 			/*
812159ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
812259ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
812359ac0c16Sdavemq 			 * 1_10G_2_1G
812459ac0c16Sdavemq 			 */
812559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
812659ac0c16Sdavemq 			    "Unsupported neptune type 8"));
812759ac0c16Sdavemq 			goto error_exit;
812859ac0c16Sdavemq 		case 1:
812959ac0c16Sdavemq 			/*
813059ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
813159ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
813259ac0c16Sdavemq 			 * 1_10G_1_1G
813359ac0c16Sdavemq 			 */
813459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
813559ac0c16Sdavemq 			    "Unsupported neptune type 9"));
813659ac0c16Sdavemq 			goto error_exit;
813700161856Syc148097 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
813800161856Syc148097 			/* Fiber XAUI */
81392d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
81402d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
81412d17280bSsbehera 
81422d17280bSsbehera 				/*
81432d17280bSsbehera 				 * Check the first phy port address against
81442d17280bSsbehera 				 * the known phy start addresses to determine
81452d17280bSsbehera 				 * the platform type.
81462d17280bSsbehera 				 */
81472d17280bSsbehera 
81482d17280bSsbehera 				switch (port_fd_arr[0]) {
814900161856Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
815000161856Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
815100161856Syc148097 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
815200161856Syc148097 					/*
815300161856Syc148097 					 * If hw_p->platform_type ==
815400161856Syc148097 					 * P_NEPTUNE_NIU, then portmode
815500161856Syc148097 					 * is already known, so there is
815600161856Syc148097 					 * no need to figure out hw_p->
815700161856Syc148097 					 * platform_type because
815800161856Syc148097 					 * platform_type is only for
815900161856Syc148097 					 * figuring out portmode.
816000161856Syc148097 					 */
81612d17280bSsbehera 					if (hw_p->platform_type !=
81622d17280bSsbehera 					    P_NEPTUNE_NIU) {
81632d17280bSsbehera 						hw_p->platform_type =
81642d17280bSsbehera 						    P_NEPTUNE_GENERIC;
81652d17280bSsbehera 						hw_p->niu_type =
81662d17280bSsbehera 						    NEPTUNE_2_10GF;
81672d17280bSsbehera 					}
81682d17280bSsbehera 					break;
81692d17280bSsbehera 				default:
81702d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
817159ac0c16Sdavemq 					    "Unsupported neptune type 10"));
817259ac0c16Sdavemq 					goto error_exit;
81732d17280bSsbehera 				}
8174321febdeSsbehera 				/*
8175321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
8176321febdeSsbehera 				 * phy address to function number mapping
8177321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
8178321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
8179321febdeSsbehera 				 * But for Huron XAUI, the assignment should
8180321febdeSsbehera 				 * be by function number, i.e., whichever
8181321febdeSsbehera 				 * function number attaches should be
8182321febdeSsbehera 				 * assigned the available PHY (this is required
8183321febdeSsbehera 				 * primarily to support pre-production Huron
8184321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
8185321febdeSsbehera 				 */
8186321febdeSsbehera 				if (port_fd_arr[0] ==
818700161856Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
8188321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
8189321febdeSsbehera 				} else {
81904202ea4bSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
81914202ea4bSsbehera 					    port_fd_arr[0];
8192321febdeSsbehera 				}
819389282175SSantwona Behera 			} else if (port_pcs_dev_id[0] == NLP2020_DEV_ID ||
819489282175SSantwona Behera 			    port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) {
819589282175SSantwona Behera 				/* A 10G NLP2020 PHY in slot0 or slot1 */
819689282175SSantwona Behera 				switch (port_fd_arr[0]) {
819789282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR0:
819889282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR1:
819989282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR2:
820089282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR3:
820189282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR0:
820289282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR1:
820389282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR2:
820489282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR3:
820589282175SSantwona Behera 					/*
820689282175SSantwona Behera 					 * If hw_p->platform_type ==
820789282175SSantwona Behera 					 * P_NEPTUNE_NIU, then portmode
820889282175SSantwona Behera 					 * is already known, so there is
820989282175SSantwona Behera 					 * no need to figure out hw_p->
821089282175SSantwona Behera 					 * platform_type because
821189282175SSantwona Behera 					 * platform_type is only for
821289282175SSantwona Behera 					 * figuring out portmode.
821389282175SSantwona Behera 					 */
821489282175SSantwona Behera 					if (hw_p->platform_type !=
821589282175SSantwona Behera 					    P_NEPTUNE_NIU) {
821689282175SSantwona Behera 						hw_p->platform_type =
821789282175SSantwona Behera 						    P_NEPTUNE_GENERIC;
821889282175SSantwona Behera 						hw_p->niu_type =
821989282175SSantwona Behera 						    NEPTUNE_2_10GF;
822089282175SSantwona Behera 					}
822189282175SSantwona Behera 					break;
822289282175SSantwona Behera 				default:
822389282175SSantwona Behera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
822489282175SSantwona Behera 					    "Unsupported neptune type 10-1"));
822589282175SSantwona Behera 					goto error_exit;
822689282175SSantwona Behera 				}
822789282175SSantwona Behera 				switch (port_fd_arr[0]) {
822889282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR0:
822989282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR1:
823089282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR2:
823189282175SSantwona Behera 				case NLP2020_CL45_PORT0_ADDR3:
823289282175SSantwona Behera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
823389282175SSantwona Behera 					break;
823489282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR0:
823589282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR1:
823689282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR2:
823789282175SSantwona Behera 				case NLP2020_CL45_PORT1_ADDR3:
823889282175SSantwona Behera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
823989282175SSantwona Behera 					break;
824089282175SSantwona Behera 				default:
824189282175SSantwona Behera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
824289282175SSantwona Behera 					    "Unsupported neptune type 10-11"));
824389282175SSantwona Behera 					goto error_exit;
824489282175SSantwona Behera 				}
824589282175SSantwona Behera 
824689282175SSantwona Behera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
824789282175SSantwona Behera 				    "Found 1 NL PHYs at addr 0x%x",
824889282175SSantwona Behera 				    port_fd_arr[0]));
824900161856Syc148097 
825000161856Syc148097 			/* A 10G copper XAUI in either slot0 or slot1 */
825100161856Syc148097 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
825200161856Syc148097 			    == TN1010_DEV_ID ||
825300161856Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
825400161856Syc148097 			    == TN1010_DEV_ID) {
825500161856Syc148097 				switch (port_fd_arr[0]) {
825600161856Syc148097 				/* The XAUI is in slot0 */
825700161856Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
825800161856Syc148097 					hw_p->niu_type = NEPTUNE_1_TN1010;
825900161856Syc148097 					break;
826000161856Syc148097 
826100161856Syc148097 				/* The XAUI is in slot1 */
826200161856Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
826300161856Syc148097 					hw_p->niu_type
826400161856Syc148097 					    = NEPTUNE_1_NONE_1_TN1010;
826500161856Syc148097 					break;
826600161856Syc148097 				default:
826700161856Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
826800161856Syc148097 					    "Unsupported XAUI port address"));
826900161856Syc148097 					goto error_exit;
827000161856Syc148097 				}
827100161856Syc148097 				hw_p->xcvr_addr[nxgep->function_num]
827200161856Syc148097 				    = port_fd_arr[0];
827300161856Syc148097 
82742d17280bSsbehera 			} else {
82752d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
827600161856Syc148097 				    "Unsupported PHY type"));
82772d17280bSsbehera 				goto error_exit;
82782d17280bSsbehera 			}
82792d17280bSsbehera 			break;
828000161856Syc148097 		case 4: /* Maramba always have 4 clause 45 ports */
828159ac0c16Sdavemq 
828200161856Syc148097 			/* Maramba with 1 XAUI */
828352ccf843Smisaki 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
828452ccf843Smisaki 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
828500161856Syc148097 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
828652ccf843Smisaki 			    != TN1010_DEV_ID) &&
828700161856Syc148097 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
828852ccf843Smisaki 			    != TN1010_DEV_ID)) {
828952ccf843Smisaki 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
829052ccf843Smisaki 				    "Unsupported neptune type 12"));
829152ccf843Smisaki 				goto error_exit;
829252ccf843Smisaki 			}
829352ccf843Smisaki 
829459ac0c16Sdavemq 			/*
829559ac0c16Sdavemq 			 * Check the first phy port address against
829659ac0c16Sdavemq 			 * the known phy start addresses to determine
829759ac0c16Sdavemq 			 * the platform type.
829859ac0c16Sdavemq 			 */
82992d17280bSsbehera 			switch (phy_fd_arr[0]) {
830000161856Syc148097 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
830159ac0c16Sdavemq 				hw_p->platform_type =
830259ac0c16Sdavemq 				    P_NEPTUNE_MARAMBA_P0;
83032d17280bSsbehera 				break;
830400161856Syc148097 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
830559ac0c16Sdavemq 				hw_p->platform_type =
830659ac0c16Sdavemq 				    P_NEPTUNE_MARAMBA_P1;
83072d17280bSsbehera 				break;
83082d17280bSsbehera 			default:
830959ac0c16Sdavemq 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
831059ac0c16Sdavemq 				    "Unknown port %d...Cannot "
83112d17280bSsbehera 				    "determine platform type 10 - 2",
83122d17280bSsbehera 				    i));
83132e59129aSraghus 				goto error_exit;
83142e59129aSraghus 			}
83152e59129aSraghus 
83162d17280bSsbehera 			/*
831700161856Syc148097 			 * Check the clause45 address to determine
83182d17280bSsbehera 			 * if XAUI is in port 0 or port 1.
83192d17280bSsbehera 			 */
83202d17280bSsbehera 			switch (port_fd_arr[0]) {
832100161856Syc148097 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
832200161856Syc148097 				if (port_pcs_dev_id[0]
832300161856Syc148097 				    == PHY_BCM8704_FAMILY ||
832400161856Syc148097 				    port_pma_pmd_dev_id[0]
832500161856Syc148097 				    == PHY_BCM8704_FAMILY) {
832600161856Syc148097 					hw_p->niu_type
832700161856Syc148097 					    = NEPTUNE_1_10GF_3_1GC;
832800161856Syc148097 				} else {
832900161856Syc148097 					hw_p->niu_type
833000161856Syc148097 					    = NEPTUNE_1_TN1010_3_1GC;
833100161856Syc148097 				}
83322d17280bSsbehera 				hw_p->xcvr_addr[0] = port_fd_arr[0];
83332d17280bSsbehera 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
83342d17280bSsbehera 					hw_p->xcvr_addr[i] =
83352d17280bSsbehera 					    phy_fd_arr[i];
83362d17280bSsbehera 				}
83372d17280bSsbehera 				break;
833800161856Syc148097 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
833900161856Syc148097 				if (port_pcs_dev_id[0]
834000161856Syc148097 				    == PHY_BCM8704_FAMILY ||
834100161856Syc148097 				    port_pma_pmd_dev_id[0]
834200161856Syc148097 				    == PHY_BCM8704_FAMILY) {
83432e59129aSraghus 					hw_p->niu_type =
83442e59129aSraghus 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
834500161856Syc148097 				} else {
834600161856Syc148097 					hw_p->niu_type =
834700161856Syc148097 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
834800161856Syc148097 				}
83492d17280bSsbehera 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
83502d17280bSsbehera 				hw_p->xcvr_addr[1] = port_fd_arr[0];
83512d17280bSsbehera 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
83522d17280bSsbehera 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
83532d17280bSsbehera 				break;
83542d17280bSsbehera 			default:
83552e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
83562e59129aSraghus 				    "Unsupported neptune type 11"));
83572e59129aSraghus 				goto error_exit;
835859ac0c16Sdavemq 			}
835959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
836000161856Syc148097 			    "Maramba with 1 XAUI (fiber or copper)"));
836159ac0c16Sdavemq 			break;
836259ac0c16Sdavemq 		default:
836359ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
836459ac0c16Sdavemq 			    "Unsupported neptune type 13"));
836559ac0c16Sdavemq 			goto error_exit;
836659ac0c16Sdavemq 		}
836759ac0c16Sdavemq 		break;
836800161856Syc148097 	case 0: /* 4 ports Neptune based NIC */
836959ac0c16Sdavemq 		switch (total_phy_fd) {
837059ac0c16Sdavemq 		case 4:
837130505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
837230505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
837330505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
837430505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
837559ac0c16Sdavemq 
837659ac0c16Sdavemq 				/*
837759ac0c16Sdavemq 				 * Check the first phy port address against
837859ac0c16Sdavemq 				 * the known phy start addresses to determine
837959ac0c16Sdavemq 				 * the platform type.
838059ac0c16Sdavemq 				 */
83812d17280bSsbehera 				switch (phy_fd_arr[0]) {
838200161856Syc148097 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
838359ac0c16Sdavemq 					hw_p->platform_type =
838459ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
83852d17280bSsbehera 					break;
838600161856Syc148097 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
83872e59129aSraghus 					hw_p->platform_type =
83882e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
83892d17280bSsbehera 					break;
83902d17280bSsbehera 				default:
83912e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
83922e59129aSraghus 					    "Unknown port %d...Cannot "
83932e59129aSraghus 					    "determine platform type", i));
83942e59129aSraghus 					goto error_exit;
839559ac0c16Sdavemq 				}
83962e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
83972d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
83982d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
83992d17280bSsbehera 				}
840059ac0c16Sdavemq 			} else {
840159ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
840259ac0c16Sdavemq 				    "Unsupported neptune type 14"));
840359ac0c16Sdavemq 				goto error_exit;
840459ac0c16Sdavemq 			}
840559ac0c16Sdavemq 			break;
840659ac0c16Sdavemq 		case 3:
840759ac0c16Sdavemq 			/* TODO 3 1G mode */
840859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
840959ac0c16Sdavemq 			    "Unsupported neptune type 15"));
841059ac0c16Sdavemq 			goto error_exit;
841159ac0c16Sdavemq 		case 2:
841259ac0c16Sdavemq 			/* TODO 2 1G mode */
841359a835ddSjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
841459a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
841559a835ddSjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
841659a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
841759a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
841859a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
841959a835ddSjoycey 			} else {
842059a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
842159ac0c16Sdavemq 				    "Unsupported neptune type 16"));
842259ac0c16Sdavemq 				goto error_exit;
842359a835ddSjoycey 			}
842459a835ddSjoycey 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
842559a835ddSjoycey 			    "2 RGMII Fiber ports - RTM"));
842659a835ddSjoycey 			break;
842759a835ddSjoycey 
842859ac0c16Sdavemq 		case 1:
842959ac0c16Sdavemq 			/* TODO 1 1G mode */
843059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
843159ac0c16Sdavemq 			    "Unsupported neptune type 17"));
843259ac0c16Sdavemq 			goto error_exit;
843359ac0c16Sdavemq 		default:
843459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
843559ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
843659ac0c16Sdavemq 			    total_phy_fd));
843759ac0c16Sdavemq 			goto error_exit;
843859ac0c16Sdavemq 		}
843959ac0c16Sdavemq 		break;
844059ac0c16Sdavemq 	default:
844159ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
844259ac0c16Sdavemq 		    "Unsupported neptune type 19"));
844359ac0c16Sdavemq 		goto error_exit;
844459ac0c16Sdavemq 	}
844559ac0c16Sdavemq 
844659ac0c16Sdavemq scan_exit:
844759ac0c16Sdavemq 
844859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
844959ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
845059ac0c16Sdavemq 	return (status);
845159ac0c16Sdavemq 
845259ac0c16Sdavemq error_exit:
845359ac0c16Sdavemq 	return (NXGE_ERROR);
845459ac0c16Sdavemq }
845559ac0c16Sdavemq 
845656d930aeSspeer boolean_t
845756d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
845856d930aeSspeer {
845956d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
846056d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
846156d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
846256d930aeSspeer 		return (B_FALSE);
846356d930aeSspeer 	else
846456d930aeSspeer 		return (B_TRUE);
846556d930aeSspeer }
846659ac0c16Sdavemq 
846759ac0c16Sdavemq static void
846859ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
846959ac0c16Sdavemq 
847059ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
847159ac0c16Sdavemq 	uint8_t xcvr_portn;
847259ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
847359ac0c16Sdavemq 
847459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
847559ac0c16Sdavemq 
847659ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
847700161856Syc148097 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
847859ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
847900161856Syc148097 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
848059ac0c16Sdavemq 	}
848159ac0c16Sdavemq 	/*
848259ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
848359ac0c16Sdavemq 	 * swapped with ethernet port number. This is
848459ac0c16Sdavemq 	 * designed for better signal integrity in routing.
848559ac0c16Sdavemq 	 */
848659ac0c16Sdavemq 	switch (portn) {
848759ac0c16Sdavemq 	case 0:
848859ac0c16Sdavemq 		xcvr_portn += 3;
848959ac0c16Sdavemq 		break;
849059ac0c16Sdavemq 	case 1:
849159ac0c16Sdavemq 		xcvr_portn += 2;
849259ac0c16Sdavemq 		break;
849359ac0c16Sdavemq 	case 2:
849459ac0c16Sdavemq 		xcvr_portn += 1;
849559ac0c16Sdavemq 		break;
849659ac0c16Sdavemq 	case 3:
849759ac0c16Sdavemq 	default:
849859ac0c16Sdavemq 		break;
849959ac0c16Sdavemq 	}
850059ac0c16Sdavemq 
8501321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
850259ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
850359ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
850459ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
850559ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
850659ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
850759ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
8508321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
850959ac0c16Sdavemq 		return;
851059ac0c16Sdavemq 	}
851159ac0c16Sdavemq 
851259ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
851359ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
851459ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
851559ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
851659ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
851759ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
851859ac0c16Sdavemq 	}
851959ac0c16Sdavemq 
8520321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
852159ac0c16Sdavemq }
8522d81011f0Ssbehera 
8523d81011f0Ssbehera static nxge_status_t
8524d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
8525d81011f0Ssbehera {
8526d81011f0Ssbehera 	p_nxge_stats_t	statsp;
8527d81011f0Ssbehera 	uint8_t		xcvr_portn;
8528d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
8529d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
8530d81011f0Ssbehera 	int		status = NXGE_OK;
8531d81011f0Ssbehera 
8532d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
8533d81011f0Ssbehera 
8534d81011f0Ssbehera 	statsp = nxgep->statsp;
8535d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
8536d81011f0Ssbehera 	mii_regs = NULL;
8537d81011f0Ssbehera 	mode.value = 0;
85386b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8539d81011f0Ssbehera #if defined(__i386)
8540d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
8541d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
8542d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
8543d81011f0Ssbehera 		goto fail;
8544d81011f0Ssbehera #else
8545d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
8546d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
8547d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
8548d81011f0Ssbehera 		goto fail;
8549d81011f0Ssbehera #endif
8550d81011f0Ssbehera 	}
8551d81011f0Ssbehera #if defined(__i386)
8552d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
8553d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
8554d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
8555d81011f0Ssbehera 		goto fail;
8556d81011f0Ssbehera 	}
8557d81011f0Ssbehera #else
8558d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
8559d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
8560d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
8561d81011f0Ssbehera 		goto fail;
8562d81011f0Ssbehera 	}
8563d81011f0Ssbehera #endif
8564d81011f0Ssbehera 
8565d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
8566d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
8567d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8568d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
8569d81011f0Ssbehera 	}
8570d81011f0Ssbehera 
8571d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8572d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
8573d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
85746b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
8575d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
8576d81011f0Ssbehera 
8577d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8578d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
8579d81011f0Ssbehera 	return (status);
8580d81011f0Ssbehera fail:
8581d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8582d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
8583d81011f0Ssbehera 	return (NXGE_ERROR);
8584d81011f0Ssbehera }
8585d81011f0Ssbehera 
85861bd6825cSml29623 nxge_status_t
85871bd6825cSml29623 nxge_mac_set_framesize(p_nxge_t nxgep)
85881bd6825cSml29623 {
85891bd6825cSml29623 	npi_attr_t		ap;
85901bd6825cSml29623 	uint8_t			portn;
85911bd6825cSml29623 	npi_handle_t		handle;
85921bd6825cSml29623 	npi_status_t		rs = NPI_SUCCESS;
85931bd6825cSml29623 
85941bd6825cSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
85951bd6825cSml29623 
85961bd6825cSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
85971bd6825cSml29623 	handle = nxgep->npi_handle;
85981bd6825cSml29623 
85991bd6825cSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
86001bd6825cSml29623 	    "==> nxge_mac_sec_framesize: port<%d> "
86011bd6825cSml29623 	    "min framesize %d max framesize %d ",
86021bd6825cSml29623 	    portn,
86031bd6825cSml29623 	    nxgep->mac.minframesize,
86041bd6825cSml29623 	    nxgep->mac.maxframesize));
86051bd6825cSml29623 
86061bd6825cSml29623 	SET_MAC_ATTR2(handle, ap, portn,
86071bd6825cSml29623 	    MAC_PORT_FRAME_SIZE,
86081bd6825cSml29623 	    nxgep->mac.minframesize,
86091bd6825cSml29623 	    nxgep->mac.maxframesize,
86101bd6825cSml29623 	    rs);
86111bd6825cSml29623 	if (rs != NPI_SUCCESS) {
86121bd6825cSml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
86131bd6825cSml29623 		    "<== nxge_mac_set_framesize: failed to configure "
86141bd6825cSml29623 		    "max/min frame size port %d", portn));
86151bd6825cSml29623 
86161bd6825cSml29623 		return (NXGE_ERROR | rs);
86171bd6825cSml29623 	}
86181bd6825cSml29623 
86191bd6825cSml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
86201bd6825cSml29623 	    "<== nxge_mac_set_framesize: port<%d>", portn));
86211bd6825cSml29623 
86221bd6825cSml29623 	return (NXGE_OK);
86231bd6825cSml29623 }
86241bd6825cSml29623 
862500161856Syc148097 static nxge_status_t
862600161856Syc148097 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
862700161856Syc148097     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
862800161856Syc148097 {
862900161856Syc148097 	uint8_t i;
863000161856Syc148097 
863100161856Syc148097 	for (i = 0; i < 4; i++) {
863200161856Syc148097 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
863300161856Syc148097 			return (NXGE_ERROR);
863400161856Syc148097 	}
863500161856Syc148097 
863600161856Syc148097 	*num_xaui = 0;
863700161856Syc148097 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
863800161856Syc148097 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
863900161856Syc148097 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
864000161856Syc148097 	    == TN1010_DEV_ID) &&
864100161856Syc148097 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
864200161856Syc148097 	    == TN1010_DEV_ID))) {
864300161856Syc148097 		(*num_xaui) ++;
864400161856Syc148097 	}
864500161856Syc148097 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
864600161856Syc148097 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
864700161856Syc148097 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
864800161856Syc148097 	    == TN1010_DEV_ID) &&
864900161856Syc148097 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
865000161856Syc148097 	    == TN1010_DEV_ID))) {
865100161856Syc148097 		(*num_xaui) ++;
865200161856Syc148097 	}
865300161856Syc148097 	return (NXGE_OK);
865400161856Syc148097 }
865500161856Syc148097 
865600161856Syc148097 /*
865700161856Syc148097  * Instruction from Teranetics:  Once you detect link is up, go
865800161856Syc148097  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
865900161856Syc148097  * may want to qualify it by first checking Register 30.1.7:6 and
866000161856Syc148097  * making sure it reads "01" (Auto-Neg Complete).
866100161856Syc148097  *
866200161856Syc148097  * If this function is called when the link is down or before auto-
866300161856Syc148097  * negotiation has completed, then the speed of the PHY is not certain.
866400161856Syc148097  * In such cases, this function returns 1G as the default speed with
866500161856Syc148097  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
866600161856Syc148097  * driver based on a default speed because this function will be called
866700161856Syc148097  * again when the link comes up.  Returning NXGE_ERROR, which may
866800161856Syc148097  * cause brutal chain reaction in caller functions, is not necessary.
866900161856Syc148097  */
867000161856Syc148097 static nxge_status_t
867100161856Syc148097 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
867200161856Syc148097 {
867300161856Syc148097 	uint8_t		phy_port_addr, autoneg_stat, link_up;
867400161856Syc148097 	nxge_status_t	status = NXGE_OK;
867500161856Syc148097 	uint16_t	val;
867600161856Syc148097 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
867700161856Syc148097 
867800161856Syc148097 	/* Set default speed to 10G */
867900161856Syc148097 	*speed = TN1010_SPEED_10G;
868000161856Syc148097 
868100161856Syc148097 	/* Set Clause 45 */
868200161856Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
868300161856Syc148097 
868400161856Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
868500161856Syc148097 
868600161856Syc148097 	/* Check Device 1 Register 0xA bit0 for link up status */
868700161856Syc148097 	status = nxge_mdio_read(nxgep, phy_port_addr,
868800161856Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
868900161856Syc148097 	if (status != NXGE_OK)
869000161856Syc148097 		goto fail;
869100161856Syc148097 
869200161856Syc148097 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
869300161856Syc148097 	    ? B_TRUE : B_FALSE);
869400161856Syc148097 	if (link_up == B_FALSE) {
869500161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
869600161856Syc148097 		    "nxge_get_tn1010_speed: link is down"));
869700161856Syc148097 		goto nxge_get_tn1010_speed_exit;
869800161856Syc148097 	}
869900161856Syc148097 
870000161856Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
870100161856Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
870200161856Syc148097 	    &val)) != NXGE_OK) {
870300161856Syc148097 		goto fail;
870400161856Syc148097 	}
870500161856Syc148097 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
870600161856Syc148097 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
870700161856Syc148097 
870800161856Syc148097 	/*
870900161856Syc148097 	 * Return NXGE_OK even when we can not get a settled speed. In
871000161856Syc148097 	 * such case, the speed reported should not be trusted but that
871100161856Syc148097 	 * is OK, we will call this function periodically and will get
871200161856Syc148097 	 * the correct speed after the link is up.
871300161856Syc148097 	 */
871400161856Syc148097 	switch (autoneg_stat) {
871500161856Syc148097 	case TN1010_AN_IN_PROG:
871600161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
871700161856Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
871800161856Syc148097 		break;
871900161856Syc148097 	case TN1010_AN_COMPLETE:
872000161856Syc148097 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
872100161856Syc148097 		    TN1010_VENDOR_MMD1_DEV_ADDR,
872200161856Syc148097 		    TN1010_VENDOR_MMD1_STATUS_REG,
872300161856Syc148097 		    &val)) != NXGE_OK) {
872400161856Syc148097 			goto fail;
872500161856Syc148097 		}
872600161856Syc148097 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
872700161856Syc148097 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
872800161856Syc148097 		break;
872900161856Syc148097 	case TN1010_AN_RSVD:
873000161856Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
873100161856Syc148097 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
873200161856Syc148097 		break;
873300161856Syc148097 	case TN1010_AN_FAILED:
873400161856Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
873500161856Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
873600161856Syc148097 		break;
873700161856Syc148097 	default:
873800161856Syc148097 		break;
873900161856Syc148097 	}
874000161856Syc148097 nxge_get_tn1010_speed_exit:
874100161856Syc148097 	return (NXGE_OK);
874200161856Syc148097 fail:
874300161856Syc148097 	return (status);
874400161856Syc148097 }
874500161856Syc148097 
874600161856Syc148097 
874700161856Syc148097 /*
874800161856Syc148097  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
874900161856Syc148097  * figures out the speed of the PHY determined by the autonegotiation
875000161856Syc148097  * process and sets the following 3 parameters,
875100161856Syc148097  * 	nxgep->mac.portmode
875200161856Syc148097  *     	nxgep->statsp->mac_stats.link_speed
875300161856Syc148097  *	nxgep->statsp->mac_stats.xcvr_inuse
875400161856Syc148097  */
875500161856Syc148097 static nxge_status_t
875600161856Syc148097 nxge_set_tn1010_param(p_nxge_t nxgep)
875700161856Syc148097 {
875800161856Syc148097 	uint16_t speed;
875900161856Syc148097 
876000161856Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
876100161856Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
876200161856Syc148097 		    "nxge_set_tn1010_param: "
876300161856Syc148097 		    "Failed to get TN1010 speed"));
876400161856Syc148097 		return (NXGE_ERROR);
876500161856Syc148097 	}
876600161856Syc148097 	if (speed == TN1010_SPEED_1G) {
876700161856Syc148097 		nxgep->mac.portmode = PORT_1G_TN1010;
876800161856Syc148097 		nxgep->statsp->mac_stats.link_speed = 1000;
876900161856Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
877000161856Syc148097 	} else {
877100161856Syc148097 		nxgep->mac.portmode = PORT_10G_TN1010;
877200161856Syc148097 		nxgep->statsp->mac_stats.link_speed = 10000;
877300161856Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
877400161856Syc148097 	}
877500161856Syc148097 	return (NXGE_OK);
877600161856Syc148097 }
877700161856Syc148097 
8778d81011f0Ssbehera #ifdef NXGE_DEBUG
8779d81011f0Ssbehera static void
8780d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
8781d81011f0Ssbehera {
8782d81011f0Ssbehera 	p_nxge_stats_t	statsp;
8783d81011f0Ssbehera 	uint8_t		xcvr_portn;
8784d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
8785d81011f0Ssbehera 	mii_bmcr_t	bmcr;
8786d81011f0Ssbehera 	mii_bmsr_t	bmsr;
8787d81011f0Ssbehera 	mii_idr1_t	idr1;
8788d81011f0Ssbehera 	mii_idr2_t	idr2;
8789d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
8790678453a8Sspeer 	p_nxge_param_t	param_arr;
8791d81011f0Ssbehera 
8792d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
8793d81011f0Ssbehera 
8794d81011f0Ssbehera 	statsp = nxgep->statsp;
8795d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
8796d81011f0Ssbehera 
8797d81011f0Ssbehera 	mii_regs = NULL;
8798d81011f0Ssbehera 
8799d81011f0Ssbehera #if defined(__i386)
8800d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8801d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
8802d81011f0Ssbehera #else
8803d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
8804d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
8805d81011f0Ssbehera #endif
8806d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8807d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
8808d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
8809d81011f0Ssbehera 
8810d81011f0Ssbehera #if defined(__i386)
8811d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8812d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8813d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
8814d81011f0Ssbehera #else
8815d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8816d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8817d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
8818d81011f0Ssbehera #endif
8819d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8820d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
8821d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
8822d81011f0Ssbehera 
8823d81011f0Ssbehera #if defined(__i386)
8824d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8825d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8826d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
8827d81011f0Ssbehera #else
8828d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8829d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8830d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
8831d81011f0Ssbehera #endif
8832d81011f0Ssbehera 
8833d81011f0Ssbehera 
8834d81011f0Ssbehera #if defined(__i386)
8835d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8836d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8837d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
8838d81011f0Ssbehera #else
8839d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
8840d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
8841d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
8842d81011f0Ssbehera #endif
8843d81011f0Ssbehera 
8844d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8845d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
8846d81011f0Ssbehera 	    xcvr_portn, idr1.value));
8847d81011f0Ssbehera 
8848d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8849d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
8850d81011f0Ssbehera 	    xcvr_portn, idr2.value));
8851d81011f0Ssbehera 
8852d81011f0Ssbehera 	mode.value = 0;
88536b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
8854d81011f0Ssbehera 
8855d81011f0Ssbehera #if defined(__i386)
8856d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
8857d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
8858d81011f0Ssbehera 
8859d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
8860d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
8861d81011f0Ssbehera #else
8862d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
8863d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
8864d81011f0Ssbehera 
8865d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
8866d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
8867d81011f0Ssbehera #endif
8868d81011f0Ssbehera 
8869d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8870d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
8871d81011f0Ssbehera 	    xcvr_portn, mode.value));
8872d81011f0Ssbehera }
8873d81011f0Ssbehera #endif
8874