xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision b1000363)
144961713Sgirish /*
244961713Sgirish  * CDDL HEADER START
344961713Sgirish  *
444961713Sgirish  * The contents of this file are subject to the terms of the
544961713Sgirish  * Common Development and Distribution License (the "License").
644961713Sgirish  * You may not use this file except in compliance with the License.
744961713Sgirish  *
844961713Sgirish  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
944961713Sgirish  * or http://www.opensolaris.org/os/licensing.
1044961713Sgirish  * See the License for the specific language governing permissions
1144961713Sgirish  * and limitations under the License.
1244961713Sgirish  *
1344961713Sgirish  * When distributing Covered Code, include this CDDL HEADER in each
1444961713Sgirish  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1544961713Sgirish  * If applicable, add the following below this CDDL HEADER, with the
1644961713Sgirish  * fields enclosed by brackets "[]" replaced with your own identifying
1744961713Sgirish  * information: Portions Copyright [yyyy] [name of copyright owner]
1844961713Sgirish  *
1944961713Sgirish  * CDDL HEADER END
2044961713Sgirish  */
2144961713Sgirish /*
2253560810Ssbehera  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish #include <sys/nxge/nxge_impl.h>
2944961713Sgirish #include <sys/nxge/nxge_mac.h>
30678453a8Sspeer #include <sys/nxge/nxge_hio.h>
3144961713Sgirish 
3298ecde52Stm #define	LINK_MONITOR_PERIOD	(1000 * 1000)
3398ecde52Stm #define	LM_WAIT_MULTIPLIER	8
3498ecde52Stm 
35321febdeSsbehera #define	SERDES_RDY_WT_INTERVAL	50
36321febdeSsbehera #define	MAX_SERDES_RDY_RETRIES	10
37321febdeSsbehera 
3800161856Syc #define	TN1010_SPEED_1G		1
3900161856Syc #define	TN1010_SPEED_10G	0
4000161856Syc #define	TN1010_AN_IN_PROG	0	/* Auto negotiation in progress */
4100161856Syc #define	TN1010_AN_COMPLETE	1
4200161856Syc #define	TN1010_AN_RSVD		2
4300161856Syc #define	TN1010_AN_FAILED	3
4400161856Syc 
4544961713Sgirish extern uint32_t nxge_no_link_notify;
4659ac0c16Sdavemq extern boolean_t nxge_no_msg;
4744961713Sgirish extern uint32_t nxge_lb_dbg;
4844961713Sgirish extern boolean_t nxge_jumbo_enable;
494202ea4bSsbehera extern uint32_t nxge_jumbo_mtu;
5044961713Sgirish 
51678453a8Sspeer 	/* The following functions may be found in nxge_main.c */
52678453a8Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot,
53678453a8Sspeer 	boolean_t factory);
54678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr);
55678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot);
56678453a8Sspeer 
5798ecde52Stm typedef enum {
5898ecde52Stm 	CHECK_LINK_RESCHEDULE,
5998ecde52Stm 	CHECK_LINK_STOP
6098ecde52Stm } check_link_state_t;
6198ecde52Stm 
6298ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *);
6398ecde52Stm 
6444961713Sgirish /*
6544961713Sgirish  * Ethernet broadcast address definition.
6644961713Sgirish  */
6744961713Sgirish static ether_addr_st etherbroadcastaddr =
6844961713Sgirish 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
6959ac0c16Sdavemq /*
7059ac0c16Sdavemq  * Ethernet zero address definition.
7159ac0c16Sdavemq  */
7256d930aeSspeer static ether_addr_st etherzeroaddr =
7356d930aeSspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
7459ac0c16Sdavemq /*
7559ac0c16Sdavemq  * Supported chip types
7659ac0c16Sdavemq  */
7752cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = {
7852cdd236Ssbehera 	BCM8704_DEV_ID,
7952cdd236Ssbehera 	MARVELL_88X_201X_DEV_ID,
8000161856Syc 	BCM8706_DEV_ID,
8100161856Syc 	TN1010_DEV_ID
8252cdd236Ssbehera };
8352cdd236Ssbehera 
84*b1000363Sml static uint32_t nxge_supported_cl22_ids[] = {
85*b1000363Sml     BCM5464R_PHY_ID,
86*b1000363Sml     BCM5482_PHY_ID
87*b1000363Sml };
8859ac0c16Sdavemq 
8959ac0c16Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
9059ac0c16Sdavemq 				sizeof (uint32_t))
9159ac0c16Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
9259ac0c16Sdavemq 				sizeof (uint32_t))
9359ac0c16Sdavemq /*
9459ac0c16Sdavemq  * static functions
9559ac0c16Sdavemq  */
962e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
972e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
982e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
9959ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
1002d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
10159ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
10259ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
10359ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
10459ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
10559ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
10659ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
10759ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
10859ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
10959ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
11059ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
11159ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
11259ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1132d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1142d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
11559ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
11659ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
11700161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
11852cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
11900161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
12000161856Syc 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
12100161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
12200161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
12300161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
12400161856Syc 	nxge_link_state_t *link_up);
12500161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
12600161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
12700161856Syc 
12800161856Syc nxge_status_t nxge_mac_init(p_nxge_t);
12900161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
13000161856Syc 
13100161856Syc #ifdef NXGE_DEBUG
13200161856Syc static void nxge_mii_dump(p_nxge_t);
13300161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
13400161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
13500161856Syc #endif
13659ac0c16Sdavemq 
13759ac0c16Sdavemq /*
13859ac0c16Sdavemq  * xcvr tables for supported transceivers
13959ac0c16Sdavemq  */
14059ac0c16Sdavemq 
14100161856Syc /*
14200161856Syc  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
14300161856Syc  * The Teranetics TN1010 based copper XAUI card can also be used
14400161856Syc  * on N2-NIU systems in 10G mode, but it uses its own table
14500161856Syc  * nxge_n2_10G_tn1010_table below.
14600161856Syc  */
1472e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
14859ac0c16Sdavemq 	nxge_n2_serdes_init,
14959ac0c16Sdavemq 	nxge_10G_xcvr_init,
15059ac0c16Sdavemq 	nxge_10G_link_intr_stop,
15159ac0c16Sdavemq 	nxge_10G_link_intr_start,
15259ac0c16Sdavemq 	nxge_check_10g_link,
1532d17280bSsbehera 	PCS_XCVR
15459ac0c16Sdavemq };
15559ac0c16Sdavemq 
15600161856Syc /*
15700161856Syc  * For the Teranetics TN1010 based copper XAUI card
15800161856Syc  */
15900161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
16000161856Syc 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
16100161856Syc 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
16200161856Syc 	nxge_10G_link_intr_stop,
16300161856Syc 	nxge_10G_link_intr_start,
16400161856Syc 	nxge_check_tn1010_link,		/* Will figure out speed */
16500161856Syc 	XPCS_XCVR
16600161856Syc };
16700161856Syc 
1682e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1692e59129aSraghus 	nxge_n2_serdes_init,
1702e59129aSraghus 	nxge_1G_xcvr_init,
1712e59129aSraghus 	nxge_1G_fiber_link_intr_stop,
1722e59129aSraghus 	nxge_1G_fiber_link_intr_start,
1732e59129aSraghus 	nxge_check_mii_link,
1742d17280bSsbehera 	PCS_XCVR
1752e59129aSraghus };
1762e59129aSraghus 
17700161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
17800161856Syc 	nxge_n2_serdes_init,
17900161856Syc 	nxge_tn1010_xcvr_init,
18000161856Syc 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
18100161856Syc 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
18200161856Syc 	nxge_check_tn1010_link,
18300161856Syc 	PCS_XCVR
18400161856Syc };
18500161856Syc 
18600161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = {
18700161856Syc 	nxge_neptune_10G_serdes_init,
18800161856Syc 	nxge_tn1010_xcvr_init,
18900161856Syc 	nxge_10G_link_intr_stop,
19000161856Syc 	nxge_10G_link_intr_start,
19100161856Syc 	nxge_check_tn1010_link,
19200161856Syc 	XPCS_XCVR
19300161856Syc };
19400161856Syc 
19500161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = {
19600161856Syc 	nxge_1G_serdes_init,
19700161856Syc 	nxge_tn1010_xcvr_init,
19800161856Syc 	nxge_1G_fiber_link_intr_stop,
19900161856Syc 	nxge_1G_fiber_link_intr_start,
20000161856Syc 	nxge_check_tn1010_link,
20100161856Syc 	PCS_XCVR
20200161856Syc };
20300161856Syc 
20459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
20559ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
20659ac0c16Sdavemq 	nxge_10G_xcvr_init,
20759ac0c16Sdavemq 	nxge_10G_link_intr_stop,
20859ac0c16Sdavemq 	nxge_10G_link_intr_start,
20959ac0c16Sdavemq 	nxge_check_10g_link,
2102d17280bSsbehera 	PCS_XCVR
21159ac0c16Sdavemq };
21259ac0c16Sdavemq 
21359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
21459ac0c16Sdavemq 	NULL,
21559ac0c16Sdavemq 	nxge_1G_xcvr_init,
21659ac0c16Sdavemq 	nxge_1G_copper_link_intr_stop,
21759ac0c16Sdavemq 	nxge_1G_copper_link_intr_start,
21859ac0c16Sdavemq 	nxge_check_mii_link,
2192d17280bSsbehera 	INT_MII_XCVR
22059ac0c16Sdavemq };
22159ac0c16Sdavemq 
22200161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */
22359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
22459ac0c16Sdavemq 	nxge_1G_serdes_init,
22559ac0c16Sdavemq 	nxge_1G_xcvr_init,
22659ac0c16Sdavemq 	nxge_1G_fiber_link_intr_stop,
22759ac0c16Sdavemq 	nxge_1G_fiber_link_intr_start,
22859ac0c16Sdavemq 	nxge_check_mii_link,
2292d17280bSsbehera 	PCS_XCVR
23059ac0c16Sdavemq };
23159ac0c16Sdavemq 
23259ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
23359ac0c16Sdavemq 	nxge_neptune_10G_serdes_init,
23459ac0c16Sdavemq 	NULL,
23559ac0c16Sdavemq 	NULL,
23659ac0c16Sdavemq 	NULL,
2372e59129aSraghus 	NULL,
2382d17280bSsbehera 	PCS_XCVR
23959ac0c16Sdavemq };
24044961713Sgirish 
24100161856Syc /*
24200161856Syc  * NXGE_PORT_TN1010 is defined as,
24300161856Syc  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
24400161856Syc  *	= 0 | 5 << 16 = 0x50000
24500161856Syc  *
24600161856Syc  * So NEPTUNE_2_TN1010 =
24700161856Syc  *      (NXGE_PORT_TN1010 |
24800161856Syc  *      (NXGE_PORT_TN1010 << 4) |
24900161856Syc  *      (NXGE_PORT_NONE << 8) |
25000161856Syc  *      (NXGE_PORT_NONE << 12)),
25100161856Syc  *      = 0x50000 | (0x50000 << 4)
25200161856Syc  *	= 0x550000
25300161856Syc  *
25400161856Syc  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
25500161856Syc  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
25600161856Syc  * = 0x50000
25700161856Syc  */
25800161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
25900161856Syc {
26000161856Syc 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
26100161856Syc 
26200161856Syc 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
26300161856Syc 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
26400161856Syc 		return (B_TRUE);
26500161856Syc 	} else {
26600161856Syc 		return (B_FALSE);
26700161856Syc 	}
26800161856Syc }
26944961713Sgirish 
270d81011f0Ssbehera 
27100161856Syc /*
27200161856Syc  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
27300161856Syc  * serial EEPROM or VPD if possible.  Note that not all systems could get
27400161856Syc  * the portmode information by calling this function.  For example, the
27500161856Syc  * Maramba system figures out the portmode information by calling function
27600161856Syc  * nxge_setup_xcvr_table.
27700161856Syc  */
2782e59129aSraghus nxge_status_t
2792e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep)
2802e59129aSraghus {
2812e59129aSraghus 	nxge_status_t status = NXGE_OK;
2822e59129aSraghus 	char *phy_type;
2832e59129aSraghus 	char *prop_val;
28400161856Syc 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2852e59129aSraghus 
2862e59129aSraghus 	nxgep->mac.portmode = 0;
2872d17280bSsbehera 	nxgep->xcvr_addr = 0;
2882e59129aSraghus 
2892d17280bSsbehera 	/*
2902d17280bSsbehera 	 * First check for hot swappable phy property.
2912d17280bSsbehera 	 */
2922d17280bSsbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
2932d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2942d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2952d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
2962d17280bSsbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
2972d17280bSsbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2982d17280bSsbehera 	    "hot-swappable-phy") == 1) {
2992d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3002d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3012d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
3022d17280bSsbehera 	} else if (nxgep->niu_type == N2_NIU &&
3032d17280bSsbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
3042d17280bSsbehera 	    "hot-swappable-phy") == 1) {
3052d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3062d17280bSsbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3072d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3082d17280bSsbehera 	}
3092d17280bSsbehera 
3102d17280bSsbehera 	/*
3112d17280bSsbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3122d17280bSsbehera 	 */
3132d17280bSsbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3142d17280bSsbehera 		nxgep->hot_swappable_phy = B_TRUE;
3152d17280bSsbehera 		/*
3162d17280bSsbehera 		 * If this is the 2nd NIU port, then check 2 addresses
3172d17280bSsbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
3182d17280bSsbehera 		 * (in the eval board) or 20 (in the P0 board).
3192d17280bSsbehera 		 */
3202d17280bSsbehera 		if (portn == 1) {
3212d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
32200161856Syc 			    ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID,
3232d17280bSsbehera 			    BCM_PHY_ID_MASK)) {
3242d17280bSsbehera 				nxgep->xcvr_addr =
32500161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR;
3262d17280bSsbehera 				goto found_phy;
3272d17280bSsbehera 			}
3282d17280bSsbehera 		}
3292d17280bSsbehera 		if (nxge_is_phy_present(nxgep,
33000161856Syc 		    GOA_CLAUSE45_PORT_ADDR_BASE + portn,
3312d17280bSsbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
33200161856Syc 			nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE +
3332d17280bSsbehera 			    portn;
3342d17280bSsbehera 			goto found_phy;
3352d17280bSsbehera 		}
3362d17280bSsbehera 
3372d17280bSsbehera 		nxgep->phy_absent = B_TRUE;
3382d17280bSsbehera 		goto check_phy_done;
3392d17280bSsbehera found_phy:
3402d17280bSsbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3412d17280bSsbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3422d17280bSsbehera 		nxgep->phy_absent = B_FALSE;
3432d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3442d17280bSsbehera 		    "found for hot swappable phy"));
3452d17280bSsbehera check_phy_done:
3462d17280bSsbehera 		return (status);
3472d17280bSsbehera 	}
3482d17280bSsbehera 
34900161856Syc 	/* Get phy-type property (May have been set by nxge.conf) */
3502e59129aSraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3512e59129aSraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3522e59129aSraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3532e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3542e59129aSraghus 		    "found  conf file: phy-type %s", prop_val));
3552e59129aSraghus 		if (strcmp("xgsd", prop_val) == 0) {
3562e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3572e59129aSraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3582e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3592e59129aSraghus 			    "found: 10G Serdes"));
3602e59129aSraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3612e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3622e59129aSraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3632e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3642e59129aSraghus 		} else if (strcmp("mif", prop_val) == 0) {
3652e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3662e59129aSraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3672e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3682e59129aSraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3692e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3702e59129aSraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3712e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
372321febdeSsbehera 		} else if (strcmp("xgf", prop_val) == 0) {
37300161856Syc 			/*
37400161856Syc 			 * Before OBP supports new phy-type property
37500161856Syc 			 * value "xgc", the 10G copper XAUI may carry
37600161856Syc 			 * "xgf" instead of "xgc". If the OBP is
37700161856Syc 			 * upgraded to a newer version which supports
37800161856Syc 			 * "xgc", then the TN1010 related code in this
37900161856Syc 			 * "xgf" case will not be used anymore.
38000161856Syc 			 */
38100161856Syc 			if (nxge_is_tn1010_phy(nxgep)) {
38200161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
38300161856Syc 				    != NXGE_OK) {
38400161856Syc 					return (status);
38500161856Syc 				}
38600161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
38700161856Syc 			} else {  /* For Fiber XAUI */
38800161856Syc 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
38900161856Syc 				nxgep->mac.portmode = PORT_10G_FIBER;
39000161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39100161856Syc 				    "10G Fiber Xcvr"));
39200161856Syc 			}
39300161856Syc 		} else if (strcmp("xgc", prop_val) == 0) {
39400161856Syc 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
39500161856Syc 				return (status);
39600161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
3972e59129aSraghus 		}
3982e59129aSraghus 
3992e59129aSraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
4002e59129aSraghus 		    "phy-type", prop_val);
4012e59129aSraghus 		ddi_prop_free(prop_val);
4022e59129aSraghus 
4032e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4042e59129aSraghus 		    "Got phy type [0x%x] from conf file",
4052e59129aSraghus 		    nxgep->mac.portmode));
4062e59129aSraghus 
4072e59129aSraghus 		return (NXGE_OK);
4082e59129aSraghus 	}
4092d17280bSsbehera 
4102d17280bSsbehera 	/* Get phy-type property from OBP */
4112e59129aSraghus 	if (nxgep->niu_type == N2_NIU) {
4122e59129aSraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4132e59129aSraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4142e59129aSraghus 			if (strcmp("xgf", prop_val) == 0) {
41500161856Syc 				/*
41600161856Syc 				 * Before OBP supports new phy-type property
41700161856Syc 				 * value "xgc", the 10G copper XAUI may carry
41800161856Syc 				 * "xgf" instead of "xgc". If the OBP is
41900161856Syc 				 * upgraded to a newer version which supports
42000161856Syc 				 * "xgc", then the TN1010 related code in this
42100161856Syc 				 * "xgf" case will not be used anymore.
42200161856Syc 				 */
42300161856Syc 				if (nxge_is_tn1010_phy(nxgep)) {
42400161856Syc 					if ((status =
42500161856Syc 					    nxge_set_tn1010_param(nxgep))
42600161856Syc 					    != NXGE_OK) {
42700161856Syc 						return (status);
42800161856Syc 					}
42900161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43000161856Syc 					    "TN1010 Xcvr"));
43100161856Syc 				} else {  /* For Fiber XAUI */
43200161856Syc 					nxgep->statsp->mac_stats.xcvr_inuse
43300161856Syc 					    = XPCS_XCVR;
43400161856Syc 					nxgep->mac.portmode = PORT_10G_FIBER;
43500161856Syc 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43600161856Syc 					    "10G Fiber Xcvr"));
43700161856Syc 				}
4382e59129aSraghus 			} else if (strcmp("mif", prop_val) == 0) {
4392e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4402e59129aSraghus 				    INT_MII_XCVR;
4412e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4422e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4432e59129aSraghus 				    "1G Copper Xcvr"));
4442e59129aSraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4452e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4462e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4472e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4482e59129aSraghus 				    "1G Fiber Xcvr"));
4492e59129aSraghus 			} else if (strcmp("xgc", prop_val) == 0) {
45000161856Syc 				status = nxge_set_tn1010_param(nxgep);
45100161856Syc 				if (status != NXGE_OK)
45200161856Syc 					return (status);
45300161856Syc 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4542e59129aSraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4552e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4562e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4572e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4582e59129aSraghus 				    "OBP: 10G Serdes"));
4592e59129aSraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4602e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4612e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4622e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4632e59129aSraghus 				    "OBP: 1G Serdes"));
4642e59129aSraghus 			} else {
4652e59129aSraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4662e59129aSraghus 				    "Unknown phy-type: %s", prop_val));
4672e59129aSraghus 				ddi_prop_free(prop_val);
4682e59129aSraghus 				return (NXGE_ERROR);
4692e59129aSraghus 			}
4702e59129aSraghus 			status = NXGE_OK;
4712e59129aSraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4722e59129aSraghus 			    nxgep->dip, "phy-type", prop_val);
4732e59129aSraghus 			ddi_prop_free(prop_val);
4742e59129aSraghus 
4752e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4762e59129aSraghus 			    "Got phy type [0x%x] from OBP",
4772e59129aSraghus 			    nxgep->mac.portmode));
4782e59129aSraghus 
4792e59129aSraghus 			return (status);
4802e59129aSraghus 		} else {
4812e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4822e59129aSraghus 			    "Exiting...phy-type property not found"));
4832e59129aSraghus 			return (NXGE_ERROR);
4842e59129aSraghus 		}
4852e59129aSraghus 	}
4862e59129aSraghus 
4872e59129aSraghus 
4882e59129aSraghus 	if (!nxgep->vpd_info.present) {
4892e59129aSraghus 		return (NXGE_OK);
4902e59129aSraghus 	}
4912e59129aSraghus 
4922e59129aSraghus 	if (!nxgep->vpd_info.ver_valid) {
4932e59129aSraghus 		goto read_seeprom;
4942e59129aSraghus 	}
4952e59129aSraghus 
4962e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4972e59129aSraghus 	    "Reading phy type from expansion ROM"));
4982e59129aSraghus 	/*
4992e59129aSraghus 	 * Try to read the phy type from the vpd data read off the
5002e59129aSraghus 	 * expansion ROM.
5012e59129aSraghus 	 */
5022e59129aSraghus 	phy_type = nxgep->vpd_info.phy_type;
5032e59129aSraghus 
504d81011f0Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
5052e59129aSraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
5062e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
507d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5082e59129aSraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5092e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
510d81011f0Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5112e59129aSraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5122e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
513d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
51400161856Syc 		status = nxge_set_tn1010_param(nxgep);
51500161856Syc 		if (status != NXGE_OK) {
51600161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51700161856Syc 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
51800161856Syc 			goto read_seeprom;
51900161856Syc 		}
520d81011f0Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
521d81011f0Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
522d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
523d81011f0Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
524d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
525d81011f0Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5262e59129aSraghus 	} else {
527d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5282e59129aSraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5292e59129aSraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5302e59129aSraghus 		goto read_seeprom;
5312e59129aSraghus 	}
5322e59129aSraghus 
5332e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5342e59129aSraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5352e59129aSraghus 
5362e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5372e59129aSraghus 	return (status);
5382e59129aSraghus 
5392e59129aSraghus read_seeprom:
5402e59129aSraghus 	/*
5412e59129aSraghus 	 * read the phy type from the SEEPROM - NCR registers
5422e59129aSraghus 	 */
5432e59129aSraghus 	status = nxge_espc_phy_type_get(nxgep);
5442e59129aSraghus 	if (status != NXGE_OK) {
5452e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5462e59129aSraghus 		    "Failed to get phy type"));
5472e59129aSraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5482e59129aSraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5492e59129aSraghus 	}
5502e59129aSraghus 
5512e59129aSraghus 	return (status);
5522e59129aSraghus 
5532e59129aSraghus }
5542e59129aSraghus 
55559ac0c16Sdavemq /* Set up the PHY specific values. */
55659ac0c16Sdavemq 
55759ac0c16Sdavemq nxge_status_t
55859ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
55959ac0c16Sdavemq {
56059ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
56159ac0c16Sdavemq 	uint32_t	port_type;
56259ac0c16Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5632e59129aSraghus 	uint32_t	pcs_id = 0;
5642e59129aSraghus 	uint32_t	pma_pmd_id = 0;
5652e59129aSraghus 	uint32_t	phy_id = 0;
5662d17280bSsbehera 	uint16_t	chip_id = 0;
56759ac0c16Sdavemq 
56859ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
56959ac0c16Sdavemq 	    portn));
57059ac0c16Sdavemq 
5712e59129aSraghus 	switch (nxgep->niu_type) {
5722e59129aSraghus 	case N2_NIU:
5732e59129aSraghus 		switch (nxgep->mac.portmode) {
5742e59129aSraghus 		case PORT_1G_FIBER:
5752e59129aSraghus 		case PORT_1G_SERDES:
5762e59129aSraghus 			nxgep->xcvr = nxge_n2_1G_table;
5772d17280bSsbehera 			nxgep->xcvr_addr = portn;
5782e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5792e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5802e59129aSraghus 			    "Serdes"));
5812e59129aSraghus 			break;
5822e59129aSraghus 		case PORT_10G_FIBER:
5832e59129aSraghus 		case PORT_10G_SERDES:
5842e59129aSraghus 			nxgep->xcvr = nxge_n2_10G_table;
5852d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5862d17280bSsbehera 				nxgep->xcvr_addr =
5872d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5882d17280bSsbehera 			}
5892e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
5902e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
5912e59129aSraghus 			    "Serdes"));
5922e59129aSraghus 			break;
59300161856Syc 		case PORT_1G_TN1010:
59400161856Syc 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
59500161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
59600161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
59700161856Syc 			    "TN1010 Copper Xcvr in 1G"));
59800161856Syc 			break;
59900161856Syc 		case PORT_10G_TN1010:
60000161856Syc 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
60100161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
60200161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60300161856Syc 			    "TN1010 Copper Xcvr in 10G"));
60400161856Syc 			break;
6052d17280bSsbehera 		case PORT_HSP_MODE:
6062d17280bSsbehera 			nxgep->xcvr = nxge_n2_10G_table;
6072d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6082d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6092d17280bSsbehera 			    "Swappable Xcvr (not present)"));
6102d17280bSsbehera 			break;
6112e59129aSraghus 		default:
6122e59129aSraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6132e59129aSraghus 			    "<== nxge_setup_xcvr_table: "
6142e59129aSraghus 			    "Unable to determine NIU portmode"));
6152e59129aSraghus 			return (NXGE_ERROR);
6162e59129aSraghus 		}
6172e59129aSraghus 		break;
6182e59129aSraghus 	default:
6192e59129aSraghus 		if (nxgep->mac.portmode == 0) {
6202e59129aSraghus 			/*
6212e59129aSraghus 			 * Would be the case for platforms like Maramba
6222e59129aSraghus 			 * in which the phy type could not be got from conf
6232e59129aSraghus 			 * file, OBP, VPD or Serial PROM.
6242e59129aSraghus 			 */
6252e59129aSraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6262e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6272e59129aSraghus 				    "<== nxge_setup_xcvr_table:"
6282e59129aSraghus 				    " Invalid Neptune type [0x%x]",
6292e59129aSraghus 				    nxgep->niu_type));
6302e59129aSraghus 				return (NXGE_ERROR);
6312e59129aSraghus 			}
6322e59129aSraghus 
6332e59129aSraghus 			port_type = nxgep->niu_type >>
6342e59129aSraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
6352e59129aSraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6362e59129aSraghus 
6372e59129aSraghus 			switch (port_type) {
6382e59129aSraghus 
6392e59129aSraghus 			case NXGE_PORT_1G_COPPER:
6402e59129aSraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
6412e59129aSraghus 				break;
6422e59129aSraghus 			case NXGE_PORT_10G_COPPER:
6432e59129aSraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6442e59129aSraghus 				break;
6452e59129aSraghus 			case NXGE_PORT_1G_FIBRE:
6462e59129aSraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6472e59129aSraghus 				break;
6482e59129aSraghus 			case NXGE_PORT_10G_FIBRE:
6492e59129aSraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6502e59129aSraghus 				break;
6512e59129aSraghus 			case NXGE_PORT_1G_SERDES:
6522e59129aSraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6532e59129aSraghus 				break;
6542e59129aSraghus 			case NXGE_PORT_10G_SERDES:
6552e59129aSraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6562e59129aSraghus 				break;
65700161856Syc 			/* Ports 2 and 3 of Alonso or ARTM */
6582e59129aSraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6592e59129aSraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6602e59129aSraghus 				break;
66100161856Syc 			case NXGE_PORT_TN1010:
66200161856Syc 				/*
66300161856Syc 				 * If this port uses the TN1010 copper
66400161856Syc 				 * PHY, then its speed is not known yet
66500161856Syc 				 * because nxge_scan_ports_phy could only
66600161856Syc 				 * figure out the vendor of the PHY but
66700161856Syc 				 * not its speed. nxge_set_tn1010_param
66800161856Syc 				 * will read the PHY speed and set
66900161856Syc 				 * portmode accordingly.
67000161856Syc 				 */
67100161856Syc 				if ((status = nxge_set_tn1010_param(nxgep))
67200161856Syc 				    != NXGE_OK) {
67300161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67400161856Syc 					    "nxge_set_tn1010_param failed"));
67500161856Syc 					return (status);
67600161856Syc 				}
67700161856Syc 				break;
6782e59129aSraghus 			default:
6792e59129aSraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6802e59129aSraghus 				    "<== nxge_setup_xcvr_table: "
6812e59129aSraghus 				    "Unknown port-type: 0x%x", port_type));
6822e59129aSraghus 				return (NXGE_ERROR);
6832e59129aSraghus 			}
6842e59129aSraghus 		}
6852e59129aSraghus 
68600161856Syc 		/*
68700161856Syc 		 * Above switch has figured out nxge->mac.portmode, now set
68800161856Syc 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
68900161856Syc 		 * to portmode.
69000161856Syc 		 */
6912e59129aSraghus 		switch (nxgep->mac.portmode) {
6922e59129aSraghus 		case PORT_1G_COPPER:
6932e59129aSraghus 		case PORT_1G_RGMII_FIBER:
69459ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
6952d17280bSsbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
69659ac0c16Sdavemq 			/*
69759ac0c16Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
69859ac0c16Sdavemq 			 * swapped with ethernet port number. This is
6992e59129aSraghus 			 * designed for better signal integrity in
7002e59129aSraghus 			 * routing. This is also the case for the
7012e59129aSraghus 			 * on-board Neptune copper ports on the Maramba
7022e59129aSraghus 			 * platform.
70359ac0c16Sdavemq 			 */
7042e59129aSraghus 			switch (nxgep->platform_type) {
7052e59129aSraghus 			case P_NEPTUNE_ATLAS_4PORT:
7062e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7072e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
7082e59129aSraghus 				switch (portn) {
7092e59129aSraghus 				case 0:
7102d17280bSsbehera 					nxgep->xcvr_addr += 3;
7112e59129aSraghus 					break;
7122e59129aSraghus 				case 1:
7132d17280bSsbehera 					nxgep->xcvr_addr += 1;
7142e59129aSraghus 					break;
7152e59129aSraghus 				case 2:
7162d17280bSsbehera 					nxgep->xcvr_addr -= 1;
7172e59129aSraghus 					break;
7182e59129aSraghus 				case 3:
7192d17280bSsbehera 					nxgep->xcvr_addr -= 3;
7202e59129aSraghus 					break;
7212e59129aSraghus 				default:
7222e59129aSraghus 					return (NXGE_ERROR);
7232e59129aSraghus 				}
72459ac0c16Sdavemq 				break;
72559ac0c16Sdavemq 			default:
7262e59129aSraghus 				break;
72759ac0c16Sdavemq 			}
728d81011f0Ssbehera 
7292e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7302e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7312e59129aSraghus 			    "Copper" : "RGMII Fiber"));
73259ac0c16Sdavemq 			break;
73300161856Syc 
7342e59129aSraghus 		case PORT_10G_COPPER:
73559ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
73659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
73759ac0c16Sdavemq 			break;
73800161856Syc 
73900161856Syc 		case PORT_1G_TN1010:
74000161856Syc 			nxgep->xcvr = nxge_1G_tn1010_table;
74100161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
74200161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
74300161856Syc 			    "1G TN1010 copper Xcvr"));
74400161856Syc 			break;
74500161856Syc 
74600161856Syc 		case PORT_10G_TN1010:
74700161856Syc 			nxgep->xcvr = nxge_10G_tn1010_table;
74800161856Syc 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
74900161856Syc 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
75000161856Syc 			    "10G TN1010 copper Xcvr"));
75100161856Syc 			break;
75200161856Syc 
7532e59129aSraghus 		case PORT_1G_FIBER:
7542e59129aSraghus 		case PORT_1G_SERDES:
75559ac0c16Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7562d17280bSsbehera 			nxgep->xcvr_addr = portn;
7572e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7582e59129aSraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7592e59129aSraghus 			    "Fiber" : "Serdes"));
76059ac0c16Sdavemq 			break;
7612e59129aSraghus 		case PORT_10G_FIBER:
7622e59129aSraghus 		case PORT_10G_SERDES:
76359ac0c16Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7642d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7652d17280bSsbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7662d17280bSsbehera 			    "nxgep->xcvr_addr = [%d]",
7672d17280bSsbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7682d17280bSsbehera 			    nxgep->xcvr_addr));
7692d17280bSsbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7702d17280bSsbehera 				nxgep->xcvr_addr =
7712d17280bSsbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7722d17280bSsbehera 			}
7732e59129aSraghus 			switch (nxgep->platform_type) {
7742e59129aSraghus 			case P_NEPTUNE_MARAMBA_P0:
7752e59129aSraghus 			case P_NEPTUNE_MARAMBA_P1:
77659ac0c16Sdavemq 				/*
77759ac0c16Sdavemq 				 * Switch off LED for corresponding copper
77859ac0c16Sdavemq 				 * port
77959ac0c16Sdavemq 				 */
78059ac0c16Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7812e59129aSraghus 				break;
7822e59129aSraghus 			default:
7832e59129aSraghus 				break;
78459ac0c16Sdavemq 			}
7852e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
7862e59129aSraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
7872e59129aSraghus 			    "Fiber" : "Serdes"));
78859ac0c16Sdavemq 			break;
7892d17280bSsbehera 
7902d17280bSsbehera 		case PORT_HSP_MODE:
7912d17280bSsbehera 			nxgep->xcvr = nxge_10G_fiber_table;
7922d17280bSsbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
7932d17280bSsbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
7942d17280bSsbehera 			    "Swappable Xcvr (not present)"));
7952d17280bSsbehera 			break;
79659ac0c16Sdavemq 		default:
79759ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
79859ac0c16Sdavemq 			    "Unknown port-type: 0x%x", port_type));
79959ac0c16Sdavemq 			return (NXGE_ERROR);
80059ac0c16Sdavemq 		}
80159ac0c16Sdavemq 	}
80259ac0c16Sdavemq 
8032d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
80452cdd236Ssbehera 		uint32_t pma_pmd_id;
80552cdd236Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
80652cdd236Ssbehera 		    nxgep->xcvr_addr);
80752cdd236Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
80852cdd236Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
80952cdd236Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
81052cdd236Ssbehera 			    "nxge_setup_xcvr_table: "
81152cdd236Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
81252cdd236Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8132d17280bSsbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8142d17280bSsbehera 		    &chip_id)) == NXGE_OK) {
8152d17280bSsbehera 
8162d17280bSsbehera 			switch (chip_id) {
8172d17280bSsbehera 			case BCM8704_CHIP_ID:
8182d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8192d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8202d17280bSsbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8212d17280bSsbehera 				    chip_id));
8222d17280bSsbehera 				break;
8232d17280bSsbehera 			case BCM8706_CHIP_ID:
8242d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8252d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8262d17280bSsbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8272d17280bSsbehera 				    chip_id));
8282d17280bSsbehera 				break;
8292d17280bSsbehera 			default:
8302d17280bSsbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8312d17280bSsbehera 				    "nxge_setup_xcvr_table: "
8322d17280bSsbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8332d17280bSsbehera 				    chip_id));
8342d17280bSsbehera 				break;
8352d17280bSsbehera 			}
8362d17280bSsbehera 		}
8372d17280bSsbehera 	}
8382d17280bSsbehera 
83959ac0c16Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8402d17280bSsbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8412d17280bSsbehera 	nxgep->chip_id = chip_id;
8422e59129aSraghus 
8432e59129aSraghus 	/*
8442e59129aSraghus 	 * Get the actual device ID value returned by MDIO read.
8452e59129aSraghus 	 */
8462e59129aSraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8472e59129aSraghus 
8482d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8492e59129aSraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8502e59129aSraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8512e59129aSraghus 	} else {
8522d17280bSsbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8532e59129aSraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8542e59129aSraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8552e59129aSraghus 		} else {
8562e59129aSraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8572d17280bSsbehera 			    nxgep->xcvr_addr);
8582e59129aSraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8592e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8602e59129aSraghus 			}
8612e59129aSraghus 		}
8622e59129aSraghus 	}
8632e59129aSraghus 
86459ac0c16Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
86559ac0c16Sdavemq 
8662e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
8672d17280bSsbehera 	    "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type,
8682d17280bSsbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8692e59129aSraghus 
87059ac0c16Sdavemq 	return (status);
87159ac0c16Sdavemq }
87259ac0c16Sdavemq 
87344961713Sgirish /* Initialize the entire MAC and physical layer */
87444961713Sgirish 
87544961713Sgirish nxge_status_t
87644961713Sgirish nxge_mac_init(p_nxge_t nxgep)
87744961713Sgirish {
87844961713Sgirish 	uint8_t			portn;
87944961713Sgirish 	nxge_status_t		status = NXGE_OK;
88044961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
88144961713Sgirish 
88244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
88344961713Sgirish 
88444961713Sgirish 	nxgep->mac.portnum = portn;
88544961713Sgirish 	nxgep->mac.porttype = PORT_TYPE_XMAC;
88644961713Sgirish 
88744961713Sgirish 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
88844961713Sgirish 		nxgep->mac.porttype = PORT_TYPE_BMAC;
88944961713Sgirish 
89000161856Syc 
89144961713Sgirish 	/* Initialize XIF to configure a network mode */
89244961713Sgirish 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
89344961713Sgirish 		goto fail;
89444961713Sgirish 	}
89544961713Sgirish 
89644961713Sgirish 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
89744961713Sgirish 		goto fail;
89844961713Sgirish 	}
89944961713Sgirish 
90044961713Sgirish 	/* Initialize TX and RX MACs */
90144961713Sgirish 	/*
90244961713Sgirish 	 * Always perform XIF init first, before TX and RX MAC init
90344961713Sgirish 	 */
90444961713Sgirish 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
90544961713Sgirish 		goto fail;
90644961713Sgirish 
90744961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
90844961713Sgirish 		goto fail;
90944961713Sgirish 
91044961713Sgirish 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
91144961713Sgirish 		goto fail;
91244961713Sgirish 
91344961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
91444961713Sgirish 		goto fail;
91544961713Sgirish 
91644961713Sgirish 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
91744961713Sgirish 		goto fail;
91844961713Sgirish 
91944961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
92044961713Sgirish 		goto fail;
92144961713Sgirish 
922cb9d3ae6Smisaki 	/* Initialize MAC control configuration */
923cb9d3ae6Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
924cb9d3ae6Smisaki 		goto fail;
925cb9d3ae6Smisaki 	}
926cb9d3ae6Smisaki 
92744961713Sgirish 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
92844961713Sgirish 
929d81011f0Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
930d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
931d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
93200161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
933d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
934d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
935d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
936d81011f0Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
937d81011f0Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
938d81011f0Ssbehera 			goto fail;
939d81011f0Ssbehera 		}
940d81011f0Ssbehera 	}
941d81011f0Ssbehera 
9422e59129aSraghus 
94344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
94444961713Sgirish 
94544961713Sgirish 	return (NXGE_OK);
94644961713Sgirish fail:
94744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
94844961713Sgirish 			"nxge_mac_init: failed to initialize MAC port<%d>",
94944961713Sgirish 			portn));
95044961713Sgirish 	return (status);
95144961713Sgirish }
95244961713Sgirish 
95344961713Sgirish /* Initialize the Ethernet Link */
95444961713Sgirish 
95544961713Sgirish nxge_status_t
95644961713Sgirish nxge_link_init(p_nxge_t nxgep)
95744961713Sgirish {
95844961713Sgirish 	nxge_status_t		status = NXGE_OK;
9592e59129aSraghus 	nxge_port_mode_t	portmode;
96044961713Sgirish #ifdef	NXGE_DEBUG
96144961713Sgirish 	uint8_t			portn;
96244961713Sgirish 
96344961713Sgirish 	portn = nxgep->mac.portnum;
96444961713Sgirish 
96544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
96644961713Sgirish #endif
9672d17280bSsbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
9682d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
9692d17280bSsbehera 		    "Phy not present, cannot initialize link"));
9702d17280bSsbehera 		return (status);
9712d17280bSsbehera 	}
97244961713Sgirish 
9732e59129aSraghus 	portmode = nxgep->mac.portmode;
9742d17280bSsbehera 
97500161856Syc 	/*
97600161856Syc 	 * Workaround to get link up in both NIU ports. Some portmodes require
97700161856Syc 	 * that the xcvr be initialized twice, the first time before calling
97800161856Syc 	 * nxge_serdes_init.
97900161856Syc 	 */
9802e59129aSraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
98100161856Syc 	    (portmode != PORT_10G_TN1010) &&
98200161856Syc 	    (portmode != PORT_1G_TN1010) &&
9832e59129aSraghus 	    (portmode != PORT_1G_SERDES)) {
9842e59129aSraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
98544961713Sgirish 			goto fail;
9862e59129aSraghus 		}
98744961713Sgirish 	}
98800161856Syc 
98944961713Sgirish 	NXGE_DELAY(200000);
99044961713Sgirish 	/* Initialize internal serdes */
99144961713Sgirish 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
99244961713Sgirish 		goto fail;
99344961713Sgirish 	NXGE_DELAY(200000);
99444961713Sgirish 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
99544961713Sgirish 		goto fail;
99644961713Sgirish 
99744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
99844961713Sgirish 
99944961713Sgirish 	return (NXGE_OK);
100044961713Sgirish 
100144961713Sgirish fail:
100244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
100344961713Sgirish 		"nxge_link_init: ",
100444961713Sgirish 		"failed to initialize Ethernet link on port<%d>",
100544961713Sgirish 		portn));
100644961713Sgirish 
100744961713Sgirish 	return (status);
100844961713Sgirish }
100944961713Sgirish 
101044961713Sgirish 
101144961713Sgirish /* Initialize the XIF sub-block within the MAC */
101244961713Sgirish 
101344961713Sgirish nxge_status_t
101444961713Sgirish nxge_xif_init(p_nxge_t nxgep)
101544961713Sgirish {
101644961713Sgirish 	uint32_t		xif_cfg = 0;
101744961713Sgirish 	npi_attr_t		ap;
101844961713Sgirish 	uint8_t			portn;
101944961713Sgirish 	nxge_port_t		portt;
102044961713Sgirish 	nxge_port_mode_t	portmode;
102144961713Sgirish 	p_nxge_stats_t		statsp;
102244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
102344961713Sgirish 	npi_handle_t		handle;
102444961713Sgirish 
102544961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
102644961713Sgirish 
102744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
102844961713Sgirish 
102944961713Sgirish 	handle = nxgep->npi_handle;
103044961713Sgirish 	portmode = nxgep->mac.portmode;
103144961713Sgirish 	portt = nxgep->mac.porttype;
103244961713Sgirish 	statsp = nxgep->statsp;
103344961713Sgirish 
1034d81011f0Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
1035d81011f0Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
103600161856Syc 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
1037d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
1038d81011f0Ssbehera 	    ((portn == 0) || (portn == 1))) {
1039d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1040d81011f0Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
1041d81011f0Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
1042d81011f0Ssbehera 	}
1043d81011f0Ssbehera 
104444961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
104544961713Sgirish 
104644961713Sgirish 		/* Setup XIF Configuration for XMAC */
104744961713Sgirish 
104844961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
10492e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
105000161856Syc 		    (portmode == PORT_10G_TN1010) ||
10512e59129aSraghus 		    (portmode == PORT_10G_SERDES))
105244961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LFS;
105344961713Sgirish 
105400161856Syc 		/* Bypass PCS so that RGMII will be used */
105544961713Sgirish 		if (portmode == PORT_1G_COPPER) {
105644961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
105744961713Sgirish 		}
105844961713Sgirish 
105944961713Sgirish 		/* Set MAC Internal Loopback if necessary */
106044961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
106144961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
106244961713Sgirish 
106344961713Sgirish 		if (statsp->mac_stats.link_speed == 100)
106444961713Sgirish 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
106544961713Sgirish 
106644961713Sgirish 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
106744961713Sgirish 
10682e59129aSraghus 		if ((portmode == PORT_10G_FIBER) ||
106900161856Syc 		    (portmode == PORT_10G_TN1010) ||
107000161856Syc 		    (portmode == PORT_1G_TN1010) ||
10712e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
107200161856Syc 			/* Assume LED same for 1G and 10G */
107344961713Sgirish 			if (statsp->mac_stats.link_up) {
107444961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
107544961713Sgirish 			} else {
107644961713Sgirish 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
107744961713Sgirish 			}
107844961713Sgirish 		}
107944961713Sgirish 
108044961713Sgirish 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
108144961713Sgirish 		if (rs != NPI_SUCCESS)
108244961713Sgirish 			goto fail;
108344961713Sgirish 
108444961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
108544961713Sgirish 
108644961713Sgirish 		/* Set Port Mode */
108744961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
10882e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
108900161856Syc 		    (portmode == PORT_10G_TN1010) ||
10902e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
109144961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
109244961713Sgirish 						MAC_XGMII_MODE, rs);
109344961713Sgirish 			if (rs != NPI_SUCCESS)
109444961713Sgirish 				goto fail;
109544961713Sgirish 			if (statsp->mac_stats.link_up) {
109644961713Sgirish 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
109744961713Sgirish 					goto fail;
109844961713Sgirish 			} else {
109944961713Sgirish 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
110044961713Sgirish 					goto fail;
110144961713Sgirish 			}
110244961713Sgirish 		} else if ((portmode == PORT_1G_FIBER) ||
11032e59129aSraghus 		    (portmode == PORT_1G_COPPER) ||
1104d81011f0Ssbehera 		    (portmode == PORT_1G_SERDES) ||
110500161856Syc 		    (portmode == PORT_1G_TN1010) ||
1106d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
1107d81011f0Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1108d81011f0Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
1109d81011f0Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
111044961713Sgirish 			if (statsp->mac_stats.link_speed == 1000) {
111144961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
111244961713Sgirish 							MAC_GMII_MODE, rs);
111344961713Sgirish 			} else {
111444961713Sgirish 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
111544961713Sgirish 							MAC_MII_MODE, rs);
111644961713Sgirish 			}
111744961713Sgirish 			if (rs != NPI_SUCCESS)
111844961713Sgirish 				goto fail;
111944961713Sgirish 		} else {
112044961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
112144961713Sgirish 					"nxge_xif_init: Unknown port mode (%d)"
112244961713Sgirish 					" for port<%d>", portmode, portn));
112344961713Sgirish 			goto fail;
112444961713Sgirish 		}
112544961713Sgirish 
1126d81011f0Ssbehera 		/* Enable ATCA mode */
1127d81011f0Ssbehera 
112844961713Sgirish 	} else if (portt == PORT_TYPE_BMAC) {
112944961713Sgirish 
113044961713Sgirish 		/* Setup XIF Configuration for BMAC */
113144961713Sgirish 
1132d81011f0Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
1133d81011f0Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
113444961713Sgirish 			if (statsp->mac_stats.link_speed == 100)
113544961713Sgirish 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
113644961713Sgirish 		}
113744961713Sgirish 
113844961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
113944961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
114044961713Sgirish 
114144961713Sgirish 		if (statsp->mac_stats.link_speed == 1000)
114244961713Sgirish 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
114344961713Sgirish 
114444961713Sgirish 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
114544961713Sgirish 
114644961713Sgirish 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
114744961713Sgirish 		if (rs != NPI_SUCCESS)
114844961713Sgirish 			goto fail;
114944961713Sgirish 		nxgep->mac.xif_config = xif_cfg;
115044961713Sgirish 	}
115144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
115244961713Sgirish 	return (NXGE_OK);
115344961713Sgirish fail:
115444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
115544961713Sgirish 			"nxge_xif_init: Failed to initialize XIF port<%d>",
115644961713Sgirish 			portn));
115744961713Sgirish 	return (NXGE_ERROR | rs);
115844961713Sgirish }
115944961713Sgirish 
116044961713Sgirish 
116100161856Syc /*
116200161856Syc  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
116300161856Syc  * support loopback like XPCS.
116400161856Syc  */
116544961713Sgirish nxge_status_t
116644961713Sgirish nxge_pcs_init(p_nxge_t nxgep)
116744961713Sgirish {
116844961713Sgirish 	pcs_cfg_t		pcs_cfg;
116944961713Sgirish 	uint32_t		val;
117044961713Sgirish 	uint8_t			portn;
117144961713Sgirish 	nxge_port_mode_t	portmode;
117244961713Sgirish 	npi_handle_t		handle;
117344961713Sgirish 	p_nxge_stats_t		statsp;
117400161856Syc 	pcs_ctrl_t		pcs_ctrl;
117544961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
117600161856Syc 	uint8_t i;
117744961713Sgirish 
117844961713Sgirish 	handle = nxgep->npi_handle;
117944961713Sgirish 	portmode = nxgep->mac.portmode;
118044961713Sgirish 	portn = nxgep->mac.portnum;
118144961713Sgirish 	statsp = nxgep->statsp;
118244961713Sgirish 
118344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
118444961713Sgirish 
118500161856Syc 	if (portmode == PORT_1G_FIBER ||
118600161856Syc 	    portmode == PORT_1G_TN1010 ||
118700161856Syc 	    portmode == PORT_1G_SERDES) {
118800161856Syc 		if (portmode == PORT_1G_TN1010) {
118900161856Syc 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
119000161856Syc 			for (i = 0; i < 6; i ++) {
119100161856Syc 				if ((rs = npi_mac_pcs_reset(handle, portn))
119200161856Syc 				    != NPI_SUCCESS) {
119300161856Syc 					goto fail;
119400161856Syc 				}
119500161856Syc 			}
119600161856Syc 		} else {
119700161856Syc 			if ((rs = npi_mac_pcs_reset(handle, portn))
119800161856Syc 			    != NPI_SUCCESS)
119900161856Syc 				goto fail;
12002e59129aSraghus 		}
12012e59129aSraghus 
120244961713Sgirish 		/* Initialize port's PCS */
120344961713Sgirish 		pcs_cfg.value = 0;
120444961713Sgirish 		pcs_cfg.bits.w0.enable = 1;
120544961713Sgirish 		pcs_cfg.bits.w0.mask = 1;
120644961713Sgirish 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
120744961713Sgirish 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
120844961713Sgirish 
12092e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12102e59129aSraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12112e59129aSraghus 		    portn, pcs_cfg.value));
121200161856Syc 
121300161856Syc 		if (portmode == PORT_1G_TN1010) {
121400161856Syc 			/*
121500161856Syc 			 * Must disable PCS auto-negotiation when the the driver
121600161856Syc 			 * is driving the TN1010 based XAUI card  Otherwise the
121700161856Syc 			 * autonegotiation between the PCS and the TN1010 PCS
121800161856Syc 			 * will never complete and the Neptune/NIU will not work
121900161856Syc 			 */
122000161856Syc 			pcs_ctrl.value = 0;
122100161856Syc 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
122200161856Syc 			    pcs_ctrl.value);
122300161856Syc 		}
122400161856Syc 	} else if (portmode == PORT_10G_FIBER ||
122500161856Syc 	    portmode == PORT_10G_COPPER ||
122600161856Syc 	    portmode == PORT_10G_TN1010 ||
122700161856Syc 	    portmode == PORT_10G_SERDES) {
122844961713Sgirish 		/* Use internal XPCS, bypass 1G PCS */
122944961713Sgirish 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
123044961713Sgirish 		val &= ~XMAC_XIF_XPCS_BYPASS;
123144961713Sgirish 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
123244961713Sgirish 
123344961713Sgirish 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
123444961713Sgirish 			goto fail;
123544961713Sgirish 
123644961713Sgirish 		/* Set XPCS Internal Loopback if necessary */
123744961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
123844961713Sgirish 						XPCS_REG_CONTROL1, &val))
123944961713Sgirish 						!= NPI_SUCCESS)
124044961713Sgirish 			goto fail;
124100161856Syc 
124244961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
124344961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_mac1000))
124444961713Sgirish 			val |= XPCS_CTRL1_LOOPBK;
124544961713Sgirish 		else
124644961713Sgirish 			val &= ~XPCS_CTRL1_LOOPBK;
124744961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
124844961713Sgirish 						XPCS_REG_CONTROL1, val))
124944961713Sgirish 						!= NPI_SUCCESS)
125044961713Sgirish 			goto fail;
125144961713Sgirish 
125244961713Sgirish 		/* Clear descw errors */
125344961713Sgirish 		if ((rs = npi_xmac_xpcs_write(handle, portn,
125444961713Sgirish 						XPCS_REG_DESCWERR_COUNTER, 0))
125544961713Sgirish 						!= NPI_SUCCESS)
125644961713Sgirish 			goto fail;
125744961713Sgirish 		/* Clear symbol errors */
125844961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
125944961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val))
126044961713Sgirish 					!= NPI_SUCCESS)
126144961713Sgirish 			goto fail;
126244961713Sgirish 		if ((rs = npi_xmac_xpcs_read(handle, portn,
126344961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val))
126444961713Sgirish 					!= NPI_SUCCESS)
126544961713Sgirish 			goto fail;
126644961713Sgirish 
1267d81011f0Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
1268d81011f0Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
1269d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
1270d81011f0Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
127144961713Sgirish 		if (portn < 4) {
127244961713Sgirish 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
127344961713Sgirish 					PCS_DATAPATH_MODE_MII);
127444961713Sgirish 		}
127544961713Sgirish 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
127644961713Sgirish 			goto fail;
127744961713Sgirish 
127844961713Sgirish 	} else {
127944961713Sgirish 		goto fail;
128044961713Sgirish 	}
128144961713Sgirish pass:
128244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
128344961713Sgirish 	return (NXGE_OK);
128444961713Sgirish fail:
128544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
128644961713Sgirish 			"nxge_pcs_init: Failed to initialize PCS port<%d>",
128744961713Sgirish 			portn));
128844961713Sgirish 	return (NXGE_ERROR | rs);
128944961713Sgirish }
129044961713Sgirish 
1291cb9d3ae6Smisaki /*
1292cb9d3ae6Smisaki  * Initialize the MAC CTRL sub-block within the MAC
1293cb9d3ae6Smisaki  * Only the receive-pause-cap is supported.
1294cb9d3ae6Smisaki  */
1295cb9d3ae6Smisaki nxge_status_t
1296cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
1297cb9d3ae6Smisaki {
1298cb9d3ae6Smisaki 	uint8_t			portn;
1299cb9d3ae6Smisaki 	nxge_port_t		portt;
1300cb9d3ae6Smisaki 	p_nxge_stats_t		statsp;
1301cb9d3ae6Smisaki 	npi_handle_t		handle;
1302cb9d3ae6Smisaki 	uint32_t		val;
1303cb9d3ae6Smisaki 
1304cb9d3ae6Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
1305cb9d3ae6Smisaki 
1306cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
1307cb9d3ae6Smisaki 	    portn));
1308cb9d3ae6Smisaki 
1309cb9d3ae6Smisaki 	handle = nxgep->npi_handle;
1310cb9d3ae6Smisaki 	portt = nxgep->mac.porttype;
1311cb9d3ae6Smisaki 	statsp = nxgep->statsp;
1312cb9d3ae6Smisaki 
1313cb9d3ae6Smisaki 	if (portt == PORT_TYPE_XMAC) {
131400161856Syc 		/* Reading the current XMAC Config Register for XMAC */
1315cb9d3ae6Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
1316cb9d3ae6Smisaki 
1317cb9d3ae6Smisaki 		/*
1318cb9d3ae6Smisaki 		 * Setup XMAC Configuration for XMAC
1319cb9d3ae6Smisaki 		 * XMAC only supports receive-pause
1320cb9d3ae6Smisaki 		 */
1321cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1322cb9d3ae6Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
1323cb9d3ae6Smisaki 				/*
1324cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1325cb9d3ae6Smisaki 				 * is 0, enable receive pause.
1326cb9d3ae6Smisaki 				 */
1327cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1328cb9d3ae6Smisaki 			} else {
1329cb9d3ae6Smisaki 				/*
1330cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1331cb9d3ae6Smisaki 				 * is 1, disable receive pause.  Send pause is
1332cb9d3ae6Smisaki 				 * not supported.
1333cb9d3ae6Smisaki 				 */
1334cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1335cb9d3ae6Smisaki 			}
1336cb9d3ae6Smisaki 		} else {
13371bd6825cSml 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13381bd6825cSml 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13391bd6825cSml 			    portn));
1340cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13411bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13421bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13431bd6825cSml 				    "enable pause", portn));
1344cb9d3ae6Smisaki 				/*
1345cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1346cb9d3ae6Smisaki 				 * is 1, enable receive pause.
1347cb9d3ae6Smisaki 				 */
1348cb9d3ae6Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
1349cb9d3ae6Smisaki 			} else {
1350cb9d3ae6Smisaki 				/*
1351cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1352cb9d3ae6Smisaki 				 * is 0, disable receive pause. Send pause is
1353cb9d3ae6Smisaki 				 * not supported
1354cb9d3ae6Smisaki 				 */
13551bd6825cSml 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13561bd6825cSml 				    "==> nxge_mac_ctrl_init: port<%d>: "
13571bd6825cSml 				    "disable pause", portn));
1358cb9d3ae6Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
1359cb9d3ae6Smisaki 			}
1360cb9d3ae6Smisaki 		}
1361cb9d3ae6Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
1362cb9d3ae6Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
136300161856Syc 		/* Reading the current MAC CTRL Config Register for BMAC */
1364cb9d3ae6Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
1365cb9d3ae6Smisaki 
1366cb9d3ae6Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
1367cb9d3ae6Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
1368cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1369cb9d3ae6Smisaki 				/*
1370cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1371cb9d3ae6Smisaki 				 * is 1, disable receive pause. Send pause
1372cb9d3ae6Smisaki 				 * is not supported
1373cb9d3ae6Smisaki 				 */
1374cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
1375cb9d3ae6Smisaki 			} else {
1376cb9d3ae6Smisaki 				/*
1377cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
1378cb9d3ae6Smisaki 				 * is 0, enable receive pause and disable
1379cb9d3ae6Smisaki 				 * send pause.
1380cb9d3ae6Smisaki 				 */
1381cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1382cb9d3ae6Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
1383cb9d3ae6Smisaki 			}
1384cb9d3ae6Smisaki 		} else {
1385cb9d3ae6Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
1386cb9d3ae6Smisaki 				/*
1387cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1388cb9d3ae6Smisaki 				 * is 1, enable receive pause. Send pause is
1389cb9d3ae6Smisaki 				 * not supported.
1390cb9d3ae6Smisaki 				 */
1391cb9d3ae6Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
1392cb9d3ae6Smisaki 			} else {
1393cb9d3ae6Smisaki 				/*
1394cb9d3ae6Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
1395cb9d3ae6Smisaki 				 * is 0, pause capability is not available in
1396cb9d3ae6Smisaki 				 * either direction.
1397cb9d3ae6Smisaki 				 */
1398cb9d3ae6Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
1399cb9d3ae6Smisaki 					~MAC_CTRL_CFG_RECV_PAUSE_EN);
1400cb9d3ae6Smisaki 			}
1401cb9d3ae6Smisaki 		}
1402cb9d3ae6Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
1403cb9d3ae6Smisaki 	}
1404cb9d3ae6Smisaki 
1405cb9d3ae6Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
1406cb9d3ae6Smisaki 	    portn));
1407cb9d3ae6Smisaki 
1408cb9d3ae6Smisaki 	return (NXGE_OK);
1409cb9d3ae6Smisaki }
1410cb9d3ae6Smisaki 
141144961713Sgirish /* Initialize the Internal Serdes */
141244961713Sgirish 
141344961713Sgirish nxge_status_t
141444961713Sgirish nxge_serdes_init(p_nxge_t nxgep)
141544961713Sgirish {
141644961713Sgirish 	p_nxge_stats_t		statsp;
141744961713Sgirish #ifdef	NXGE_DEBUG
141844961713Sgirish 	uint8_t			portn;
141944961713Sgirish #endif
142044961713Sgirish 	nxge_status_t		status = NXGE_OK;
142144961713Sgirish 
142244961713Sgirish #ifdef	NXGE_DEBUG
142344961713Sgirish 	portn = nxgep->mac.portnum;
142444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
142559ac0c16Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
142644961713Sgirish #endif
142744961713Sgirish 
142859ac0c16Sdavemq 	if (nxgep->xcvr.serdes_init) {
142959ac0c16Sdavemq 		statsp = nxgep->statsp;
143059ac0c16Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
143159ac0c16Sdavemq 		if (status != NXGE_OK)
143244961713Sgirish 			goto fail;
143359ac0c16Sdavemq 		statsp->mac_stats.serdes_inits++;
143444961713Sgirish 	}
143544961713Sgirish 
143644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
143759ac0c16Sdavemq 	    portn));
143844961713Sgirish 
143944961713Sgirish 	return (NXGE_OK);
144044961713Sgirish 
144144961713Sgirish fail:
144244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
144359ac0c16Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
144459ac0c16Sdavemq 	    portn));
144544961713Sgirish 
144644961713Sgirish 	return (status);
144744961713Sgirish }
144844961713Sgirish 
144944961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
145044961713Sgirish 
145159ac0c16Sdavemq static nxge_status_t
145244961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep)
145344961713Sgirish {
145444961713Sgirish 	uint8_t portn;
145544961713Sgirish 	int chan;
145644961713Sgirish 	esr_ti_cfgpll_l_t pll_cfg_l;
14572e59129aSraghus 	esr_ti_cfgpll_l_t pll_sts_l;
145844961713Sgirish 	esr_ti_cfgrx_l_t rx_cfg_l;
145944961713Sgirish 	esr_ti_cfgrx_h_t rx_cfg_h;
146044961713Sgirish 	esr_ti_cfgtx_l_t tx_cfg_l;
146144961713Sgirish 	esr_ti_cfgtx_h_t tx_cfg_h;
14622e59129aSraghus #ifdef NXGE_DEBUG
14632e59129aSraghus 	esr_ti_testcfg_t cfg;
14642e59129aSraghus #endif
146544961713Sgirish 	esr_ti_testcfg_t test_cfg;
146644961713Sgirish 	nxge_status_t status = NXGE_OK;
146744961713Sgirish 
146844961713Sgirish 	portn = nxgep->mac.portnum;
146944961713Sgirish 
147044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
147144961713Sgirish 			portn));
147244961713Sgirish 
147344961713Sgirish 	tx_cfg_l.value = 0;
147444961713Sgirish 	tx_cfg_h.value = 0;
147544961713Sgirish 	rx_cfg_l.value = 0;
147644961713Sgirish 	rx_cfg_h.value = 0;
147744961713Sgirish 	pll_cfg_l.value = 0;
14782e59129aSraghus 	pll_sts_l.value = 0;
147944961713Sgirish 	test_cfg.value = 0;
148044961713Sgirish 
148100161856Syc 	/*
148200161856Syc 	 * If the nxge driver has been plumbed without a link, then it will
148300161856Syc 	 * detect a link up when a cable connecting to an anto-negotiation
148400161856Syc 	 * partner is plugged into the port. Because the TN1010 PHY supports
148500161856Syc 	 * both 1G and 10G speeds, the driver must re-configure the
148600161856Syc 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
148700161856Syc 	 * is called at the post-link-up reconfiguration time. Here it calls
148800161856Syc 	 * nxge_set_tn1010_param to set portmode before re-initializing
148900161856Syc 	 * the serdes.
149000161856Syc 	 */
149100161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
149200161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
149300161856Syc 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
149400161856Syc 			goto fail;
149500161856Syc 		}
149600161856Syc 	}
149700161856Syc 
149800161856Syc 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
149900161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
150000161856Syc 	    nxgep->mac.portmode == PORT_10G_SERDES) {
150144961713Sgirish 		/* 0x0E01 */
150244961713Sgirish 		tx_cfg_l.bits.entx = 1;
150344961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
150444961713Sgirish 
150544961713Sgirish 		/* 0x9101 */
150644961713Sgirish 		rx_cfg_l.bits.enrx = 1;
150744961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
150844961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
150944961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
151044961713Sgirish 
151144961713Sgirish 		/* 0x0008 */
151244961713Sgirish 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
151344961713Sgirish 
151444961713Sgirish 		/* Set loopback mode if necessary */
151544961713Sgirish 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
151644961713Sgirish 			tx_cfg_l.bits.entest = 1;
151744961713Sgirish 			rx_cfg_l.bits.entest = 1;
151844961713Sgirish 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
151944961713Sgirish 			if ((status = nxge_mdio_write(nxgep, portn,
152044961713Sgirish 				ESR_N2_DEV_ADDR,
152144961713Sgirish 				ESR_N2_TEST_CFG_REG, test_cfg.value))
152244961713Sgirish 				!= NXGE_OK)
152344961713Sgirish 			goto fail;
152444961713Sgirish 		}
152544961713Sgirish 
152600161856Syc 		/* Initialize PLL for 10G */
152700161856Syc 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
152800161856Syc 		pll_cfg_l.bits.enpll = 1;
152900161856Syc 		pll_sts_l.bits.enpll = 1;
153000161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
153100161856Syc 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
153200161856Syc 			goto fail;
153300161856Syc 
153400161856Syc 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
153500161856Syc 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
153600161856Syc 			goto fail;
153744961713Sgirish 
153800161856Syc #ifdef  NXGE_DEBUG
153900161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
154000161856Syc 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
154100161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
154200161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
154300161856Syc 		    portn, pll_cfg_l.value, cfg.value));
154444961713Sgirish 
154500161856Syc 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
154600161856Syc 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
154700161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
154800161856Syc 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
154900161856Syc 		    portn, pll_sts_l.value, cfg.value));
155000161856Syc #endif
155100161856Syc 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
155200161856Syc 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
155300161856Syc 	    nxgep->mac.portmode == PORT_1G_SERDES) {
155444961713Sgirish 		/* 0x0E21 */
155544961713Sgirish 		tx_cfg_l.bits.entx = 1;
155644961713Sgirish 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
155744961713Sgirish 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
155844961713Sgirish 
155944961713Sgirish 		/* 0x9121 */
156044961713Sgirish 		rx_cfg_l.bits.enrx = 1;
156144961713Sgirish 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
156244961713Sgirish 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
156344961713Sgirish 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
156444961713Sgirish 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
156544961713Sgirish 
15662e59129aSraghus 		if (portn == 0) {
15672e59129aSraghus 			/* 0x8 */
15682e59129aSraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15692e59129aSraghus 		}
157044961713Sgirish 
157100161856Syc 		/* Initialize PLL for 1G */
157244961713Sgirish 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
157344961713Sgirish 		pll_cfg_l.bits.enpll = 1;
15742e59129aSraghus 		pll_sts_l.bits.enpll = 1;
157544961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
157644961713Sgirish 				ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
157744961713Sgirish 				!= NXGE_OK)
157844961713Sgirish 			goto fail;
15792e59129aSraghus 
15802e59129aSraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15812e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15822e59129aSraghus 			goto fail;
15832e59129aSraghus 
15842e59129aSraghus #ifdef  NXGE_DEBUG
15852e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15862e59129aSraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15872e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15882e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15892e59129aSraghus 		    portn, pll_cfg_l.value, cfg.value));
15902e59129aSraghus 
15912e59129aSraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15922e59129aSraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15932e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15942e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
15952e59129aSraghus 		    portn, pll_sts_l.value, cfg.value));
15962e59129aSraghus #endif
15972e59129aSraghus 
15982e59129aSraghus 		/* Set loopback mode if necessary */
15992e59129aSraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16002e59129aSraghus 			tx_cfg_l.bits.entest = 1;
16012e59129aSraghus 			rx_cfg_l.bits.entest = 1;
16022e59129aSraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
16032e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16042e59129aSraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
16052e59129aSraghus 			    portn, test_cfg.value));
16062e59129aSraghus 			if ((status = nxge_mdio_write(nxgep, portn,
16072e59129aSraghus 			    ESR_N2_DEV_ADDR,
16082e59129aSraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
16092e59129aSraghus 				goto fail;
16102e59129aSraghus 			}
16112e59129aSraghus 		}
161244961713Sgirish 	} else {
161344961713Sgirish 		goto fail;
161444961713Sgirish 	}
161544961713Sgirish 
161644961713Sgirish 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
161744961713Sgirish 
161844961713Sgirish 	NXGE_DELAY(20);
161944961713Sgirish 
162044961713Sgirish 	/* init TX channels */
162144961713Sgirish 	for (chan = 0; chan < 4; chan++) {
162244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
162344961713Sgirish 				ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value))
162444961713Sgirish 				!= NXGE_OK)
162544961713Sgirish 			goto fail;
162644961713Sgirish 
162744961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
162844961713Sgirish 				ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value))
162944961713Sgirish 				!= NXGE_OK)
163044961713Sgirish 			goto fail;
16312e59129aSraghus 
16322e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16332e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16342e59129aSraghus 		    portn, chan, tx_cfg_l.value));
16352e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16362e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16372e59129aSraghus 		    portn, chan, tx_cfg_h.value));
163844961713Sgirish 	}
163944961713Sgirish 
164044961713Sgirish 	/* init RX channels */
164144961713Sgirish 	for (chan = 0; chan < 4; chan++) {
164244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
164344961713Sgirish 				ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
164444961713Sgirish 				!= NXGE_OK)
164544961713Sgirish 			goto fail;
164644961713Sgirish 
164744961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
164844961713Sgirish 				ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
164944961713Sgirish 				!= NXGE_OK)
165044961713Sgirish 			goto fail;
16512e59129aSraghus 
16522e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16532e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16542e59129aSraghus 		    portn, chan, rx_cfg_l.value));
165500161856Syc 
16562e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16572e59129aSraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16582e59129aSraghus 		    portn, chan, rx_cfg_h.value));
165944961713Sgirish 	}
166044961713Sgirish 
166144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
166244961713Sgirish 			portn));
166344961713Sgirish 
166444961713Sgirish 	return (NXGE_OK);
166544961713Sgirish fail:
16662d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16672d17280bSsbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16682d17280bSsbehera 	    portn));
166944961713Sgirish 
167044961713Sgirish 	return (status);
167144961713Sgirish }
167244961713Sgirish 
167359ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
167444961713Sgirish 
167559ac0c16Sdavemq static nxge_status_t
167659ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
167744961713Sgirish {
167844961713Sgirish 	npi_handle_t		handle;
167944961713Sgirish 	uint8_t			portn;
1680321febdeSsbehera 	int			chan, i;
168144961713Sgirish 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
168244961713Sgirish 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
168344961713Sgirish 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
168444961713Sgirish 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
168544961713Sgirish 	uint64_t		val;
168644961713Sgirish 	uint16_t		val16l;
168744961713Sgirish 	uint16_t		val16h;
168844961713Sgirish 	nxge_status_t		status = NXGE_OK;
168944961713Sgirish 
169044961713Sgirish 	portn = nxgep->mac.portnum;
169144961713Sgirish 
169244961713Sgirish 	if ((portn != 0) && (portn != 1))
169344961713Sgirish 		return (NXGE_OK);
169444961713Sgirish 
169559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
169659ac0c16Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
169744961713Sgirish 	handle = nxgep->npi_handle;
169859ac0c16Sdavemq 	switch (portn) {
169959ac0c16Sdavemq 	case 0:
17004202ea4bSsbehera 		/* Reset Serdes */
17014202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
17024202ea4bSsbehera 		NXGE_DELAY(20);
17034202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17044202ea4bSsbehera 		NXGE_DELAY(2000);
17054202ea4bSsbehera 
17064202ea4bSsbehera 		/* Configure Serdes to 10G mode */
17074202ea4bSsbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
17084202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
17094202ea4bSsbehera 
171059ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
171159ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
171259ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
171359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
171459ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
171559ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
171659ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
171759ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
171859ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
171959ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
172059ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
172159ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
172259ac0c16Sdavemq 
172359ac0c16Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
172459ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
172559ac0c16Sdavemq 			ESR_REG_WR(handle,
172659ac0c16Sdavemq 			    ESR_0_TEST_CONFIG_REG,
172759ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
172859ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
172959ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
173059ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
173159ac0c16Sdavemq 		} else {
173259ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
173344961713Sgirish 		}
173459ac0c16Sdavemq 		break;
173559ac0c16Sdavemq 	case 1:
17364202ea4bSsbehera 		/* Reset Serdes */
17374202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
17384202ea4bSsbehera 		NXGE_DELAY(20);
17394202ea4bSsbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17404202ea4bSsbehera 		NXGE_DELAY(2000);
17414202ea4bSsbehera 
17424202ea4bSsbehera 		/* Configure Serdes to 10G mode */
17434202ea4bSsbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
17444202ea4bSsbehera 		    ESR_PLL_CFG_10G_SERDES);
17454202ea4bSsbehera 
174659ac0c16Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
174759ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
174859ac0c16Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
174959ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
175059ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
175159ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
175259ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
175359ac0c16Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
175459ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
175559ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
175659ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
175759ac0c16Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
175859ac0c16Sdavemq 
175959ac0c16Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
176059ac0c16Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
176159ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
176259ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
176359ac0c16Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
176459ac0c16Sdavemq 		} else {
176559ac0c16Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
176644961713Sgirish 		}
176759ac0c16Sdavemq 		break;
176859ac0c16Sdavemq 	default:
176959ac0c16Sdavemq 		/* Nothing to do here */
177059ac0c16Sdavemq 		goto done;
177159ac0c16Sdavemq 	}
177244961713Sgirish 
177359ac0c16Sdavemq 	/* init TX RX channels */
177459ac0c16Sdavemq 	for (chan = 0; chan < 4; chan++) {
177559ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
177659ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
177759ac0c16Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
177844961713Sgirish 			goto fail;
177959ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
178059ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
178159ac0c16Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
178244961713Sgirish 			goto fail;
178359ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
178459ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
178559ac0c16Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
178659ac0c16Sdavemq 			goto fail;
178759ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
178859ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
178959ac0c16Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
179059ac0c16Sdavemq 			goto fail;
179159ac0c16Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
179259ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
179359ac0c16Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
179459ac0c16Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
179559ac0c16Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
179659ac0c16Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
179759ac0c16Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
179844961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
179959ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
180059ac0c16Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
180144961713Sgirish 			goto fail;
180244961713Sgirish 		if ((status = nxge_mdio_write(nxgep, portn,
180359ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
180459ac0c16Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
180544961713Sgirish 			goto fail;
180659ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
180759ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
180859ac0c16Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
180944961713Sgirish 			goto fail;
181059ac0c16Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
181159ac0c16Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
181259ac0c16Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
181344961713Sgirish 			goto fail;
181444961713Sgirish 		}
181544961713Sgirish 
181659ac0c16Sdavemq 	/* Apply Tx core reset */
181759ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
181859ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
181959ac0c16Sdavemq 	    (uint16_t)0)) != NXGE_OK)
182059ac0c16Sdavemq 		goto fail;
182159ac0c16Sdavemq 
182259ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
182359ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
182459ac0c16Sdavemq 	    NXGE_OK)
182559ac0c16Sdavemq 		goto fail;
182659ac0c16Sdavemq 
182759ac0c16Sdavemq 	NXGE_DELAY(200);
182859ac0c16Sdavemq 
182959ac0c16Sdavemq 	/* Apply Rx core reset */
183059ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
183159ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
183259ac0c16Sdavemq 	    NXGE_OK)
183359ac0c16Sdavemq 		goto fail;
183459ac0c16Sdavemq 
183559ac0c16Sdavemq 	NXGE_DELAY(200);
183659ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
183759ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
183859ac0c16Sdavemq 		goto fail;
183959ac0c16Sdavemq 
184059ac0c16Sdavemq 	NXGE_DELAY(200);
184159ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
184259ac0c16Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
184359ac0c16Sdavemq 	    &val16l)) != NXGE_OK)
184459ac0c16Sdavemq 		goto fail;
184559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
184659ac0c16Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
184759ac0c16Sdavemq 		goto fail;
184859ac0c16Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
184959ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1850d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
1851d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
1852d81011f0Ssbehera 		    portn, val16l, val16h));
185359ac0c16Sdavemq 	}
185459ac0c16Sdavemq 
185559ac0c16Sdavemq 	if (portn == 0) {
1856321febdeSsbehera 		/* Wait for serdes to be ready */
1857321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1858321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1859321febdeSsbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
1860321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
1861321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P0 |
1862321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH3 |
1863321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH2 |
1864321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH1 |
1865321febdeSsbehera 			    ESR_SIG_XDETECT_P0_CH0))
1866321febdeSsbehera 
1867321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1868321febdeSsbehera 			else
1869321febdeSsbehera 				break;
1870321febdeSsbehera 		}
1871321febdeSsbehera 
1872321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1873ab6abb7aSjoycey 			/*
1874ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
1875ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
1876ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
1877ab6abb7aSjoycey 			 * stays down
1878ab6abb7aSjoycey 			 */
1879321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1880321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1881321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
188200161856Syc 				goto done;
188359ac0c16Sdavemq 		}
188459ac0c16Sdavemq 	} else if (portn == 1) {
1885321febdeSsbehera 		/* Wait for serdes to be ready */
1886321febdeSsbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
1887321febdeSsbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
1888321febdeSsbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
1889321febdeSsbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
1890321febdeSsbehera 			    ESR_SIG_XSERDES_RDY_P1 |
1891321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH3 |
1892321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH2 |
1893321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH1 |
1894321febdeSsbehera 			    ESR_SIG_XDETECT_P1_CH0))
1895321febdeSsbehera 
1896321febdeSsbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
1897321febdeSsbehera 			else
1898321febdeSsbehera 				break;
1899321febdeSsbehera 		}
1900321febdeSsbehera 
1901321febdeSsbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
1902ab6abb7aSjoycey 			/*
1903ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
1904ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
1905ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
1906ab6abb7aSjoycey 			 * stays down
1907ab6abb7aSjoycey 			 */
1908321febdeSsbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1909321febdeSsbehera 			    "nxge_neptune_10G_serdes_init: "
1910321febdeSsbehera 			    "Serdes/signal for port<%d> not ready", portn));
191100161856Syc 				goto done;
191244961713Sgirish 		}
191344961713Sgirish 	}
191444961713Sgirish 
191544961713Sgirish done:
191659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
191759ac0c16Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
191859ac0c16Sdavemq 
191944961713Sgirish 	return (NXGE_OK);
192044961713Sgirish fail:
19212d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
192259ac0c16Sdavemq 	    "nxge_neptune_10G_serdes_init: "
192359ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
192444961713Sgirish 
192544961713Sgirish 	return (status);
192644961713Sgirish }
192744961713Sgirish 
192859ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
192944961713Sgirish 
193059ac0c16Sdavemq static nxge_status_t
193159ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
193244961713Sgirish {
193359ac0c16Sdavemq 	npi_handle_t		handle;
193459ac0c16Sdavemq 	uint8_t			portn;
1935d81011f0Ssbehera 	int			chan;
1936d81011f0Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
1937d81011f0Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
1938d81011f0Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
1939d81011f0Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
194059ac0c16Sdavemq 	uint64_t		val;
1941d81011f0Ssbehera 	uint16_t		val16l;
1942d81011f0Ssbehera 	uint16_t		val16h;
1943d81011f0Ssbehera 	nxge_status_t		status = NXGE_OK;
194444961713Sgirish 
194544961713Sgirish 	portn = nxgep->mac.portnum;
194644961713Sgirish 
194759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
194859ac0c16Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
194944961713Sgirish 
195059ac0c16Sdavemq 	handle = nxgep->npi_handle;
195144961713Sgirish 
195259ac0c16Sdavemq 	switch (portn) {
195359ac0c16Sdavemq 	case 0:
1954d81011f0Ssbehera 		/* Assert the reset register */
1955d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1956d81011f0Ssbehera 		val |= ESR_RESET_0;
1957d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1958d81011f0Ssbehera 
1959d81011f0Ssbehera 		/* Set the PLL register to 0x79 */
1960d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
1961d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1962d81011f0Ssbehera 
1963d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1964d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
1965d81011f0Ssbehera 
1966d81011f0Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
1967d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1968d81011f0Ssbehera 			/* Set pad loopback modes 0xaa */
1969d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
1970d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1971d81011f0Ssbehera 		} else {
1972d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
1973d81011f0Ssbehera 		}
1974d81011f0Ssbehera 
1975d81011f0Ssbehera 		/* Deassert the reset register */
1976d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1977d81011f0Ssbehera 		val &= ~ESR_RESET_0;
1978d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
197959ac0c16Sdavemq 		break;
1980d81011f0Ssbehera 
198159ac0c16Sdavemq 	case 1:
1982d81011f0Ssbehera 		/* Assert the reset register */
1983d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
1984d81011f0Ssbehera 		val |= ESR_RESET_1;
1985d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
1986d81011f0Ssbehera 
1987d81011f0Ssbehera 		/* Set PLL register to 0x79 */
1988d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
1989d81011f0Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
1990d81011f0Ssbehera 
1991d81011f0Ssbehera 		/* Set the control register to 0x249249f */
1992d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
1993d81011f0Ssbehera 
1994d81011f0Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
1995d81011f0Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
1996d81011f0Ssbehera 			/* Set pad loopback mode 0xaa */
1997d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
1998d81011f0Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
1999d81011f0Ssbehera 		} else {
2000d81011f0Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
2001d81011f0Ssbehera 		}
2002d81011f0Ssbehera 
2003d81011f0Ssbehera 		/* Deassert the reset register */
2004d81011f0Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
2005d81011f0Ssbehera 		val &= ~ESR_RESET_1;
2006d81011f0Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
200759ac0c16Sdavemq 		break;
2008d81011f0Ssbehera 
200959ac0c16Sdavemq 	default:
2010d81011f0Ssbehera 		/* Nothing to do here */
2011d81011f0Ssbehera 		goto done;
2012d81011f0Ssbehera 	}
2013d81011f0Ssbehera 
2014d81011f0Ssbehera 	/* init TX RX channels */
2015d81011f0Ssbehera 	for (chan = 0; chan < 4; chan++) {
2016d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2017d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2018d81011f0Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
2019d81011f0Ssbehera 			goto fail;
2020d81011f0Ssbehera 		}
2021d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2022d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2023d81011f0Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
2024d81011f0Ssbehera 			goto fail;
2025d81011f0Ssbehera 		}
2026d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2027d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2028d81011f0Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
2029d81011f0Ssbehera 			goto fail;
2030d81011f0Ssbehera 		}
2031d81011f0Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
2032d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2033d81011f0Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
2034d81011f0Ssbehera 			goto fail;
2035d81011f0Ssbehera 		}
2036d81011f0Ssbehera 
2037d81011f0Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
2038d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
2039d81011f0Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
2040d81011f0Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
2041d81011f0Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
2042d81011f0Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
2043d81011f0Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
2044d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2045d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
2046d81011f0Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
2047d81011f0Ssbehera 			goto fail;
2048d81011f0Ssbehera 		}
2049d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2050d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
2051d81011f0Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
2052d81011f0Ssbehera 			goto fail;
2053d81011f0Ssbehera 		}
2054d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2055d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
2056d81011f0Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
2057d81011f0Ssbehera 			goto fail;
2058d81011f0Ssbehera 		}
2059d81011f0Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
2060d81011f0Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
2061d81011f0Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
2062d81011f0Ssbehera 			goto fail;
2063d81011f0Ssbehera 		}
2064d81011f0Ssbehera 	}
2065d81011f0Ssbehera 
2066d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2067d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
2068d81011f0Ssbehera 		goto fail;
2069d81011f0Ssbehera 	}
2070d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2071d81011f0Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
2072d81011f0Ssbehera 		goto fail;
2073d81011f0Ssbehera 	}
2074d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2075d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
2076d81011f0Ssbehera 		goto fail;
2077d81011f0Ssbehera 	}
2078d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2079d81011f0Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
208059ac0c16Sdavemq 		goto fail;
208144961713Sgirish 	}
208244961713Sgirish 
2083d81011f0Ssbehera 	/* Apply Tx core reset */
2084d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2085d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
2086d81011f0Ssbehera 		goto fail;
2087d81011f0Ssbehera 	}
2088d81011f0Ssbehera 
2089d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2090d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
2091d81011f0Ssbehera 	    NXGE_OK) {
2092d81011f0Ssbehera 		goto fail;
2093d81011f0Ssbehera 	}
2094d81011f0Ssbehera 
2095d81011f0Ssbehera 	NXGE_DELAY(200);
2096d81011f0Ssbehera 
2097d81011f0Ssbehera 	/* Apply Rx core reset */
2098d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2099d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
2100d81011f0Ssbehera 	    NXGE_OK) {
2101d81011f0Ssbehera 		goto fail;
2102d81011f0Ssbehera 	}
2103d81011f0Ssbehera 
2104d81011f0Ssbehera 	NXGE_DELAY(200);
2105d81011f0Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2106d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
2107d81011f0Ssbehera 		goto fail;
2108d81011f0Ssbehera 	}
2109d81011f0Ssbehera 
2110d81011f0Ssbehera 	NXGE_DELAY(200);
2111d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2112d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
2113d81011f0Ssbehera 		goto fail;
2114d81011f0Ssbehera 	}
2115d81011f0Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
2116d81011f0Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
2117d81011f0Ssbehera 		goto fail;
2118d81011f0Ssbehera 	}
2119d81011f0Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
2120d81011f0Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2121d81011f0Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
2122d81011f0Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
2123d81011f0Ssbehera 		status = NXGE_ERROR;
2124d81011f0Ssbehera 		goto fail;
2125d81011f0Ssbehera 	}
2126d81011f0Ssbehera 
2127d81011f0Ssbehera 	NXGE_DELAY(200);
2128d81011f0Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
2129d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
2130d81011f0Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
2131d81011f0Ssbehera 	    "val 0x%x", portn, val));
2132d81011f0Ssbehera 	if (portn == 0) {
2133d81011f0Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
2134d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
2135ab6abb7aSjoycey 			/*
2136ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2137ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2138ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2139ab6abb7aSjoycey 			 * stays down
2140ab6abb7aSjoycey 			 */
2141d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2142ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2143ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
214400161856Syc 				goto done;
2145d81011f0Ssbehera 		}
2146d81011f0Ssbehera 	} else if (portn == 1) {
2147d81011f0Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
2148d81011f0Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
2149ab6abb7aSjoycey 			/*
2150ab6abb7aSjoycey 			 * RDY signal stays low may due to the absent of the
2151ab6abb7aSjoycey 			 * external PHY, it is not an error condition. But still
2152ab6abb7aSjoycey 			 * print the message for the debugging purpose when link
2153ab6abb7aSjoycey 			 * stays down
2154ab6abb7aSjoycey 			 */
2155d81011f0Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2156ab6abb7aSjoycey 			    "nxge_neptune_1G_serdes_init: "
2157ab6abb7aSjoycey 			    "Serdes/signal for port<%d> not ready", portn));
215800161856Syc 				goto done;
215900161856Syc 
2160d81011f0Ssbehera 		}
2161d81011f0Ssbehera 	}
2162d81011f0Ssbehera done:
216359ac0c16Sdavemq 
216459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
216559ac0c16Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
216644961713Sgirish 	return (NXGE_OK);
216759ac0c16Sdavemq fail:
2168d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
216959ac0c16Sdavemq 	    "nxge_1G_serdes_init: "
217059ac0c16Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
217159ac0c16Sdavemq 	    portn));
217259ac0c16Sdavemq 
2173d81011f0Ssbehera 	return (status);
217444961713Sgirish }
217544961713Sgirish 
21762d17280bSsbehera /* Initialize the BCM 8704 xcvr */
217744961713Sgirish 
217859ac0c16Sdavemq static nxge_status_t
21792d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
218044961713Sgirish {
218144961713Sgirish 	uint16_t		val;
218244961713Sgirish #ifdef	NXGE_DEBUG
218314ea4bb7Ssd 	uint8_t			portn;
218444961713Sgirish 	uint16_t		val1;
218544961713Sgirish #endif
218644961713Sgirish 	uint8_t			phy_port_addr;
218744961713Sgirish 	pmd_tx_control_t	tx_ctl;
218844961713Sgirish 	control_t		ctl;
218944961713Sgirish 	phyxs_control_t		phyxs_ctl;
219044961713Sgirish 	pcs_control_t		pcs_ctl;
219144961713Sgirish 	uint32_t		delay = 0;
219244961713Sgirish 	optics_dcntr_t		op_ctr;
219344961713Sgirish 	nxge_status_t		status = NXGE_OK;
219414ea4bb7Ssd #ifdef	NXGE_DEBUG
219544961713Sgirish 	portn = nxgep->mac.portnum;
219614ea4bb7Ssd #endif
21972d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
219859ac0c16Sdavemq 	    portn));
219944961713Sgirish 
220059ac0c16Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
220159ac0c16Sdavemq 
220259ac0c16Sdavemq 	/* Reset the transceiver */
220359ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
220459ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
220559ac0c16Sdavemq 		goto fail;
220659ac0c16Sdavemq 
220759ac0c16Sdavemq 	phyxs_ctl.bits.reset = 1;
220859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
220959ac0c16Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
221059ac0c16Sdavemq 		goto fail;
221159ac0c16Sdavemq 
221259ac0c16Sdavemq 	do {
221359ac0c16Sdavemq 		drv_usecwait(500);
221459ac0c16Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
221559ac0c16Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
221659ac0c16Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
221759ac0c16Sdavemq 			goto fail;
221859ac0c16Sdavemq 		delay++;
221959ac0c16Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
222059ac0c16Sdavemq 	if (delay == 100) {
222159ac0c16Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
222259ac0c16Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
222359ac0c16Sdavemq 		status = NXGE_ERROR;
222459ac0c16Sdavemq 		goto fail;
222559ac0c16Sdavemq 	}
222644961713Sgirish 
222759ac0c16Sdavemq 	/* Set to 0x7FBF */
222859ac0c16Sdavemq 	ctl.value = 0;
222959ac0c16Sdavemq 	ctl.bits.res1 = 0x3F;
223059ac0c16Sdavemq 	ctl.bits.optxon_lvl = 1;
223159ac0c16Sdavemq 	ctl.bits.oprxflt_lvl = 1;
223259ac0c16Sdavemq 	ctl.bits.optrxlos_lvl = 1;
223359ac0c16Sdavemq 	ctl.bits.optxflt_lvl = 1;
223459ac0c16Sdavemq 	ctl.bits.opprflt_lvl = 1;
223559ac0c16Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
223659ac0c16Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
223759ac0c16Sdavemq 	ctl.bits.optxrst_lvl = 1;
223859ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
223959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
224059ac0c16Sdavemq 	    != NXGE_OK)
224159ac0c16Sdavemq 		goto fail;
224259ac0c16Sdavemq 
224359ac0c16Sdavemq 	/* Set to 0x164 */
224459ac0c16Sdavemq 	tx_ctl.value = 0;
224559ac0c16Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
224659ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
224759ac0c16Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
224859ac0c16Sdavemq 	tx_ctl.bits.xfp_clken = 1;
224959ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
225059ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
225159ac0c16Sdavemq 	    tx_ctl.value)) != NXGE_OK)
225259ac0c16Sdavemq 		goto fail;
225344961713Sgirish 	/*
225459ac0c16Sdavemq 	 * According to Broadcom's instruction, SW needs to read
225559ac0c16Sdavemq 	 * back these registers twice after written.
225644961713Sgirish 	 */
225759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
225859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
225959ac0c16Sdavemq 	    != NXGE_OK)
226059ac0c16Sdavemq 		goto fail;
226144961713Sgirish 
226259ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
226359ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
226459ac0c16Sdavemq 	    != NXGE_OK)
226559ac0c16Sdavemq 		goto fail;
226644961713Sgirish 
226759ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
226859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
226959ac0c16Sdavemq 	    != NXGE_OK)
227059ac0c16Sdavemq 		goto fail;
227144961713Sgirish 
227259ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
227359ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
227459ac0c16Sdavemq 	    != NXGE_OK)
227559ac0c16Sdavemq 		goto fail;
227644961713Sgirish 
227759ac0c16Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
227859ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
227959ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
228059ac0c16Sdavemq 	    &op_ctr.value)) != NXGE_OK)
228159ac0c16Sdavemq 		goto fail;
2282cb9d3ae6Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
2283cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x1;
2284cb9d3ae6Smisaki 	} else {
2285cb9d3ae6Smisaki 		op_ctr.bits.gpio_sel = 0x3;
2286cb9d3ae6Smisaki 	}
228759ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
228859ac0c16Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
228959ac0c16Sdavemq 	    op_ctr.value)) != NXGE_OK)
229059ac0c16Sdavemq 		goto fail;
229144961713Sgirish 
229259ac0c16Sdavemq 	NXGE_DELAY(1000000);
229344961713Sgirish 
229459ac0c16Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
229559ac0c16Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
229659ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
229759ac0c16Sdavemq 	    != NXGE_OK)
229859ac0c16Sdavemq 		goto fail;
229959ac0c16Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
230059ac0c16Sdavemq 		pcs_ctl.bits.loopback = 1;
230159ac0c16Sdavemq 	else
230259ac0c16Sdavemq 		pcs_ctl.bits.loopback = 0;
230359ac0c16Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
230459ac0c16Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
230559ac0c16Sdavemq 	    != NXGE_OK)
230659ac0c16Sdavemq 		goto fail;
230744961713Sgirish 
230859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
230959ac0c16Sdavemq 	if (status != NXGE_OK)
231059ac0c16Sdavemq 		goto fail;
231159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
231259ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
231359ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
231459ac0c16Sdavemq 	if (status != NXGE_OK)
231559ac0c16Sdavemq 		goto fail;
231659ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
231759ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
231859ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
231959ac0c16Sdavemq 	if (status != NXGE_OK)
232059ac0c16Sdavemq 		goto fail;
232159ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
232259ac0c16Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
232344961713Sgirish 
232459ac0c16Sdavemq #ifdef	NXGE_DEBUG
232559ac0c16Sdavemq 	/* Diagnose link issue if link is not up */
232659ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
232759ac0c16Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
232859ac0c16Sdavemq 	    &val);
232959ac0c16Sdavemq 	if (status != NXGE_OK)
233059ac0c16Sdavemq 		goto fail;
233144961713Sgirish 
233259ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
233344961713Sgirish 				BCM8704_USER_DEV3_ADDR,
233459ac0c16Sdavemq 				BCM8704_USER_ANALOG_STATUS0_REG,
233559ac0c16Sdavemq 				&val);
233659ac0c16Sdavemq 	if (status != NXGE_OK)
233759ac0c16Sdavemq 		goto fail;
233844961713Sgirish 
233959ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
234044961713Sgirish 				BCM8704_USER_DEV3_ADDR,
234159ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
234259ac0c16Sdavemq 				&val1);
234359ac0c16Sdavemq 	if (status != NXGE_OK)
234459ac0c16Sdavemq 		goto fail;
234544961713Sgirish 
234659ac0c16Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
234744961713Sgirish 				BCM8704_USER_DEV3_ADDR,
234859ac0c16Sdavemq 				BCM8704_USER_TX_ALARM_STATUS_REG,
234959ac0c16Sdavemq 				&val1);
235059ac0c16Sdavemq 	if (status != NXGE_OK)
235159ac0c16Sdavemq 		goto fail;
235244961713Sgirish 
235359ac0c16Sdavemq 	if (val != 0x3FC) {
235459ac0c16Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
235559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
235659ac0c16Sdavemq 			    "Cable not connected to peer or bad"
235759ac0c16Sdavemq 			    " cable on port<%d>\n", portn));
235859ac0c16Sdavemq 		} else if (val == 0x639C) {
235959ac0c16Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
236059ac0c16Sdavemq 			    "Optical module (XFP) is bad or absent"
236159ac0c16Sdavemq 			    " on port<%d>\n", portn));
236259ac0c16Sdavemq 		}
236359ac0c16Sdavemq 	}
236459ac0c16Sdavemq #endif
236544961713Sgirish 
23662d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
23672d17280bSsbehera 	    portn));
23682d17280bSsbehera 	return (NXGE_OK);
23692d17280bSsbehera 
23702d17280bSsbehera fail:
23712d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23722d17280bSsbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
23732d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
23742d17280bSsbehera 	return (NXGE_ERROR);
23752d17280bSsbehera }
23762d17280bSsbehera 
23772d17280bSsbehera /* Initialize the BCM 8706 Transceiver */
23782d17280bSsbehera 
23792d17280bSsbehera static nxge_status_t
23802d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
23812d17280bSsbehera {
23822d17280bSsbehera 	uint8_t			phy_port_addr;
23832d17280bSsbehera 	phyxs_control_t		phyxs_ctl;
23842d17280bSsbehera 	pcs_control_t		pcs_ctl;
23852d17280bSsbehera 	uint32_t		delay = 0;
23862d17280bSsbehera 	optics_dcntr_t		op_ctr;
23872d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
23882d17280bSsbehera #ifdef	NXGE_DEBUG
23892d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
23902d17280bSsbehera #endif
23912d17280bSsbehera 
23922d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
23932d17280bSsbehera 	    portn));
23942d17280bSsbehera 
23952d17280bSsbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
23962d17280bSsbehera 
23972d17280bSsbehera 	/* Reset the transceiver */
23982d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23992d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
24002d17280bSsbehera 		goto fail;
24012d17280bSsbehera 
24022d17280bSsbehera 	phyxs_ctl.bits.reset = 1;
24032d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
24042d17280bSsbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
24052d17280bSsbehera 		goto fail;
24062d17280bSsbehera 	do {
24072d17280bSsbehera 		drv_usecwait(500);
24082d17280bSsbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24092d17280bSsbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
24102d17280bSsbehera 		    &phyxs_ctl.value)) != NXGE_OK)
24112d17280bSsbehera 			goto fail;
24122d17280bSsbehera 		delay++;
24132d17280bSsbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
24142d17280bSsbehera 
24152d17280bSsbehera 	if (delay == 100) {
24162d17280bSsbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
24172d17280bSsbehera 		    "failed to reset Transceiver on port<%d>", portn));
24182d17280bSsbehera 		status = NXGE_ERROR;
24192d17280bSsbehera 		goto fail;
24202d17280bSsbehera 	}
24212d17280bSsbehera 
24222d17280bSsbehera 	NXGE_DELAY(1000000);
24232d17280bSsbehera 
24242d17280bSsbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
24252d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24262d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
24272d17280bSsbehera 	    != NXGE_OK)
24282d17280bSsbehera 		goto fail;
24292d17280bSsbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24302d17280bSsbehera 		pcs_ctl.bits.loopback = 1;
24312d17280bSsbehera 	else
24322d17280bSsbehera 		pcs_ctl.bits.loopback = 0;
24332d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24342d17280bSsbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
24352d17280bSsbehera 	    != NXGE_OK)
24362d17280bSsbehera 		goto fail;
24372d17280bSsbehera 
24382d17280bSsbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
24392d17280bSsbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24402d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24412d17280bSsbehera 	    &op_ctr.value)) != NXGE_OK)
24422d17280bSsbehera 		goto fail;
24432d17280bSsbehera 	op_ctr.bits.gpio_sel = 0x3;
24442d17280bSsbehera 	op_ctr.bits.res2 = 0x1;
24452d17280bSsbehera 
24462d17280bSsbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24472d17280bSsbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24482d17280bSsbehera 	    op_ctr.value)) != NXGE_OK)
24492d17280bSsbehera 		goto fail;
24502d17280bSsbehera 
24512d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
24522d17280bSsbehera 	    portn));
24532d17280bSsbehera 	return (NXGE_OK);
24542d17280bSsbehera 
24552d17280bSsbehera fail:
24562d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24572d17280bSsbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
24582d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
24592d17280bSsbehera 	return (status);
24602d17280bSsbehera }
24612d17280bSsbehera 
246252cdd236Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
246352cdd236Ssbehera 
246452cdd236Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
246552cdd236Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
246652cdd236Ssbehera 
246752cdd236Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
246852cdd236Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
246952cdd236Ssbehera 
247052cdd236Ssbehera 
247152cdd236Ssbehera static void
247252cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
247352cdd236Ssbehera {
247452cdd236Ssbehera 	uint16_t	value;
247552cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
247652cdd236Ssbehera 
247752cdd236Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
247852cdd236Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
247952cdd236Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
248052cdd236Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
248152cdd236Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
248252cdd236Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
248352cdd236Ssbehera 		    value);
248452cdd236Ssbehera 	}
248552cdd236Ssbehera }
248652cdd236Ssbehera 
248752cdd236Ssbehera static nxge_status_t
248852cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
248952cdd236Ssbehera {
249052cdd236Ssbehera 	nxge_status_t	status;
249152cdd236Ssbehera 	pcs_control_t	pcs_ctl;
249252cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
249352cdd236Ssbehera 
249452cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
249552cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
249652cdd236Ssbehera 
249752cdd236Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
249852cdd236Ssbehera 		pcs_ctl.bits.loopback = 1;
249952cdd236Ssbehera 	else
250052cdd236Ssbehera 		pcs_ctl.bits.loopback = 0;
250152cdd236Ssbehera 
250252cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
250352cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
250452cdd236Ssbehera 
250552cdd236Ssbehera fail:
250652cdd236Ssbehera 	return (status);
250752cdd236Ssbehera }
250852cdd236Ssbehera 
250952cdd236Ssbehera 
251052cdd236Ssbehera static void
251152cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
251252cdd236Ssbehera {
251352cdd236Ssbehera 	uint16_t	val2;
251452cdd236Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
251552cdd236Ssbehera 
251652cdd236Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
251752cdd236Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
251852cdd236Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
251952cdd236Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
252052cdd236Ssbehera 
252152cdd236Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
252252cdd236Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
252352cdd236Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
252452cdd236Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
252552cdd236Ssbehera 	}
252652cdd236Ssbehera }
252752cdd236Ssbehera 
252852cdd236Ssbehera 
252952cdd236Ssbehera static nxge_status_t
253052cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
253152cdd236Ssbehera {
253252cdd236Ssbehera 	uint8_t		phy;
253352cdd236Ssbehera 	nxge_status_t	status;
253452cdd236Ssbehera 	uint16_t	clk;
253552cdd236Ssbehera 
253652cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
253752cdd236Ssbehera 
253852cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
253952cdd236Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
254052cdd236Ssbehera 	    nxgep->mac.portnum, phy));
254152cdd236Ssbehera 
254252cdd236Ssbehera 	/* Set LED functions	*/
254352cdd236Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
254452cdd236Ssbehera 	/* PCS activity */
254552cdd236Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
254652cdd236Ssbehera 
254752cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
254852cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
254952cdd236Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
255052cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
255152cdd236Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
255252cdd236Ssbehera 
255352cdd236Ssbehera 	/* Set internal loopback mode if necessary */
255452cdd236Ssbehera 
255552cdd236Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
255652cdd236Ssbehera 
255752cdd236Ssbehera 	/* Enable PMD */
255852cdd236Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
255952cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
256052cdd236Ssbehera 
256152cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
256252cdd236Ssbehera 
256352cdd236Ssbehera fail:
256452cdd236Ssbehera 	return (status);
256552cdd236Ssbehera }
256652cdd236Ssbehera 
256752cdd236Ssbehera 
256852cdd236Ssbehera 
25692d17280bSsbehera /* Initialize the 10G Transceiver */
25702d17280bSsbehera 
25712d17280bSsbehera static nxge_status_t
25722d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
25732d17280bSsbehera {
25742d17280bSsbehera 	p_nxge_stats_t		statsp;
25751bd6825cSml 	p_nxge_param_t		param_arr = nxgep->param_arr;
25762d17280bSsbehera 	nxge_status_t		status = NXGE_OK;
25772d17280bSsbehera #ifdef	NXGE_DEBUG
25782d17280bSsbehera 	uint8_t			portn = nxgep->mac.portnum;
25792d17280bSsbehera #endif
25802d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
25812d17280bSsbehera 	    portn));
25822d17280bSsbehera 
25832d17280bSsbehera 	statsp = nxgep->statsp;
25842d17280bSsbehera 
25852d17280bSsbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
25862d17280bSsbehera 		goto done;
25872d17280bSsbehera 	}
25882d17280bSsbehera 
25892d17280bSsbehera 	/* Disable Link LEDs */
25902d17280bSsbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
25912d17280bSsbehera 		goto fail;
25922d17280bSsbehera 
25932d17280bSsbehera 	/* Set Clause 45 */
25942d17280bSsbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
25952d17280bSsbehera 
25962d17280bSsbehera 	switch (nxgep->chip_id) {
25972d17280bSsbehera 	case BCM8704_CHIP_ID:
259800161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25992d17280bSsbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
26002d17280bSsbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
26012d17280bSsbehera 		break;
26022d17280bSsbehera 	case BCM8706_CHIP_ID:
260300161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
26042d17280bSsbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
26052d17280bSsbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
26062d17280bSsbehera 		break;
260752cdd236Ssbehera 	case MRVL88X201X_CHIP_ID:
260800161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
260952cdd236Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
261052cdd236Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
261152cdd236Ssbehera 		break;
26122d17280bSsbehera 	default:
26132d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
26142d17280bSsbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
26152d17280bSsbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
26162d17280bSsbehera 		goto fail;
26172d17280bSsbehera 	}
26182d17280bSsbehera 
26192d17280bSsbehera 	if (status != NXGE_OK) {
26202d17280bSsbehera 		goto fail;
26212d17280bSsbehera 	}
26222e59129aSraghus done:
262359ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
262459ac0c16Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
26251bd6825cSml 	statsp->mac_stats.adv_cap_asmpause =
26261bd6825cSml 	    param_arr[param_anar_asmpause].value;
26271bd6825cSml 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
262844961713Sgirish 
262959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
263059ac0c16Sdavemq 	    portn));
263159ac0c16Sdavemq 	return (NXGE_OK);
263244961713Sgirish 
263359ac0c16Sdavemq fail:
26342d17280bSsbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
263559ac0c16Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
26362d17280bSsbehera 	    "port<%d>", nxgep->mac.portnum));
26372d17280bSsbehera 	return (NXGE_ERROR);
263859ac0c16Sdavemq }
263944961713Sgirish 
264059ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
264144961713Sgirish 
264259ac0c16Sdavemq static nxge_status_t
264359ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
264459ac0c16Sdavemq {
264559ac0c16Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
264659ac0c16Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
264759ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
264844961713Sgirish 
26492e59129aSraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
26502e59129aSraghus 		statsp->mac_stats.cap_1000fdx =
26512e59129aSraghus 		    param_arr[param_anar_1000fdx].value;
26522e59129aSraghus 		goto done;
26532e59129aSraghus 	}
26542e59129aSraghus 
265559ac0c16Sdavemq 	/* Set Clause 22 */
265659ac0c16Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
265744961713Sgirish 
265859ac0c16Sdavemq 	/* Set capability flags */
265959ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
26602e59129aSraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
26612e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
26622e59129aSraghus 		statsp->mac_stats.cap_100fdx =
26632e59129aSraghus 		    param_arr[param_anar_100fdx].value;
26642e59129aSraghus 		statsp->mac_stats.cap_10fdx =
26652e59129aSraghus 		    param_arr[param_anar_10fdx].value;
26662e59129aSraghus 	}
266744961713Sgirish 
266859ac0c16Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
26692e59129aSraghus done:
267059ac0c16Sdavemq 	return (status);
267159ac0c16Sdavemq }
267259ac0c16Sdavemq 
267300161856Syc /*
267400161856Syc  * Although the Teranetics copper transceiver (TN1010) does not need
267500161856Syc  * to be initialized by the driver for passing packets, this funtion
267600161856Syc  * initializes the members of nxgep->statsp->mac_stats struct for
267700161856Syc  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
267800161856Syc  * It also configures the TN1010 for PHY loopback to support SunVTS.
267900161856Syc  *
268000161856Syc  * TN1010 only has the option to disable advertisement for the 10G
268100161856Syc  * mode. So we can set it to either Dual Mode or 1G Only mode but
268200161856Syc  * can't set it to 10G Only mode.
268300161856Syc  *
268400161856Syc  * ndd -set command can set the following 6 speed/duplex related parameters.
268500161856Syc  *
268600161856Syc  * ----------------------------------------------------------------
268700161856Syc  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
268800161856Syc  * ----------------------------------------------------------------
268900161856Syc  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
269000161856Syc  * adv_10gfdx_cap
269100161856Syc  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
269200161856Syc  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
269300161856Syc  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
269400161856Syc  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
269500161856Syc  * ----------------------------------------------------------------
269600161856Syc  */
269700161856Syc static nxge_status_t
269800161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep)
269900161856Syc {
270000161856Syc 	p_nxge_param_t		param_arr;
270100161856Syc 	p_nxge_stats_t		statsp;
270200161856Syc 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
270300161856Syc 	uint16_t		speed;
270400161856Syc 	uint8_t			phy_port_addr;
270500161856Syc 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
270600161856Syc 	int			status = NXGE_OK;
270700161856Syc 
270800161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
270900161856Syc 
271000161856Syc 	param_arr	= nxgep->param_arr;
271100161856Syc 	statsp		= nxgep->statsp;
271200161856Syc 
271300161856Syc 	/*
271400161856Syc 	 * Initialize the xcvr statistics which are NOT controlled by ndd
271500161856Syc 	 */
271600161856Syc 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
271700161856Syc 	statsp->mac_stats.cap_100T4    = 0;
271800161856Syc 
271900161856Syc 	/*
272000161856Syc 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
272100161856Syc 	 * that function nxge_check_tn1010_link repeatedly invoked by the
272200161856Syc 	 * timer will update link_speed real time.
272300161856Syc 	 */
272400161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
272500161856Syc 		goto fail;
272600161856Syc 	}
272700161856Syc 	if (speed == TN1010_SPEED_1G) {
272800161856Syc 		statsp->mac_stats.cap_10gfdx = 0;
272900161856Syc 	} else {
273000161856Syc 		statsp->mac_stats.cap_10gfdx = 1;
273100161856Syc 	}
273200161856Syc 
273300161856Syc 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
273400161856Syc 	statsp->mac_stats.cap_1000fdx  = 1;
273500161856Syc 
273600161856Syc 	/* TN1010 is not able to operate in the following states */
273700161856Syc 	statsp->mac_stats.cap_1000hdx  = 0;
273800161856Syc 	statsp->mac_stats.cap_100fdx   = 0;
273900161856Syc 	statsp->mac_stats.cap_100hdx   = 0;
274000161856Syc 	statsp->mac_stats.cap_10fdx    = 0;
274100161856Syc 	statsp->mac_stats.cap_10hdx    = 0;
274200161856Syc 
274300161856Syc 	/* param_anar_pause can be modified by ndd -set */
274400161856Syc 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
274500161856Syc 
274600161856Syc 	/*
274700161856Syc 	 * The following 4 lines actually overwrites what ever the ndd command
274800161856Syc 	 * has set. For example, by command
274900161856Syc 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
275000161856Syc 	 * we could set param_arr[param_autoneg].value to n.  However, because
275100161856Syc 	 * here we assign constants to these parameters, whatever we set with
275200161856Syc 	 * the "ndd -set" command will be replaced. So command
275300161856Syc 	 *	kstat nxge:X | grep param
275400161856Syc 	 * will always show those constant values.  In other words, the
275500161856Syc 	 * "ndd -set" command can NOT change the values of these 4 parameters
275600161856Syc 	 * even though the command appears to be successful.
275700161856Syc 	 *
275800161856Syc 	 * Note: TN1010 auto negotiation is always enabled.
275900161856Syc 	 */
276000161856Syc 	statsp->mac_stats.adv_cap_autoneg
276100161856Syc 	    = param_arr[param_autoneg].value = 1;
276200161856Syc 	statsp->mac_stats.adv_cap_1000fdx
276300161856Syc 	    = param_arr[param_anar_1000fdx].value = 1;
276400161856Syc 	statsp->mac_stats.adv_cap_100fdx
276500161856Syc 	    = param_arr[param_anar_100fdx].value = 0;
276600161856Syc 	statsp->mac_stats.adv_cap_10fdx
276700161856Syc 	    = param_arr[param_anar_10fdx].value = 0;
276800161856Syc 
276900161856Syc 	/*
277000161856Syc 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
277100161856Syc 	 * defined in nxge_param_arr[], therefore they are not seen by the
277200161856Syc 	 * "ndd -get" command and can not be changed by ndd.  We just set
277300161856Syc 	 * them (both ndd param and kstat values) to constant 0 because TN1010
277400161856Syc 	 * does not support those speeds.
277500161856Syc 	 */
277600161856Syc 	statsp->mac_stats.adv_cap_100T4
277700161856Syc 	    = param_arr[param_anar_100T4].value = 0;
277800161856Syc 	statsp->mac_stats.adv_cap_1000hdx
277900161856Syc 	    = param_arr[param_anar_1000hdx].value = 0;
278000161856Syc 	statsp->mac_stats.adv_cap_100hdx
278100161856Syc 	    = param_arr[param_anar_100hdx].value = 0;
278200161856Syc 	statsp->mac_stats.adv_cap_10hdx
278300161856Syc 	    = param_arr[param_anar_10hdx].value = 0;
278400161856Syc 
278500161856Syc 	/*
278600161856Syc 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
278700161856Syc 	 * by ndd
278800161856Syc 	 */
278900161856Syc 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
279000161856Syc 
279100161856Syc 	/*
279200161856Syc 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
279300161856Syc 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
279400161856Syc 	 * "ndd -get" command and can not be changed by ndd. Here we do not
279500161856Syc 	 * assign a constant to it so the default value defined in
279600161856Syc 	 * nxge_param_arr[] will be used to set the parameter and
279700161856Syc 	 * will be shown by the kstat.
279800161856Syc 	 */
279900161856Syc 	statsp->mac_stats.adv_cap_asmpause
280000161856Syc 	    = param_arr[param_anar_asmpause].value;
280100161856Syc 
280200161856Syc 	/*
280300161856Syc 	 * Initialize the link statistics.
280400161856Syc 	 */
280500161856Syc 	statsp->mac_stats.link_T4 = 0;
280600161856Syc 	statsp->mac_stats.link_asmpause = 0;
280700161856Syc 	statsp->mac_stats.link_pause = 0;
280800161856Syc 	if (speed == TN1010_SPEED_1G) {
280900161856Syc 		statsp->mac_stats.link_speed = 1000;
281000161856Syc 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
281100161856Syc 		statsp->mac_stats.link_up = 1;
281200161856Syc 	} else {
281300161856Syc 		statsp->mac_stats.link_speed = 10000;
281400161856Syc 		statsp->mac_stats.link_duplex = 2;
281500161856Syc 		statsp->mac_stats.link_up = 1;
281600161856Syc 	}
281700161856Syc 
281800161856Syc 	/*
281900161856Syc 	 * Because TN1010 does not have a link partner register, to
282000161856Syc 	 * figure out the link partner's capabilities is tricky. Here we
282100161856Syc 	 * just set the kstat based on our knowledge about the partner
282200161856Syc 	 * (The partner must support auto-neg because auto-negotiation
282300161856Syc 	 * has completed, it must support 1G or 10G because that is the
282400161856Syc 	 * negotiated speed we are using.)
282500161856Syc 	 *
282600161856Syc 	 * Note: Current kstat does not show lp_cap_10gfdx and
282700161856Syc 	 *	lp_cap_10ghdx.
282800161856Syc 	 */
282900161856Syc 	if (speed == TN1010_SPEED_1G) {
283000161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 1;
283100161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 0;
283200161856Syc 	} else {
283300161856Syc 		statsp->mac_stats.lp_cap_1000fdx  = 0;
283400161856Syc 		statsp->mac_stats.lp_cap_10gfdx   = 1;
283500161856Syc 	}
283600161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
283700161856Syc 	statsp->mac_stats.lp_cap_1000hdx  = 0;
283800161856Syc 	statsp->mac_stats.lp_cap_100fdx   = 0;
283900161856Syc 	statsp->mac_stats.lp_cap_100hdx   = 0;
284000161856Syc 	statsp->mac_stats.lp_cap_10fdx    = 0;
284100161856Syc 	statsp->mac_stats.lp_cap_10hdx    = 0;
284200161856Syc 	statsp->mac_stats.lp_cap_10gfdx   = 0;
284300161856Syc 	statsp->mac_stats.lp_cap_10ghdx   = 0;
284400161856Syc 	statsp->mac_stats.lp_cap_100T4    = 0;
284500161856Syc 	statsp->mac_stats.lp_cap_autoneg  = 1;
284600161856Syc 	statsp->mac_stats.lp_cap_asmpause = 0;
284700161856Syc 	statsp->mac_stats.lp_cap_pause    = 0;
284800161856Syc 
284900161856Syc 	/* Handle PHY loopback for SunVTS loopback test */
285000161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
285100161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
285200161856Syc 
285300161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
285400161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
285500161856Syc 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
285600161856Syc 		goto fail;
285700161856Syc 	}
285800161856Syc 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
285900161856Syc 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
286000161856Syc 		tn1010_pcs_ctrl.bits.loopback = 1;
286100161856Syc 	} else {
286200161856Syc 		tn1010_pcs_ctrl.bits.loopback = 0;
286300161856Syc 	}
286400161856Syc 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
286500161856Syc 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
286600161856Syc 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
286700161856Syc 		goto fail;
286800161856Syc 	}
286900161856Syc 
287000161856Syc 	statsp->mac_stats.xcvr_inits++;
287100161856Syc 
287200161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
287300161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
287400161856Syc 	return (status);
287500161856Syc fail:
287600161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
287700161856Syc 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
287800161856Syc 	return (status);
287900161856Syc }
288000161856Syc 
288159ac0c16Sdavemq /* Initialize transceiver */
288259ac0c16Sdavemq 
288359ac0c16Sdavemq nxge_status_t
288459ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
288559ac0c16Sdavemq {
288659ac0c16Sdavemq 	p_nxge_stats_t		statsp;
288759ac0c16Sdavemq #ifdef	NXGE_DEBUG
288859ac0c16Sdavemq 	uint8_t			portn;
288944961713Sgirish #endif
289044961713Sgirish 
289159ac0c16Sdavemq 	nxge_status_t		status = NXGE_OK;
289259ac0c16Sdavemq #ifdef	NXGE_DEBUG
289359ac0c16Sdavemq 	portn = nxgep->mac.portnum;
289459ac0c16Sdavemq #endif
289559ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
289659ac0c16Sdavemq 	statsp = nxgep->statsp;
289744961713Sgirish 
289859ac0c16Sdavemq 	/*
289900161856Syc 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
290000161856Syc 	 * modify mac_stats.
290159ac0c16Sdavemq 	 */
290259ac0c16Sdavemq 	statsp->mac_stats.cap_autoneg = 0;
290359ac0c16Sdavemq 	statsp->mac_stats.cap_100T4 = 0;
290459ac0c16Sdavemq 	statsp->mac_stats.cap_100fdx = 0;
290559ac0c16Sdavemq 	statsp->mac_stats.cap_100hdx = 0;
290659ac0c16Sdavemq 	statsp->mac_stats.cap_10fdx = 0;
290759ac0c16Sdavemq 	statsp->mac_stats.cap_10hdx = 0;
290859ac0c16Sdavemq 	statsp->mac_stats.cap_asmpause = 0;
290959ac0c16Sdavemq 	statsp->mac_stats.cap_pause = 0;
291059ac0c16Sdavemq 	statsp->mac_stats.cap_1000fdx = 0;
291159ac0c16Sdavemq 	statsp->mac_stats.cap_1000hdx = 0;
291259ac0c16Sdavemq 	statsp->mac_stats.cap_10gfdx = 0;
291359ac0c16Sdavemq 	statsp->mac_stats.cap_10ghdx = 0;
291459ac0c16Sdavemq 
291559ac0c16Sdavemq 	/*
291659ac0c16Sdavemq 	 * Initialize the link statistics.
291759ac0c16Sdavemq 	 */
291859ac0c16Sdavemq 	statsp->mac_stats.link_T4 = 0;
291959ac0c16Sdavemq 	statsp->mac_stats.link_asmpause = 0;
292059ac0c16Sdavemq 	statsp->mac_stats.link_pause = 0;
292144961713Sgirish 
292259ac0c16Sdavemq 	if (nxgep->xcvr.xcvr_init) {
292359ac0c16Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
292459ac0c16Sdavemq 		if (status != NXGE_OK)
292544961713Sgirish 			goto fail;
292659ac0c16Sdavemq 		statsp->mac_stats.xcvr_inits++;
292744961713Sgirish 	}
292844961713Sgirish 
292959ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
293059ac0c16Sdavemq 	    portn));
293144961713Sgirish 	return (NXGE_OK);
293244961713Sgirish 
293344961713Sgirish fail:
293444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
293559ac0c16Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
293659ac0c16Sdavemq 	    portn));
293744961713Sgirish 	return (status);
293844961713Sgirish }
293944961713Sgirish 
29402e59129aSraghus /* Look for transceiver type */
29412e59129aSraghus 
29422e59129aSraghus nxge_status_t
29432e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep)
29442e59129aSraghus {
2945d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
2946d81011f0Ssbehera 	    nxgep->mac.portnum));
29472e59129aSraghus 
29482e59129aSraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
29492e59129aSraghus 		return (NXGE_ERROR);
29502e59129aSraghus 
29512e59129aSraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
29522e59129aSraghus 		return (NXGE_ERROR);
29532e59129aSraghus 
29542e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
29552e59129aSraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
29562e59129aSraghus 	return (NXGE_OK);
29572e59129aSraghus }
295844961713Sgirish 
295944961713Sgirish /* Initialize the TxMAC sub-block */
296044961713Sgirish 
296144961713Sgirish nxge_status_t
296244961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep)
296344961713Sgirish {
296444961713Sgirish 	npi_attr_t		ap;
296544961713Sgirish 	uint8_t			portn;
296644961713Sgirish 	nxge_port_mode_t	portmode;
296744961713Sgirish 	nxge_port_t		portt;
296844961713Sgirish 	npi_handle_t		handle;
296944961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
297044961713Sgirish 
297144961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
297244961713Sgirish 	portt    = nxgep->mac.porttype;
297344961713Sgirish 	handle   = nxgep->npi_handle;
297444961713Sgirish 	portmode = nxgep->mac.portmode;
297544961713Sgirish 
297644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
297744961713Sgirish 			portn));
297844961713Sgirish 	/* Set Max and Min Frame Size */
29791bd6825cSml 	/*
29801bd6825cSml 	 * Use maxframesize to configure the hardware maxframe size
298100161856Syc 	 * and minframesize to configure the hardware minframe size.
29821bd6825cSml 	 */
29831bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29841bd6825cSml 	    "==> nxge_tx_mac_init: port<%d> "
29851bd6825cSml 	    "min framesize %d max framesize %d ",
29861bd6825cSml 	    nxgep->mac.minframesize,
29871bd6825cSml 	    nxgep->mac.maxframesize,
29881bd6825cSml 	    portn));
298944961713Sgirish 
29901bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
29911bd6825cSml 	    MAC_PORT_FRAME_SIZE,
29921bd6825cSml 	    nxgep->mac.minframesize,
29931bd6825cSml 	    nxgep->mac.maxframesize,
29941bd6825cSml 	    rs);
299544961713Sgirish 	if (rs != NPI_SUCCESS)
299644961713Sgirish 		goto fail;
299744961713Sgirish 
299844961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
299944961713Sgirish 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
300044961713Sgirish 				0)) != NPI_SUCCESS)
300144961713Sgirish 			goto fail;
300244961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
300344961713Sgirish 		if ((portmode == PORT_10G_FIBER) ||
30042e59129aSraghus 		    (portmode == PORT_10G_COPPER) ||
300500161856Syc 		    (portmode == PORT_10G_TN1010) ||
30062e59129aSraghus 		    (portmode == PORT_10G_SERDES)) {
300744961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
300844961713Sgirish 					XGMII_IPG_12_15, rs);
300944961713Sgirish 			if (rs != NPI_SUCCESS)
301044961713Sgirish 				goto fail;
301144961713Sgirish 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
301244961713Sgirish 		} else {
301344961713Sgirish 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
301444961713Sgirish 					MII_GMII_IPG_12, rs);
301544961713Sgirish 			if (rs != NPI_SUCCESS)
301644961713Sgirish 				goto fail;
301744961713Sgirish 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
301844961713Sgirish 		}
301944961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
302044961713Sgirish 				CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
302144961713Sgirish 			goto fail;
302244961713Sgirish 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
302344961713Sgirish 		nxgep->mac.maxburstsize = 0;	/* not programmable */
302444961713Sgirish 		nxgep->mac.ctrltype = 0;	/* not programmable */
302544961713Sgirish 		nxgep->mac.pa_size = 0;		/* not programmable */
302644961713Sgirish 
302744961713Sgirish 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
302844961713Sgirish 							!= NPI_SUCCESS)
302944961713Sgirish 			goto fail;
303044961713Sgirish 
303144961713Sgirish 	} else {
303244961713Sgirish 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
303344961713Sgirish 				0)) != NPI_SUCCESS)
303444961713Sgirish 			goto fail;
303544961713Sgirish 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
303644961713Sgirish 
303744961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
303844961713Sgirish 				rs);
303944961713Sgirish 		if (rs != NPI_SUCCESS)
304044961713Sgirish 			goto fail;
304144961713Sgirish 		nxgep->mac.ctrltype = 0x8808;
304244961713Sgirish 
304344961713Sgirish 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
304444961713Sgirish 		if (rs != NPI_SUCCESS)
304544961713Sgirish 			goto fail;
304644961713Sgirish 		nxgep->mac.pa_size = 0x7;
304744961713Sgirish 
304844961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
304944961713Sgirish 				CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
305044961713Sgirish 			goto fail;
305144961713Sgirish 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
305244961713Sgirish 	}
305344961713Sgirish 
305444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
305544961713Sgirish 			portn));
305644961713Sgirish 
305744961713Sgirish 	return (NXGE_OK);
305844961713Sgirish fail:
305944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
306044961713Sgirish 		"nxge_tx_mac_init: failed to initialize port<%d> TXMAC",
306144961713Sgirish 					portn));
306244961713Sgirish 
306344961713Sgirish 	return (NXGE_ERROR | rs);
306444961713Sgirish }
306544961713Sgirish 
3066678453a8Sspeer int
3067678453a8Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep)
3068678453a8Sspeer {
3069678453a8Sspeer 	int rdc_tbl;
3070678453a8Sspeer 
3071678453a8Sspeer 	/*
3072678453a8Sspeer 	 * Get an RDC table (version 0).
3073678453a8Sspeer 	 */
3074678453a8Sspeer 	if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) {
3075678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, OBP_CTL,
3076678453a8Sspeer 		    "nxge_hio_hostinfo_get_rdc_table: "
3077678453a8Sspeer 		    "there are no free RDC tables!"));
3078678453a8Sspeer 		return (EBUSY);
3079678453a8Sspeer 	}
3080678453a8Sspeer 
3081678453a8Sspeer 	return (rdc_tbl);
3082678453a8Sspeer }
3083678453a8Sspeer 
3084678453a8Sspeer /*
3085678453a8Sspeer  * nxge_hio_hostinfo_init
3086678453a8Sspeer  *
3087678453a8Sspeer  *	Initialize an alternate MAC address, and bind a macrdctbln to it.
3088678453a8Sspeer  *
3089678453a8Sspeer  * Arguments:
3090678453a8Sspeer  * 	nxge
3091678453a8Sspeer  * 	vr	The Virtualization Region
3092678453a8Sspeer  * 	macaddr	The alternate MAC address
3093678453a8Sspeer  *
3094678453a8Sspeer  * Notes:
3095678453a8Sspeer  *	1. Find & bind an RDC table to <nxge>.
3096678453a8Sspeer  *	2. Program an alternate MAC address (<macaddr>).
3097678453a8Sspeer  *	3. Bind the RDC table to <macaddr>.
3098678453a8Sspeer  *
3099678453a8Sspeer  * Context:
3100678453a8Sspeer  *	Service domain
3101678453a8Sspeer  *
3102678453a8Sspeer  * Side Effects:
3103678453a8Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
3104678453a8Sspeer  *	vr->slot & vr->altmac
3105678453a8Sspeer  *
3106678453a8Sspeer  */
3107678453a8Sspeer int
3108678453a8Sspeer nxge_hio_hostinfo_init(
3109678453a8Sspeer 	nxge_t *nxge,
3110678453a8Sspeer 	nxge_hio_vr_t *vr,	/* Virtualization Region */
3111678453a8Sspeer 	ether_addr_t *macaddr)	/* The alternate MAC address */
3112678453a8Sspeer {
3113678453a8Sspeer 	int rdc_tbl, slot;
3114678453a8Sspeer 
3115678453a8Sspeer 	nxge_class_pt_cfg_t *class;
3116678453a8Sspeer 	hostinfo_t mac_rdc;
3117678453a8Sspeer 	npi_mac_addr_t altmac;
3118678453a8Sspeer 	nxge_mmac_t *mmac_info;
3119678453a8Sspeer 	nxge_rdc_grp_t	*group;
3120678453a8Sspeer 	uint8_t *addr = (uint8_t *)macaddr;
3121678453a8Sspeer 
3122678453a8Sspeer 	mutex_enter(nxge->genlock);
3123678453a8Sspeer 
3124678453a8Sspeer 	rdc_tbl = vr->rdc_tbl;
3125678453a8Sspeer 
3126678453a8Sspeer 	/* Initialize the NXGE RDC table data structure. */
3127678453a8Sspeer 	group = &nxge->pt_config.rdc_grps[rdc_tbl];
3128678453a8Sspeer 	group->port = NXGE_GET_PORT_NUM(nxge->function_num);
3129678453a8Sspeer 	group->config_method = RDC_TABLE_ENTRY_METHOD_REP;
3130678453a8Sspeer 	group->flag = 1;	/* This group has been configured. */
3131678453a8Sspeer 
3132678453a8Sspeer 	mmac_info = &nxge->nxge_mmac_info;
3133678453a8Sspeer 
3134678453a8Sspeer 	/*
3135678453a8Sspeer 	 * Are there free slots.
3136678453a8Sspeer 	 */
3137678453a8Sspeer 	if (mmac_info->naddrfree == 0) {
3138678453a8Sspeer 		mutex_exit(nxge->genlock);
3139678453a8Sspeer 		return (ENOSPC);
3140678453a8Sspeer 	}
3141678453a8Sspeer 
3142678453a8Sspeer 	/*
3143678453a8Sspeer 	 * The vswitch has already added this MAC address.
3144678453a8Sspeer 	 * Find its assigned slot.
3145678453a8Sspeer 	 */
3146678453a8Sspeer 	if (mmac_info->num_factory_mmac < mmac_info->num_mmac) {
3147678453a8Sspeer 		for (slot = mmac_info->num_factory_mmac + 1;
3148678453a8Sspeer 		    slot <= mmac_info->num_mmac; slot++) {
3149678453a8Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
3150678453a8Sspeer 				break;
3151678453a8Sspeer 		}
3152678453a8Sspeer 		if (slot > mmac_info->num_mmac) {
3153678453a8Sspeer 			for (slot = 1; slot <= mmac_info->num_factory_mmac;
3154678453a8Sspeer 			    slot++) {
3155678453a8Sspeer 				if (!(mmac_info->mac_pool[slot].flags
3156678453a8Sspeer 				    & MMAC_SLOT_USED))
3157678453a8Sspeer 					break;
3158678453a8Sspeer 			}
3159678453a8Sspeer 		}
3160678453a8Sspeer 	} else {
3161678453a8Sspeer 		for (slot = 1; slot <= mmac_info->num_mmac; slot++) {
3162678453a8Sspeer 			if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED))
3163678453a8Sspeer 				break;
3164678453a8Sspeer 		}
3165678453a8Sspeer 	}
3166678453a8Sspeer 
3167678453a8Sspeer 	ASSERT(slot <= mmac_info->num_mmac);
3168678453a8Sspeer 	vr->slot = slot;
3169678453a8Sspeer 	slot = vr->slot - 1;
3170678453a8Sspeer 
3171678453a8Sspeer 	/*
317200161856Syc 	 * Program the mac address.
3173678453a8Sspeer 	 */
3174678453a8Sspeer 	altmac.w2 = (((uint16_t)addr[0]) << 8) |
3175678453a8Sspeer 	    (((uint16_t)addr[1]) & 0x0ff);
3176678453a8Sspeer 	altmac.w1 = (((uint16_t)addr[2]) << 8) |
3177678453a8Sspeer 	    (((uint16_t)addr[3]) & 0x0ff);
3178678453a8Sspeer 	altmac.w0 = (((uint16_t)addr[4]) << 8) |
3179678453a8Sspeer 	    (((uint16_t)addr[5]) & 0x0ff);
3180678453a8Sspeer 
3181678453a8Sspeer 	if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET,
3182678453a8Sspeer 	    nxge->function_num, slot, &altmac) != NPI_SUCCESS) {
3183678453a8Sspeer 		mutex_exit(nxge->genlock);
3184678453a8Sspeer 		return (EIO);
3185678453a8Sspeer 	}
3186678453a8Sspeer 
3187678453a8Sspeer 	/*
3188678453a8Sspeer 	 * Associate <rdc_tbl> with this MAC address slot.
3189678453a8Sspeer 	 */
3190678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
3191678453a8Sspeer 
3192678453a8Sspeer 	/* Update this variable. */
3193678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
3194678453a8Sspeer 	class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl;
3195678453a8Sspeer 
3196678453a8Sspeer 	mac_rdc.value = 0;
3197678453a8Sspeer 	mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl;
3198678453a8Sspeer 	mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr;
3199678453a8Sspeer 	/* <mpr_npr> had better be 1! */
3200678453a8Sspeer 
3201678453a8Sspeer 	/* Program the RDC table. */
3202678453a8Sspeer 	if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET,
3203678453a8Sspeer 		nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) {
3204678453a8Sspeer 		mutex_exit(nxge->genlock);
3205678453a8Sspeer 		(void) nxge_m_mmac_remove(nxge, vr->slot);
3206678453a8Sspeer 		return (EIO);
3207678453a8Sspeer 	}
3208678453a8Sspeer 
3209678453a8Sspeer 	if (nxge->mac.portnum != XMAC_PORT_0 &&
3210678453a8Sspeer 	    nxge->mac.portnum != XMAC_PORT_1)
3211678453a8Sspeer 		slot++;
3212678453a8Sspeer 
3213678453a8Sspeer 	/* (Re-)enable the MAC address. */
3214678453a8Sspeer 	(void) npi_mac_altaddr_enable(
3215678453a8Sspeer 		nxge->npi_handle, nxge->mac.portnum, slot);
3216678453a8Sspeer 
3217678453a8Sspeer 	bcopy(macaddr, vr->altmac, sizeof (vr->altmac));
3218678453a8Sspeer 
3219678453a8Sspeer 	/*
3220678453a8Sspeer 	 * Update mmac
3221678453a8Sspeer 	 */
3222678453a8Sspeer 	bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL);
3223678453a8Sspeer 	mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED;
3224678453a8Sspeer 	mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR;
3225678453a8Sspeer 	mmac_info->naddrfree--;
3226678453a8Sspeer 	nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE);
3227678453a8Sspeer 
3228678453a8Sspeer 	mutex_exit(nxge->genlock);
3229678453a8Sspeer 	return (0);
3230678453a8Sspeer }
3231678453a8Sspeer 
3232678453a8Sspeer /*
3233678453a8Sspeer  * nxge_hio_hostinfo_uninit
3234678453a8Sspeer  *
3235678453a8Sspeer  *	Uninitialize an alternate MAC address.
3236678453a8Sspeer  *
3237678453a8Sspeer  * Arguments:
3238678453a8Sspeer  * 	nxge
3239678453a8Sspeer  * 	vr	The Virtualization Region
3240678453a8Sspeer  *
3241678453a8Sspeer  * Notes:
3242678453a8Sspeer  *	1. Remove the VR's alternate MAC address.
3243678453a8Sspeer  *	1. Free (unbind) the RDC table allocated to this VR.
3244678453a8Sspeer  *
3245678453a8Sspeer  * Context:
3246678453a8Sspeer  *	Service domain
3247678453a8Sspeer  *
3248678453a8Sspeer  * Side Effects:
3249678453a8Sspeer  *	nxge->class_config.mac_host_info[slot].rdctbl
3250678453a8Sspeer  *
3251678453a8Sspeer  */
3252678453a8Sspeer void
3253678453a8Sspeer nxge_hio_hostinfo_uninit(
3254678453a8Sspeer 	nxge_t *nxge,
3255678453a8Sspeer 	nxge_hio_vr_t *vr)
3256678453a8Sspeer {
3257678453a8Sspeer 	nxge_class_pt_cfg_t *class;
3258678453a8Sspeer 
3259678453a8Sspeer 	(void) npi_mac_altaddr_disable(
3260678453a8Sspeer 		nxge->npi_handle, nxge->mac.portnum, vr->slot);
3261678453a8Sspeer 
3262678453a8Sspeer 	/* Set this variable to its default. */
3263678453a8Sspeer 	class = (p_nxge_class_pt_cfg_t)&nxge->class_config;
3264678453a8Sspeer 	class->mac_host_info[vr->slot].rdctbl =
3265678453a8Sspeer 	    nxge->pt_config.hw_config.def_mac_rxdma_grpid;
3266678453a8Sspeer 
3267678453a8Sspeer 	(void) nxge_m_mmac_remove(nxge, vr->slot);
3268678453a8Sspeer 	vr->slot = -1;
3269678453a8Sspeer 
3270678453a8Sspeer 	(void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl);
3271678453a8Sspeer 	vr->rdc_tbl = -1;
3272678453a8Sspeer }
3273678453a8Sspeer 
327444961713Sgirish /* Initialize the RxMAC sub-block */
327544961713Sgirish 
327644961713Sgirish nxge_status_t
327744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep)
327844961713Sgirish {
327944961713Sgirish 	npi_attr_t		ap;
328044961713Sgirish 	uint32_t		i;
328144961713Sgirish 	uint16_t		hashtab_e;
328244961713Sgirish 	p_hash_filter_t		hash_filter;
328344961713Sgirish 	nxge_port_t		portt;
328444961713Sgirish 	uint8_t			portn;
328544961713Sgirish 	npi_handle_t		handle;
328644961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
328744961713Sgirish 	uint16_t 		*addr16p;
328844961713Sgirish 	uint16_t 		addr0, addr1, addr2;
328944961713Sgirish 	xmac_rx_config_t	xconfig;
329044961713Sgirish 	bmac_rx_config_t	bconfig;
329144961713Sgirish 
329244961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
329344961713Sgirish 
329444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
329544961713Sgirish 			portn));
329644961713Sgirish 	handle = nxgep->npi_handle;
329744961713Sgirish 	portt = nxgep->mac.porttype;
329844961713Sgirish 
329944961713Sgirish 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
330044961713Sgirish 	addr0 = ntohs(addr16p[2]);
330144961713Sgirish 	addr1 = ntohs(addr16p[1]);
330244961713Sgirish 	addr2 = ntohs(addr16p[0]);
330344961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
330444961713Sgirish 		rs);
330544961713Sgirish 
330644961713Sgirish 	if (rs != NPI_SUCCESS)
330744961713Sgirish 		goto fail;
330844961713Sgirish 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
330944961713Sgirish 	if (rs != NPI_SUCCESS)
331044961713Sgirish 		goto fail;
331144961713Sgirish 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
331244961713Sgirish 	if (rs != NPI_SUCCESS)
331344961713Sgirish 		goto fail;
331444961713Sgirish 
331544961713Sgirish 	/*
331644961713Sgirish 	 * Load the multicast hash filter bits.
331744961713Sgirish 	 */
331844961713Sgirish 	hash_filter = nxgep->hash_filter;
331944961713Sgirish 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
332044961713Sgirish 		if (hash_filter != NULL) {
332144961713Sgirish 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
332244961713Sgirish 				(NMCFILTER_REGS - 1) - i];
332344961713Sgirish 		} else {
332444961713Sgirish 			hashtab_e = 0;
332544961713Sgirish 		}
332644961713Sgirish 
332744961713Sgirish 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
332844961713Sgirish 					(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
332944961713Sgirish 			goto fail;
333044961713Sgirish 	}
333144961713Sgirish 
333244961713Sgirish 	if (portt == PORT_TYPE_XMAC) {
333344961713Sgirish 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
333444961713Sgirish 				0)) != NPI_SUCCESS)
333544961713Sgirish 			goto fail;
333644961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
333744961713Sgirish 
333844961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
333944961713Sgirish 
334044961713Sgirish 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
3341a3c5bd6dSspeer 			CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
3342a3c5bd6dSspeer 			~CFG_XMAC_RX_STRIP_CRC;
334344961713Sgirish 
334444961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
334544961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
334644961713Sgirish 
334744961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
334844961713Sgirish 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
334944961713Sgirish 
335044961713Sgirish 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
335144961713Sgirish 
335244961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
335344961713Sgirish 					xconfig)) != NPI_SUCCESS)
335444961713Sgirish 			goto fail;
335544961713Sgirish 		nxgep->mac.rx_config = xconfig;
335644961713Sgirish 
335744961713Sgirish 		/* Comparison of mac unique address is always enabled on XMAC */
335844961713Sgirish 
335944961713Sgirish 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
336044961713Sgirish 							!= NPI_SUCCESS)
336144961713Sgirish 			goto fail;
336244961713Sgirish 	} else {
336344961713Sgirish 		(void) nxge_fflp_init_hostinfo(nxgep);
336444961713Sgirish 
336544961713Sgirish 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
336644961713Sgirish 					0) != NPI_SUCCESS)
336744961713Sgirish 			goto fail;
336844961713Sgirish 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
336944961713Sgirish 
3370a3c5bd6dSspeer 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
3371a3c5bd6dSspeer 			~CFG_BMAC_RX_STRIP_CRC;
337244961713Sgirish 
337344961713Sgirish 		if (nxgep->filter.all_phys_cnt != 0)
337444961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
337544961713Sgirish 
337644961713Sgirish 		if (nxgep->filter.all_multicast_cnt != 0)
337744961713Sgirish 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
337844961713Sgirish 
337944961713Sgirish 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
338044961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
338144961713Sgirish 					bconfig)) != NPI_SUCCESS)
338244961713Sgirish 			goto fail;
338344961713Sgirish 		nxgep->mac.rx_config = bconfig;
338444961713Sgirish 
338544961713Sgirish 		/* Always enable comparison of mac unique address */
338644961713Sgirish 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
338744961713Sgirish 					!= NPI_SUCCESS)
338844961713Sgirish 			goto fail;
338944961713Sgirish 	}
339044961713Sgirish 
339144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
339244961713Sgirish 			portn));
339344961713Sgirish 
339444961713Sgirish 	return (NXGE_OK);
339544961713Sgirish 
339644961713Sgirish fail:
339744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
339844961713Sgirish 		"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC",
339944961713Sgirish 				portn));
340044961713Sgirish 
340144961713Sgirish 	return (NXGE_ERROR | rs);
340244961713Sgirish }
340344961713Sgirish 
340444961713Sgirish /* Enable TXMAC */
340544961713Sgirish 
340644961713Sgirish nxge_status_t
340744961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep)
340844961713Sgirish {
340944961713Sgirish 	npi_handle_t	handle;
341044961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
341144961713Sgirish 	nxge_status_t	status = NXGE_OK;
341244961713Sgirish 
341344961713Sgirish 	handle = nxgep->npi_handle;
341444961713Sgirish 
341544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
341644961713Sgirish 			nxgep->mac.portnum));
341744961713Sgirish 
341844961713Sgirish 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
341944961713Sgirish 		goto fail;
342044961713Sgirish 
342144961713Sgirish 	/* based on speed */
342244961713Sgirish 	nxgep->msg_min = ETHERMIN;
342344961713Sgirish 
342444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
342544961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
342644961713Sgirish 						CFG_XMAC_TX)) != NPI_SUCCESS)
342744961713Sgirish 			goto fail;
342844961713Sgirish 	} else {
342944961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
343044961713Sgirish 						CFG_BMAC_TX)) != NPI_SUCCESS)
343144961713Sgirish 			goto fail;
343244961713Sgirish 	}
343344961713Sgirish 
343444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
343544961713Sgirish 			nxgep->mac.portnum));
343644961713Sgirish 
343744961713Sgirish 	return (NXGE_OK);
343844961713Sgirish fail:
343944961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
344044961713Sgirish 			"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
344144961713Sgirish 			nxgep->mac.portnum));
344244961713Sgirish 	if (rs != NPI_SUCCESS)
344344961713Sgirish 		return (NXGE_ERROR | rs);
344444961713Sgirish 	else
344544961713Sgirish 		return (status);
344644961713Sgirish }
344744961713Sgirish 
344844961713Sgirish /* Disable TXMAC */
344944961713Sgirish 
345044961713Sgirish nxge_status_t
345144961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep)
345244961713Sgirish {
345344961713Sgirish 	npi_handle_t	handle;
345444961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
345544961713Sgirish 
3456678453a8Sspeer 	if (isLDOMguest(nxgep))
3457678453a8Sspeer 		return (NXGE_OK);
3458678453a8Sspeer 
345944961713Sgirish 	handle = nxgep->npi_handle;
346044961713Sgirish 
346144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
346244961713Sgirish 			nxgep->mac.portnum));
346344961713Sgirish 
346444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
346544961713Sgirish 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
346644961713Sgirish 			nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
346744961713Sgirish 			goto fail;
346844961713Sgirish 	} else {
346944961713Sgirish 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
347044961713Sgirish 			nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
347144961713Sgirish 			goto fail;
347244961713Sgirish 	}
347344961713Sgirish 
347444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
347544961713Sgirish 			nxgep->mac.portnum));
347644961713Sgirish 	return (NXGE_OK);
347744961713Sgirish fail:
347844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
347944961713Sgirish 			"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
348044961713Sgirish 			nxgep->mac.portnum));
348144961713Sgirish 	return (NXGE_ERROR | rs);
348244961713Sgirish }
348344961713Sgirish 
348444961713Sgirish /* Enable RXMAC */
348544961713Sgirish 
348644961713Sgirish nxge_status_t
348744961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep)
348844961713Sgirish {
348944961713Sgirish 	npi_handle_t	handle;
349044961713Sgirish 	uint8_t 	portn;
349144961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
349244961713Sgirish 	nxge_status_t	status = NXGE_OK;
349344961713Sgirish 
3494678453a8Sspeer 	/* This is a service-domain-only activity. */
3495678453a8Sspeer 	if (isLDOMguest(nxgep))
3496678453a8Sspeer 		return (status);
3497678453a8Sspeer 
349844961713Sgirish 	handle = nxgep->npi_handle;
349944961713Sgirish 	portn = nxgep->mac.portnum;
350044961713Sgirish 
350144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
350244961713Sgirish 			portn));
350344961713Sgirish 
350444961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
350544961713Sgirish 		goto fail;
350644961713Sgirish 
350744961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
350844961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
3509678453a8Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
351044961713Sgirish 			goto fail;
351144961713Sgirish 	} else {
351244961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
3513678453a8Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
351444961713Sgirish 			goto fail;
351544961713Sgirish 	}
351644961713Sgirish 
3517678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3518678453a8Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
351944961713Sgirish 
352044961713Sgirish 	return (NXGE_OK);
352144961713Sgirish fail:
352244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3523678453a8Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
352444961713Sgirish 
352544961713Sgirish 	if (rs != NPI_SUCCESS)
352644961713Sgirish 		return (NXGE_ERROR | rs);
352744961713Sgirish 	else
352844961713Sgirish 		return (status);
352944961713Sgirish }
353044961713Sgirish 
353144961713Sgirish /* Disable RXMAC */
353244961713Sgirish 
353344961713Sgirish nxge_status_t
353444961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep)
353544961713Sgirish {
353644961713Sgirish 	npi_handle_t	handle;
353744961713Sgirish 	uint8_t		portn;
353844961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
353944961713Sgirish 
3540678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
3541678453a8Sspeer 	if (isLDOMguest(nxgep))
3542678453a8Sspeer 		return (NXGE_OK);
3543678453a8Sspeer 
354444961713Sgirish 	handle = nxgep->npi_handle;
354544961713Sgirish 	portn = nxgep->mac.portnum;
354644961713Sgirish 
354744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
354844961713Sgirish 			portn));
354944961713Sgirish 
355044961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
355144961713Sgirish 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
355244961713Sgirish 						CFG_XMAC_RX)) != NPI_SUCCESS)
355344961713Sgirish 			goto fail;
355444961713Sgirish 	} else {
355544961713Sgirish 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
355644961713Sgirish 						CFG_BMAC_RX)) != NPI_SUCCESS)
355744961713Sgirish 			goto fail;
355844961713Sgirish 	}
355944961713Sgirish 
356044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
356144961713Sgirish 			portn));
356244961713Sgirish 	return (NXGE_OK);
356344961713Sgirish fail:
356444961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
356544961713Sgirish 			"nxgep_rx_mac_disable: ",
356644961713Sgirish 			"Failed to disable port<%d> RxMAC",
356744961713Sgirish 			portn));
356844961713Sgirish 
356944961713Sgirish 	return (NXGE_ERROR | rs);
357044961713Sgirish }
357144961713Sgirish 
357244961713Sgirish /* Reset TXMAC */
357344961713Sgirish 
357444961713Sgirish nxge_status_t
357544961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep)
357644961713Sgirish {
357744961713Sgirish 	npi_handle_t	handle;
357844961713Sgirish 	uint8_t		portn;
357944961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
358044961713Sgirish 
358144961713Sgirish 	handle = nxgep->npi_handle;
358244961713Sgirish 	portn = nxgep->mac.portnum;
358344961713Sgirish 
358444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
358544961713Sgirish 			portn));
358644961713Sgirish 
358744961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
358844961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
358944961713Sgirish 		    != NPI_SUCCESS)
359044961713Sgirish 			goto fail;
359144961713Sgirish 	} else {
359244961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
359344961713Sgirish 					!= NPI_SUCCESS)
359444961713Sgirish 			goto fail;
359544961713Sgirish 	}
359644961713Sgirish 
359744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
359844961713Sgirish 			portn));
359944961713Sgirish 
360044961713Sgirish 	return (NXGE_OK);
360144961713Sgirish fail:
360244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
360344961713Sgirish 			"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>",
360444961713Sgirish 			portn));
360544961713Sgirish 
360644961713Sgirish 	return (NXGE_ERROR | rs);
360744961713Sgirish }
360844961713Sgirish 
360944961713Sgirish /* Reset RXMAC */
361044961713Sgirish 
361144961713Sgirish nxge_status_t
361244961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep)
361344961713Sgirish {
361444961713Sgirish 	npi_handle_t	handle;
361544961713Sgirish 	uint8_t		portn;
361644961713Sgirish 	npi_status_t	rs = NPI_SUCCESS;
361744961713Sgirish 
361844961713Sgirish 	handle = nxgep->npi_handle;
361944961713Sgirish 	portn = nxgep->mac.portnum;
362044961713Sgirish 
362144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
362244961713Sgirish 			portn));
362344961713Sgirish 
362444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
362544961713Sgirish 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
362644961713Sgirish 		    != NPI_SUCCESS)
362744961713Sgirish 		goto fail;
362844961713Sgirish 	} else {
362944961713Sgirish 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
363044961713Sgirish 					!= NPI_SUCCESS)
363144961713Sgirish 		goto fail;
363244961713Sgirish 	}
363344961713Sgirish 
363444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
363544961713Sgirish 			portn));
363644961713Sgirish 
363759ac0c16Sdavemq 	return (NXGE_OK);
363859ac0c16Sdavemq fail:
363959ac0c16Sdavemq 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
364059ac0c16Sdavemq 			"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>",
364159ac0c16Sdavemq 			portn));
364259ac0c16Sdavemq 	return (NXGE_ERROR | rs);
364359ac0c16Sdavemq }
364459ac0c16Sdavemq 
364559ac0c16Sdavemq /* 10G fiber link interrupt start routine */
364659ac0c16Sdavemq 
364759ac0c16Sdavemq static nxge_status_t
364859ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
364959ac0c16Sdavemq {
365059ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
365159ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
365259ac0c16Sdavemq 
365359ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
365459ac0c16Sdavemq 
365559ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
365659ac0c16Sdavemq 		return (NXGE_ERROR | rs);
365759ac0c16Sdavemq 	else
365859ac0c16Sdavemq 		return (NXGE_OK);
365959ac0c16Sdavemq }
366059ac0c16Sdavemq 
366159ac0c16Sdavemq /* 10G fiber link interrupt stop routine */
366259ac0c16Sdavemq 
366359ac0c16Sdavemq static nxge_status_t
366459ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
366559ac0c16Sdavemq {
366659ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
366759ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
366859ac0c16Sdavemq 
366959ac0c16Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
367059ac0c16Sdavemq 
367159ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
367259ac0c16Sdavemq 		return (NXGE_ERROR | rs);
367359ac0c16Sdavemq 	else
367459ac0c16Sdavemq 		return (NXGE_OK);
367559ac0c16Sdavemq }
367659ac0c16Sdavemq 
367759ac0c16Sdavemq /* 1G fiber link interrupt start routine */
367859ac0c16Sdavemq 
367959ac0c16Sdavemq static nxge_status_t
368059ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
368159ac0c16Sdavemq {
368259ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
368359ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
368459ac0c16Sdavemq 
368559ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
368659ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
368759ac0c16Sdavemq 		return (NXGE_ERROR | rs);
368859ac0c16Sdavemq 	else
368959ac0c16Sdavemq 		return (NXGE_OK);
369059ac0c16Sdavemq }
369159ac0c16Sdavemq 
369259ac0c16Sdavemq /* 1G fiber link interrupt stop routine */
369359ac0c16Sdavemq 
369459ac0c16Sdavemq static nxge_status_t
369559ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
369659ac0c16Sdavemq {
369759ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
369859ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
369959ac0c16Sdavemq 
370059ac0c16Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
370159ac0c16Sdavemq 
370259ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
370359ac0c16Sdavemq 		return (NXGE_ERROR | rs);
370459ac0c16Sdavemq 	else
370559ac0c16Sdavemq 		return (NXGE_OK);
370659ac0c16Sdavemq }
370759ac0c16Sdavemq 
370859ac0c16Sdavemq /* 1G copper link interrupt start routine */
370959ac0c16Sdavemq 
371059ac0c16Sdavemq static nxge_status_t
371159ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
371259ac0c16Sdavemq {
371359ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
371459ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
371559ac0c16Sdavemq 
371659ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
37176b438925Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
371859ac0c16Sdavemq 
371959ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
372059ac0c16Sdavemq 		return (NXGE_ERROR | rs);
372159ac0c16Sdavemq 	else
372259ac0c16Sdavemq 		return (NXGE_OK);
372344961713Sgirish }
372444961713Sgirish 
372559ac0c16Sdavemq /* 1G copper link interrupt stop routine */
372659ac0c16Sdavemq 
372759ac0c16Sdavemq static nxge_status_t
372859ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
372959ac0c16Sdavemq {
373059ac0c16Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
373159ac0c16Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
373259ac0c16Sdavemq 
373359ac0c16Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
373459ac0c16Sdavemq 
373559ac0c16Sdavemq 	if (rs != NPI_SUCCESS)
373659ac0c16Sdavemq 		return (NXGE_ERROR | rs);
373759ac0c16Sdavemq 	else
373859ac0c16Sdavemq 		return (NXGE_OK);
373959ac0c16Sdavemq }
374044961713Sgirish 
374159ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */
374244961713Sgirish 
374344961713Sgirish nxge_status_t
374444961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
374544961713Sgirish {
374659ac0c16Sdavemq 	uint8_t		portn;
374759ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
374844961713Sgirish 
374944961713Sgirish 	portn = nxgep->mac.portnum;
375044961713Sgirish 
375144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
375259ac0c16Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
375359ac0c16Sdavemq 		return (NXGE_OK);
375444961713Sgirish 
375559ac0c16Sdavemq 	if (enable == LINK_INTR_START)
375659ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
375759ac0c16Sdavemq 	else if (enable == LINK_INTR_STOP)
375859ac0c16Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
375959ac0c16Sdavemq 	if (status != NXGE_OK)
376059ac0c16Sdavemq 		goto fail;
376144961713Sgirish 
376244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
376344961713Sgirish 
376444961713Sgirish 	return (NXGE_OK);
376544961713Sgirish fail:
376644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
376744961713Sgirish 			"nxge_link_intr: Failed to set port<%d> mif intr mode",
376844961713Sgirish 			portn));
376944961713Sgirish 
377059ac0c16Sdavemq 	return (status);
377144961713Sgirish }
377244961713Sgirish 
377344961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
377444961713Sgirish 
377544961713Sgirish nxge_status_t
377644961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep)
377744961713Sgirish {
377844961713Sgirish 	p_nxge_param_t	param_arr;
377944961713Sgirish 	p_nxge_stats_t	statsp;
378044961713Sgirish 	uint8_t		xcvr_portn;
378144961713Sgirish 	p_mii_regs_t	mii_regs;
378244961713Sgirish 	mii_bmcr_t	bmcr;
378344961713Sgirish 	mii_bmsr_t	bmsr;
378444961713Sgirish 	mii_anar_t	anar;
378544961713Sgirish 	mii_gcr_t	gcr;
378644961713Sgirish 	mii_esr_t	esr;
378744961713Sgirish 	mii_aux_ctl_t	bcm5464r_aux;
378844961713Sgirish 	int		status = NXGE_OK;
378944961713Sgirish 
379044961713Sgirish 	uint_t delay;
379144961713Sgirish 
379244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
379344961713Sgirish 
379444961713Sgirish 	param_arr = nxgep->param_arr;
379544961713Sgirish 	statsp = nxgep->statsp;
379644961713Sgirish 	xcvr_portn = statsp->mac_stats.xcvr_portn;
379744961713Sgirish 
379844961713Sgirish 	mii_regs = NULL;
379944961713Sgirish 
380044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
380144961713Sgirish 		"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
380244961713Sgirish 
3803d81011f0Ssbehera 	/*
3804d81011f0Ssbehera 	 * The mif phy mode may be connected to either a copper link
3805d81011f0Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
3806d81011f0Ssbehera 	 * configuration if it is hard-wired to fiber link.
3807d81011f0Ssbehera 	 */
3808d81011f0Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
3809d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
3810d81011f0Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
3811d81011f0Ssbehera 	}
3812d81011f0Ssbehera 
381344961713Sgirish 	/*
381444961713Sgirish 	 * Reset the transceiver.
381544961713Sgirish 	 */
381644961713Sgirish 	delay = 0;
381744961713Sgirish 	bmcr.value = 0;
381844961713Sgirish 	bmcr.bits.reset = 1;
381944961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3820adfcba55Sjoycey #if defined(__i386)
3821adfcba55Sjoycey 		(uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3822adfcba55Sjoycey #else
382344961713Sgirish 		(uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK)
3824adfcba55Sjoycey #endif
382544961713Sgirish 		goto fail;
382644961713Sgirish 	do {
382744961713Sgirish 		drv_usecwait(500);
382844961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3829adfcba55Sjoycey #if defined(__i386)
3830adfcba55Sjoycey 			(uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value))
3831adfcba55Sjoycey #else
383244961713Sgirish 			(uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value))
3833adfcba55Sjoycey #endif
383444961713Sgirish 				!= NXGE_OK)
383544961713Sgirish 			goto fail;
383644961713Sgirish 		delay++;
383744961713Sgirish 	} while ((bmcr.bits.reset) && (delay < 1000));
383844961713Sgirish 	if (delay == 1000) {
383944961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
384044961713Sgirish 		goto fail;
384144961713Sgirish 	}
384244961713Sgirish 
384344961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
3844adfcba55Sjoycey #if defined(__i386)
3845adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmsr),
3846adfcba55Sjoycey #else
384744961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmsr),
3848adfcba55Sjoycey #endif
384944961713Sgirish 			&bmsr.value)) != NXGE_OK)
385044961713Sgirish 		goto fail;
385144961713Sgirish 
385244961713Sgirish 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
385344961713Sgirish 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
385444961713Sgirish 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
385544961713Sgirish 	param_arr[param_anar_100hdx].value = 0;
385644961713Sgirish 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
385744961713Sgirish 	param_arr[param_anar_10hdx].value = 0;
385844961713Sgirish 
385944961713Sgirish 	/*
386058324dfcSspeer 	 * Initialize the xcvr statistics.
386144961713Sgirish 	 */
386244961713Sgirish 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
386344961713Sgirish 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
386444961713Sgirish 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
386544961713Sgirish 	statsp->mac_stats.cap_100hdx = 0;
386644961713Sgirish 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
386744961713Sgirish 	statsp->mac_stats.cap_10hdx = 0;
386844961713Sgirish 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
386944961713Sgirish 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
387044961713Sgirish 
387144961713Sgirish 	/*
387200161856Syc 	 * Initialize the xcvr advertised capability statistics.
387344961713Sgirish 	 */
387444961713Sgirish 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
387544961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
387644961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
387744961713Sgirish 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
387844961713Sgirish 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
387944961713Sgirish 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
388044961713Sgirish 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
388144961713Sgirish 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
388244961713Sgirish 	statsp->mac_stats.adv_cap_asmpause =
388344961713Sgirish 					param_arr[param_anar_asmpause].value;
388444961713Sgirish 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
388544961713Sgirish 
388644961713Sgirish 
388744961713Sgirish 	/*
388844961713Sgirish 	 * Check for extended status just in case we're
388944961713Sgirish 	 * running a Gigibit phy.
389044961713Sgirish 	 */
389144961713Sgirish 	if (bmsr.bits.extend_status) {
389244961713Sgirish 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
3893adfcba55Sjoycey #if defined(__i386)
3894adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->esr), &esr.value))
3895adfcba55Sjoycey #else
389644961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value))
3897adfcba55Sjoycey #endif
389844961713Sgirish 				!= NXGE_OK)
389944961713Sgirish 			goto fail;
390044961713Sgirish 		param_arr[param_anar_1000fdx].value &=
390144961713Sgirish 					esr.bits.link_1000fdx;
390244961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
390344961713Sgirish 
390444961713Sgirish 		statsp->mac_stats.cap_1000fdx =
390544961713Sgirish 			(esr.bits.link_1000Xfdx ||
390644961713Sgirish 				esr.bits.link_1000fdx);
390744961713Sgirish 		statsp->mac_stats.cap_1000hdx = 0;
390844961713Sgirish 	} else {
390944961713Sgirish 		param_arr[param_anar_1000fdx].value = 0;
391044961713Sgirish 		param_arr[param_anar_1000hdx].value = 0;
391144961713Sgirish 	}
391244961713Sgirish 
391344961713Sgirish 	/*
391444961713Sgirish 	 * Initialize 1G Statistics once the capability is established.
391544961713Sgirish 	 */
391644961713Sgirish 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
391744961713Sgirish 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
391844961713Sgirish 
391944961713Sgirish 	/*
392000161856Syc 	 * Initialize the link statistics.
392144961713Sgirish 	 */
392244961713Sgirish 	statsp->mac_stats.link_T4 = 0;
392344961713Sgirish 	statsp->mac_stats.link_asmpause = 0;
392444961713Sgirish 	statsp->mac_stats.link_pause = 0;
392544961713Sgirish 	statsp->mac_stats.link_speed = 0;
392644961713Sgirish 	statsp->mac_stats.link_duplex = 0;
392744961713Sgirish 	statsp->mac_stats.link_up = 0;
392844961713Sgirish 
392944961713Sgirish 	/*
393044961713Sgirish 	 * Switch off Auto-negotiation, 100M and full duplex.
393144961713Sgirish 	 */
393244961713Sgirish 	bmcr.value = 0;
393344961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
3934adfcba55Sjoycey #if defined(__i386)
3935adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3936adfcba55Sjoycey #else
393744961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
3938adfcba55Sjoycey #endif
393944961713Sgirish 		goto fail;
394044961713Sgirish 
394144961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
394244961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
394344961713Sgirish 		bmcr.bits.loopback = 1;
394444961713Sgirish 		bmcr.bits.enable_autoneg = 0;
394544961713Sgirish 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
394644961713Sgirish 			bmcr.bits.speed_1000_sel = 1;
394744961713Sgirish 		bmcr.bits.duplex_mode = 1;
394844961713Sgirish 		param_arr[param_autoneg].value = 0;
394944961713Sgirish 	} else {
395044961713Sgirish 		bmcr.bits.loopback = 0;
395144961713Sgirish 	}
395244961713Sgirish 
395344961713Sgirish 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
395444961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
395544961713Sgirish 		(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
395644961713Sgirish 		param_arr[param_autoneg].value = 0;
395744961713Sgirish 		bcm5464r_aux.value = 0;
395844961713Sgirish 		bcm5464r_aux.bits.ext_lb = 1;
395944961713Sgirish 		bcm5464r_aux.bits.write_1 = 1;
396044961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
396144961713Sgirish 				BCM5464R_AUX_CTL, bcm5464r_aux.value))
396244961713Sgirish 				!= NXGE_OK)
396344961713Sgirish 			goto fail;
396444961713Sgirish 	}
396544961713Sgirish 
396600161856Syc 	/* If auto-negotiation is desired */
396744961713Sgirish 	if (param_arr[param_autoneg].value) {
396844961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
396944961713Sgirish 				"Restarting Auto-negotiation."));
397044961713Sgirish 		/*
397144961713Sgirish 		 * Setup our Auto-negotiation advertisement register.
397244961713Sgirish 		 */
397344961713Sgirish 		anar.value = 0;
397444961713Sgirish 		anar.bits.selector = 1;
397544961713Sgirish 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
397644961713Sgirish 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
397744961713Sgirish 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
397844961713Sgirish 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
397944961713Sgirish 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
398044961713Sgirish 		anar.bits.cap_asmpause = 0;
398144961713Sgirish 		anar.bits.cap_pause = 0;
398244961713Sgirish 		if (param_arr[param_anar_1000fdx].value ||
398344961713Sgirish 			param_arr[param_anar_100fdx].value ||
398444961713Sgirish 			param_arr[param_anar_10fdx].value) {
398544961713Sgirish 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
398644961713Sgirish 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
398744961713Sgirish 		}
398844961713Sgirish 
398900161856Syc 		/* Write to the auto-negotiation advertisement register */
399044961713Sgirish 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
3991adfcba55Sjoycey #if defined(__i386)
3992adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->anar), anar.value))
3993adfcba55Sjoycey #else
399444961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->anar), anar.value))
3995adfcba55Sjoycey #endif
399644961713Sgirish 				!= NXGE_OK)
399744961713Sgirish 			goto fail;
399844961713Sgirish 		if (bmsr.bits.extend_status) {
399944961713Sgirish 			gcr.value = 0;
400044961713Sgirish 			gcr.bits.ms_mode_en =
400144961713Sgirish 				param_arr[param_master_cfg_enable].value;
400244961713Sgirish 			gcr.bits.master =
400344961713Sgirish 				param_arr[param_master_cfg_value].value;
400444961713Sgirish 			gcr.bits.link_1000fdx =
400544961713Sgirish 				param_arr[param_anar_1000fdx].value;
400644961713Sgirish 			gcr.bits.link_1000hdx =
400744961713Sgirish 				param_arr[param_anar_1000hdx].value;
400844961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4009adfcba55Sjoycey #if defined(__i386)
4010adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value))
4011adfcba55Sjoycey #else
401244961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value))
4013adfcba55Sjoycey #endif
401444961713Sgirish 				!= NXGE_OK)
401544961713Sgirish 				goto fail;
401644961713Sgirish 		}
401744961713Sgirish 
401844961713Sgirish 		bmcr.bits.enable_autoneg = 1;
401944961713Sgirish 		bmcr.bits.restart_autoneg = 1;
402044961713Sgirish 
402144961713Sgirish 	} else {
402244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
402344961713Sgirish 		bmcr.bits.speed_1000_sel =
402444961713Sgirish 			param_arr[param_anar_1000fdx].value |
402544961713Sgirish 				param_arr[param_anar_1000hdx].value;
402644961713Sgirish 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
402744961713Sgirish 			(param_arr[param_anar_100fdx].value |
402844961713Sgirish 				param_arr[param_anar_100hdx].value);
402900161856Syc 
403000161856Syc 		/* Force to 1G */
403144961713Sgirish 		if (bmcr.bits.speed_1000_sel) {
403244961713Sgirish 			statsp->mac_stats.link_speed = 1000;
403344961713Sgirish 			gcr.value = 0;
403444961713Sgirish 			gcr.bits.ms_mode_en =
403544961713Sgirish 				param_arr[param_master_cfg_enable].value;
403644961713Sgirish 			gcr.bits.master =
403744961713Sgirish 				param_arr[param_master_cfg_value].value;
403844961713Sgirish 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
4039adfcba55Sjoycey #if defined(__i386)
4040adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gcr),
4041adfcba55Sjoycey #else
404244961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->gcr),
4043adfcba55Sjoycey #endif
404444961713Sgirish 				gcr.value))
404544961713Sgirish 				!= NXGE_OK)
404644961713Sgirish 				goto fail;
404744961713Sgirish 			if (param_arr[param_anar_1000fdx].value) {
404844961713Sgirish 				bmcr.bits.duplex_mode = 1;
404944961713Sgirish 				statsp->mac_stats.link_duplex = 2;
405044961713Sgirish 			} else
405144961713Sgirish 				statsp->mac_stats.link_duplex = 1;
405200161856Syc 
405300161856Syc 		/* Force to 100M */
405444961713Sgirish 		} else if (bmcr.bits.speed_sel) {
405544961713Sgirish 			statsp->mac_stats.link_speed = 100;
405644961713Sgirish 			if (param_arr[param_anar_100fdx].value) {
405744961713Sgirish 				bmcr.bits.duplex_mode = 1;
405844961713Sgirish 				statsp->mac_stats.link_duplex = 2;
405944961713Sgirish 			} else
406044961713Sgirish 				statsp->mac_stats.link_duplex = 1;
406100161856Syc 
406200161856Syc 		/* Force to 10M */
406344961713Sgirish 		} else {
406444961713Sgirish 			statsp->mac_stats.link_speed = 10;
406544961713Sgirish 			if (param_arr[param_anar_10fdx].value) {
406644961713Sgirish 				bmcr.bits.duplex_mode = 1;
406744961713Sgirish 				statsp->mac_stats.link_duplex = 2;
406844961713Sgirish 			} else
406944961713Sgirish 				statsp->mac_stats.link_duplex = 1;
407044961713Sgirish 		}
407144961713Sgirish 		if (statsp->mac_stats.link_duplex != 1) {
407244961713Sgirish 			statsp->mac_stats.link_asmpause =
407344961713Sgirish 						statsp->mac_stats.cap_asmpause;
407444961713Sgirish 			statsp->mac_stats.link_pause =
407544961713Sgirish 						statsp->mac_stats.cap_pause;
407644961713Sgirish 		}
407744961713Sgirish 
407844961713Sgirish 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
407944961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
408044961713Sgirish 			(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
408144961713Sgirish 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
408244961713Sgirish 				/* BCM5464R 1000mbps external loopback mode */
408344961713Sgirish 				gcr.value = 0;
408444961713Sgirish 				gcr.bits.ms_mode_en = 1;
408544961713Sgirish 				gcr.bits.master = 1;
408644961713Sgirish 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
4087adfcba55Sjoycey #if defined(__i386)
4088adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gcr),
4089adfcba55Sjoycey #else
409044961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gcr),
4091adfcba55Sjoycey #endif
409244961713Sgirish 					gcr.value))
409344961713Sgirish 					!= NXGE_OK)
409444961713Sgirish 					goto fail;
409544961713Sgirish 				bmcr.value = 0;
409644961713Sgirish 				bmcr.bits.speed_1000_sel = 1;
409744961713Sgirish 				statsp->mac_stats.link_speed = 1000;
409844961713Sgirish 			} else if (statsp->port_stats.lb_mode
409944961713Sgirish 			    == nxge_lb_ext100) {
410044961713Sgirish 				/* BCM5464R 100mbps external loopback mode */
410144961713Sgirish 				bmcr.value = 0;
410244961713Sgirish 				bmcr.bits.speed_sel = 1;
410344961713Sgirish 				bmcr.bits.duplex_mode = 1;
410444961713Sgirish 				statsp->mac_stats.link_speed = 100;
410544961713Sgirish 			} else if (statsp->port_stats.lb_mode
410644961713Sgirish 			    == nxge_lb_ext10) {
410744961713Sgirish 				/* BCM5464R 10mbps external loopback mode */
410844961713Sgirish 				bmcr.value = 0;
410944961713Sgirish 				bmcr.bits.duplex_mode = 1;
411044961713Sgirish 				statsp->mac_stats.link_speed = 10;
411144961713Sgirish 			}
411244961713Sgirish 		}
411344961713Sgirish 	}
411444961713Sgirish 
411544961713Sgirish 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4116adfcba55Sjoycey #if defined(__i386)
4117adfcba55Sjoycey 			(uint8_t)(uint32_t)(&mii_regs->bmcr),
4118adfcba55Sjoycey #else
411944961713Sgirish 			(uint8_t)(uint64_t)(&mii_regs->bmcr),
4120adfcba55Sjoycey #endif
412144961713Sgirish 			bmcr.value)) != NXGE_OK)
412244961713Sgirish 		goto fail;
412344961713Sgirish 
412444961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4125adfcba55Sjoycey #if defined(__i386)
4126adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4127adfcba55Sjoycey #else
412844961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4129adfcba55Sjoycey #endif
413044961713Sgirish 		goto fail;
413144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
413244961713Sgirish 
413344961713Sgirish 	/*
413444961713Sgirish 	 * Initialize the xcvr status kept in the context structure.
413544961713Sgirish 	 */
413644961713Sgirish 	nxgep->soft_bmsr.value = 0;
413744961713Sgirish 
413844961713Sgirish 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4139adfcba55Sjoycey #if defined(__i386)
4140adfcba55Sjoycey 		(uint8_t)(uint32_t)(&mii_regs->bmsr),
4141adfcba55Sjoycey #else
414244961713Sgirish 		(uint8_t)(uint64_t)(&mii_regs->bmsr),
4143adfcba55Sjoycey #endif
414444961713Sgirish 			&nxgep->bmsr.value)) != NXGE_OK)
414544961713Sgirish 		goto fail;
414644961713Sgirish 
414744961713Sgirish 	statsp->mac_stats.xcvr_inits++;
414844961713Sgirish 	nxgep->bmsr.value = 0;
414944961713Sgirish 
415044961713Sgirish fail:
415144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
415244961713Sgirish 			"<== nxge_mii_xcvr_init status 0x%x", status));
415344961713Sgirish 	return (status);
415444961713Sgirish }
415544961713Sgirish 
4156d81011f0Ssbehera nxge_status_t
4157d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
4158d81011f0Ssbehera {
4159d81011f0Ssbehera 	p_nxge_param_t	param_arr;
4160d81011f0Ssbehera 	p_nxge_stats_t	statsp;
4161d81011f0Ssbehera 	uint8_t		xcvr_portn;
4162d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
4163d81011f0Ssbehera 	mii_bmcr_t	bmcr;
4164d81011f0Ssbehera 	mii_bmsr_t	bmsr;
4165d81011f0Ssbehera 	mii_gcr_t	gcr;
4166d81011f0Ssbehera 	mii_esr_t	esr;
4167d81011f0Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
4168d81011f0Ssbehera 	int		status = NXGE_OK;
4169d81011f0Ssbehera 
4170d81011f0Ssbehera 	uint_t delay;
4171d81011f0Ssbehera 
4172d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
4173d81011f0Ssbehera 
4174d81011f0Ssbehera 	param_arr = nxgep->param_arr;
4175d81011f0Ssbehera 	statsp = nxgep->statsp;
4176d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
4177d81011f0Ssbehera 
4178d81011f0Ssbehera 	mii_regs = NULL;
4179d81011f0Ssbehera 
4180d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4181d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
4182d81011f0Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
4183d81011f0Ssbehera 
4184d81011f0Ssbehera 	/*
4185d81011f0Ssbehera 	 * Reset the transceiver.
4186d81011f0Ssbehera 	 */
4187d81011f0Ssbehera 	delay = 0;
4188d81011f0Ssbehera 	bmcr.value = 0;
4189d81011f0Ssbehera 	bmcr.bits.reset = 1;
4190d81011f0Ssbehera 
4191d81011f0Ssbehera #if defined(__i386)
4192d81011f0Ssbehera 
4193d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4194d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4195d81011f0Ssbehera 		goto fail;
4196d81011f0Ssbehera #else
4197d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4198d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4199d81011f0Ssbehera 		goto fail;
4200d81011f0Ssbehera #endif
4201d81011f0Ssbehera 	do {
4202d81011f0Ssbehera 		drv_usecwait(500);
4203d81011f0Ssbehera #if defined(__i386)
4204d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4205d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
4206d81011f0Ssbehera 		    != NXGE_OK)
4207d81011f0Ssbehera 			goto fail;
4208d81011f0Ssbehera #else
4209d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4210d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
4211d81011f0Ssbehera 		    != NXGE_OK)
4212d81011f0Ssbehera 			goto fail;
4213d81011f0Ssbehera #endif
4214d81011f0Ssbehera 		delay++;
4215d81011f0Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
4216d81011f0Ssbehera 	if (delay == 1000) {
4217d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
4218d81011f0Ssbehera 		goto fail;
4219d81011f0Ssbehera 	}
4220d81011f0Ssbehera 
4221d81011f0Ssbehera #if defined(__i386)
4222d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4223d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4224d81011f0Ssbehera 		goto fail;
4225d81011f0Ssbehera #else
4226d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4227d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
4228d81011f0Ssbehera 		goto fail;
4229d81011f0Ssbehera #endif
4230d81011f0Ssbehera 
4231d81011f0Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
4232d81011f0Ssbehera 	param_arr[param_anar_100T4].value = 0;
4233d81011f0Ssbehera 	param_arr[param_anar_100fdx].value = 0;
4234d81011f0Ssbehera 	param_arr[param_anar_100hdx].value = 0;
4235d81011f0Ssbehera 	param_arr[param_anar_10fdx].value = 0;
4236d81011f0Ssbehera 	param_arr[param_anar_10hdx].value = 0;
4237d81011f0Ssbehera 
4238d81011f0Ssbehera 	/*
4239d81011f0Ssbehera 	 * Initialize the xcvr statistics.
4240d81011f0Ssbehera 	 */
4241d81011f0Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
4242d81011f0Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
4243d81011f0Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
4244d81011f0Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
4245d81011f0Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
4246d81011f0Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
4247d81011f0Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
4248d81011f0Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
4249d81011f0Ssbehera 
4250d81011f0Ssbehera 	/*
4251d81011f0Ssbehera 	 * Initialize the xcvr advertised capability statistics.
4252d81011f0Ssbehera 	 */
4253d81011f0Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
4254d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4255d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4256d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
4257d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
4258d81011f0Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
4259d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
4260d81011f0Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
4261d81011f0Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
4262d81011f0Ssbehera 	    param_arr[param_anar_asmpause].value;
4263d81011f0Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
4264d81011f0Ssbehera 
4265d81011f0Ssbehera 	/*
4266d81011f0Ssbehera 	 * Check for extended status just in case we're
4267d81011f0Ssbehera 	 * running a Gigibit phy.
4268d81011f0Ssbehera 	 */
4269d81011f0Ssbehera 	if (bmsr.bits.extend_status) {
4270d81011f0Ssbehera #if defined(__i386)
4271d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4272d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
4273d81011f0Ssbehera 		    NXGE_OK)
4274d81011f0Ssbehera 			goto fail;
4275d81011f0Ssbehera #else
4276d81011f0Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
4277d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
4278d81011f0Ssbehera 		    NXGE_OK)
4279d81011f0Ssbehera 			goto fail;
4280d81011f0Ssbehera #endif
4281d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value &=
4282d81011f0Ssbehera 		    esr.bits.link_1000fdx;
4283d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4284d81011f0Ssbehera 
4285d81011f0Ssbehera 		statsp->mac_stats.cap_1000fdx =
4286d81011f0Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
4287d81011f0Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
4288d81011f0Ssbehera 	} else {
4289d81011f0Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
4290d81011f0Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
4291d81011f0Ssbehera 	}
4292d81011f0Ssbehera 
4293d81011f0Ssbehera 	/*
4294d81011f0Ssbehera 	 * Initialize 1G Statistics once the capability is established.
4295d81011f0Ssbehera 	 */
4296d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
4297d81011f0Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
4298d81011f0Ssbehera 
4299d81011f0Ssbehera 	/*
4300d81011f0Ssbehera 	 * Initialize the link statistics.
4301d81011f0Ssbehera 	 */
4302d81011f0Ssbehera 	statsp->mac_stats.link_T4 = 0;
4303d81011f0Ssbehera 	statsp->mac_stats.link_asmpause = 0;
4304d81011f0Ssbehera 	statsp->mac_stats.link_pause = 0;
4305d81011f0Ssbehera 	statsp->mac_stats.link_speed = 0;
4306d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 0;
4307d81011f0Ssbehera 	statsp->mac_stats.link_up = 0;
4308d81011f0Ssbehera 
4309d81011f0Ssbehera 	/*
4310d81011f0Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
4311d81011f0Ssbehera 	 */
4312d81011f0Ssbehera 	bmcr.value = 0;
4313d81011f0Ssbehera #if defined(__i386)
4314d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4315d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4316d81011f0Ssbehera 		goto fail;
4317d81011f0Ssbehera #else
4318d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4319d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
4320d81011f0Ssbehera 		goto fail;
4321d81011f0Ssbehera #endif
4322d81011f0Ssbehera 
4323d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
4324d81011f0Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
4325d81011f0Ssbehera 		bmcr.bits.loopback = 1;
4326d81011f0Ssbehera 		bmcr.bits.enable_autoneg = 0;
4327d81011f0Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
4328d81011f0Ssbehera 			bmcr.bits.speed_1000_sel = 1;
4329d81011f0Ssbehera 		bmcr.bits.duplex_mode = 1;
4330d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4331d81011f0Ssbehera 	} else {
4332d81011f0Ssbehera 		bmcr.bits.loopback = 0;
4333d81011f0Ssbehera 	}
4334d81011f0Ssbehera 
4335d81011f0Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
4336d81011f0Ssbehera 		param_arr[param_autoneg].value = 0;
4337d81011f0Ssbehera 		bcm5464r_aux.value = 0;
4338d81011f0Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
4339d81011f0Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
4340d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4341d81011f0Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
4342d81011f0Ssbehera 			goto fail;
4343d81011f0Ssbehera 	}
4344d81011f0Ssbehera 
4345d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
4346d81011f0Ssbehera 	bmcr.bits.speed_1000_sel = 1;
4347d81011f0Ssbehera 	bmcr.bits.speed_sel = 0;
4348d81011f0Ssbehera 	bmcr.bits.duplex_mode = 1;
4349d81011f0Ssbehera 	statsp->mac_stats.link_speed = 1000;
4350d81011f0Ssbehera 	statsp->mac_stats.link_duplex = 2;
4351d81011f0Ssbehera 
4352d81011f0Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
4353d81011f0Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
4354d81011f0Ssbehera 		gcr.value = 0;
4355d81011f0Ssbehera 		gcr.bits.ms_mode_en = 1;
4356d81011f0Ssbehera 		gcr.bits.master = 1;
4357d81011f0Ssbehera #if defined(__i386)
4358d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4359d81011f0Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
4360d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4361d81011f0Ssbehera 			goto fail;
4362d81011f0Ssbehera #else
4363d81011f0Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
4364d81011f0Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
4365d81011f0Ssbehera 		    gcr.value)) != NXGE_OK)
4366d81011f0Ssbehera 			goto fail;
4367d81011f0Ssbehera #endif
4368d81011f0Ssbehera 		bmcr.value = 0;
4369d81011f0Ssbehera 		bmcr.bits.speed_1000_sel = 1;
4370d81011f0Ssbehera 		statsp->mac_stats.link_speed = 1000;
4371d81011f0Ssbehera 	}
4372d81011f0Ssbehera 
4373d81011f0Ssbehera #if defined(__i386)
4374d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4375d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
4376d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4377d81011f0Ssbehera 		goto fail;
4378d81011f0Ssbehera #else
4379d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
4380d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
4381d81011f0Ssbehera 	    bmcr.value)) != NXGE_OK)
4382d81011f0Ssbehera 		goto fail;
4383d81011f0Ssbehera #endif
4384d81011f0Ssbehera 
4385d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4386d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
4387d81011f0Ssbehera 	    bmcr.value));
4388d81011f0Ssbehera 
4389d81011f0Ssbehera #if defined(__i386)
4390d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4391d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4392d81011f0Ssbehera 		goto fail;
4393d81011f0Ssbehera #else
4394d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4395d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
4396d81011f0Ssbehera 		goto fail;
4397d81011f0Ssbehera #endif
4398d81011f0Ssbehera 
4399d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4400d81011f0Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
4401d81011f0Ssbehera 
4402d81011f0Ssbehera 	/*
4403d81011f0Ssbehera 	 * Initialize the xcvr status kept in the context structure.
4404d81011f0Ssbehera 	 */
4405d81011f0Ssbehera 	nxgep->soft_bmsr.value = 0;
4406d81011f0Ssbehera #if defined(__i386)
4407d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4408d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
4409d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4410d81011f0Ssbehera 		goto fail;
4411d81011f0Ssbehera #else
4412d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
4413d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
4414d81011f0Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
4415d81011f0Ssbehera 		goto fail;
4416d81011f0Ssbehera #endif
4417d81011f0Ssbehera 
4418d81011f0Ssbehera 	statsp->mac_stats.xcvr_inits++;
4419d81011f0Ssbehera 	nxgep->bmsr.value = 0;
4420d81011f0Ssbehera 
4421d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4422d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4423d81011f0Ssbehera 	return (status);
4424d81011f0Ssbehera 
4425d81011f0Ssbehera fail:
4426d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4427d81011f0Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
4428d81011f0Ssbehera 	return (status);
4429d81011f0Ssbehera }
4430d81011f0Ssbehera 
443144961713Sgirish /* Read from a MII compliant register */
443244961713Sgirish 
443344961713Sgirish nxge_status_t
443444961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
443544961713Sgirish 		uint16_t *value)
443644961713Sgirish {
443744961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
443844961713Sgirish 
443944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
444044961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
444144961713Sgirish 
4442321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
444344961713Sgirish 
4444d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4445d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
444644961713Sgirish 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
444744961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
444844961713Sgirish 			goto fail;
44492e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
44502e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
445144961713Sgirish 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
445244961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
445344961713Sgirish 			goto fail;
445444961713Sgirish 	} else
445544961713Sgirish 		goto fail;
445644961713Sgirish 
4457321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
445844961713Sgirish 
445944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
446044961713Sgirish 			"xcvr_reg<%d> value=0x%x",
446144961713Sgirish 			xcvr_portn, xcvr_reg, *value));
446244961713Sgirish 	return (NXGE_OK);
446344961713Sgirish fail:
4464321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
446544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
446644961713Sgirish 			"nxge_mii_read: Failed to read mii on xcvr %d",
446744961713Sgirish 			xcvr_portn));
446844961713Sgirish 
446944961713Sgirish 	return (NXGE_ERROR | rs);
447044961713Sgirish }
447144961713Sgirish 
447244961713Sgirish /* Write to a MII compliant Register */
447344961713Sgirish 
447444961713Sgirish nxge_status_t
447544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
447644961713Sgirish 		uint16_t value)
447744961713Sgirish {
447844961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
447944961713Sgirish 
448044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
448144961713Sgirish 			"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg,
448244961713Sgirish 			value));
448344961713Sgirish 
4484321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
448544961713Sgirish 
4486d81011f0Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
4487d81011f0Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
448844961713Sgirish 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
448944961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
449044961713Sgirish 			goto fail;
44912e59129aSraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
44922e59129aSraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
449344961713Sgirish 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
449444961713Sgirish 				xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
449544961713Sgirish 			goto fail;
449644961713Sgirish 	} else
449744961713Sgirish 		goto fail;
449844961713Sgirish 
4499321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
450044961713Sgirish 
450144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
450244961713Sgirish 			"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
450344961713Sgirish 	return (NXGE_OK);
450444961713Sgirish fail:
4505321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
450644961713Sgirish 
450744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
450844961713Sgirish 			"nxge_mii_write: Failed to write mii on xcvr %d",
450944961713Sgirish 			xcvr_portn));
451044961713Sgirish 
451144961713Sgirish 	return (NXGE_ERROR | rs);
451244961713Sgirish }
451344961713Sgirish 
451400161856Syc /*
451500161856Syc  * Perform write to Clause45 serdes / transceiver device
451600161856Syc  * Arguments:
451700161856Syc  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
451800161856Syc  *			number if nxge_mdio_write is used for accessing the
451900161856Syc  *			internal LSIL serdes. Otherwise PHYAD is different
452000161856Syc  * 			for different platforms.
452100161856Syc  *	device:		With each PHYAD, the driver can use MDIO to control
452200161856Syc  *			multiple devices inside the PHY, here "device" is an
452300161856Syc  *			MMD (MDIO managable device).
452400161856Syc  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
452500161856Syc  *			the register which the driver will write value to.
452600161856Syc  *	value:		The register value will be filled in.
452700161856Syc  */
452844961713Sgirish nxge_status_t
452944961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
453044961713Sgirish 		uint16_t xcvr_reg, uint16_t *value)
453144961713Sgirish {
453244961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
453344961713Sgirish 
453444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
453544961713Sgirish 			xcvr_portn));
453644961713Sgirish 
453753560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
453844961713Sgirish 
453944961713Sgirish 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
454044961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
454144961713Sgirish 		goto fail;
454244961713Sgirish 
454353560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
454444961713Sgirish 
454544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
454644961713Sgirish 			xcvr_portn));
454744961713Sgirish 	return (NXGE_OK);
454844961713Sgirish fail:
454953560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
455044961713Sgirish 
455144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
455244961713Sgirish 			"nxge_mdio_read: Failed to read mdio on xcvr %d",
455344961713Sgirish 			xcvr_portn));
455444961713Sgirish 
455544961713Sgirish 	return (NXGE_ERROR | rs);
455644961713Sgirish }
455744961713Sgirish 
455844961713Sgirish /* Perform write to Clause45 serdes / transceiver device */
455944961713Sgirish 
456044961713Sgirish nxge_status_t
456144961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
456244961713Sgirish 		uint16_t xcvr_reg, uint16_t value)
456344961713Sgirish {
456444961713Sgirish 	npi_status_t rs = NPI_SUCCESS;
456544961713Sgirish 
456644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
456744961713Sgirish 			xcvr_portn));
456844961713Sgirish 
456953560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
457044961713Sgirish 
457144961713Sgirish 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
457244961713Sgirish 			xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
457344961713Sgirish 		goto fail;
457444961713Sgirish 
457553560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
457644961713Sgirish 
457744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
457844961713Sgirish 			xcvr_portn));
457944961713Sgirish 	return (NXGE_OK);
458044961713Sgirish fail:
458153560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
458244961713Sgirish 
458344961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
458444961713Sgirish 			"nxge_mdio_write: Failed to write mdio on xcvr %d",
458544961713Sgirish 			xcvr_portn));
458644961713Sgirish 
458744961713Sgirish 	return (NXGE_ERROR | rs);
458844961713Sgirish }
458944961713Sgirish 
459044961713Sgirish 
459144961713Sgirish /* Check MII to see if there is any link status change */
459244961713Sgirish 
459344961713Sgirish nxge_status_t
4594a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
4595a3c5bd6dSspeer 		nxge_link_state_t *link_up)
459644961713Sgirish {
459744961713Sgirish 	p_nxge_param_t	param_arr;
459844961713Sgirish 	p_nxge_stats_t	statsp;
459944961713Sgirish 	p_mii_regs_t	mii_regs;
460044961713Sgirish 	p_mii_bmsr_t	soft_bmsr;
460144961713Sgirish 	mii_anar_t	anar;
460244961713Sgirish 	mii_anlpar_t	anlpar;
460344961713Sgirish 	mii_anar_t	an_common;
460444961713Sgirish 	mii_aner_t	aner;
460544961713Sgirish 	mii_gsr_t	gsr;
460644961713Sgirish 	nxge_status_t	status = NXGE_OK;
460744961713Sgirish 
460844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
460944961713Sgirish 
461044961713Sgirish 	mii_regs = NULL;
461144961713Sgirish 	param_arr = nxgep->param_arr;
461244961713Sgirish 	statsp = nxgep->statsp;
461344961713Sgirish 	soft_bmsr = &nxgep->soft_bmsr;
4614a3c5bd6dSspeer 	*link_up = LINK_NO_CHANGE;
461544961713Sgirish 
4616d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4617d81011f0Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
4618d81011f0Ssbehera 	    bmsr.value, bmsr_ints.value));
4619d81011f0Ssbehera 
462044961713Sgirish 	if (bmsr_ints.bits.link_status) {
4621d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4622d81011f0Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
4623d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
462444961713Sgirish 		if (bmsr.bits.link_status) {
462544961713Sgirish 			soft_bmsr->bits.link_status = 1;
4626d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4627d81011f0Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
4628d81011f0Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
462944961713Sgirish 		} else {
463044961713Sgirish 			statsp->mac_stats.link_up = 0;
463144961713Sgirish 			soft_bmsr->bits.link_status = 0;
463244961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
463344961713Sgirish 					"Link down cable problem"));
4634a3c5bd6dSspeer 			*link_up = LINK_IS_DOWN;
463544961713Sgirish 		}
463644961713Sgirish 	}
463744961713Sgirish 
4638d81011f0Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
4639d81011f0Ssbehera 	    param_arr[param_autoneg].value) {
464044961713Sgirish 		if (bmsr_ints.bits.auto_neg_complete) {
464144961713Sgirish 			if (bmsr.bits.auto_neg_complete)
464244961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 1;
464344961713Sgirish 			else
464444961713Sgirish 				soft_bmsr->bits.auto_neg_complete = 0;
464544961713Sgirish 		}
464644961713Sgirish 		if (soft_bmsr->bits.link_status == 0) {
464744961713Sgirish 			statsp->mac_stats.link_T4 = 0;
464844961713Sgirish 			statsp->mac_stats.link_speed = 0;
464944961713Sgirish 			statsp->mac_stats.link_duplex = 0;
465044961713Sgirish 			statsp->mac_stats.link_asmpause = 0;
465144961713Sgirish 			statsp->mac_stats.link_pause = 0;
465244961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = 0;
465344961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = 0;
465444961713Sgirish 			statsp->mac_stats.lp_cap_1000fdx = 0;
465544961713Sgirish 			statsp->mac_stats.lp_cap_1000hdx = 0;
465644961713Sgirish 			statsp->mac_stats.lp_cap_100fdx = 0;
465744961713Sgirish 			statsp->mac_stats.lp_cap_100hdx = 0;
465844961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = 0;
465944961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = 0;
466044961713Sgirish 			statsp->mac_stats.lp_cap_10gfdx = 0;
466144961713Sgirish 			statsp->mac_stats.lp_cap_10ghdx = 0;
466244961713Sgirish 			statsp->mac_stats.lp_cap_asmpause = 0;
466344961713Sgirish 			statsp->mac_stats.lp_cap_pause = 0;
466444961713Sgirish 		}
466544961713Sgirish 	} else
466644961713Sgirish 		soft_bmsr->bits.auto_neg_complete = 1;
466744961713Sgirish 
466844961713Sgirish 	if ((bmsr_ints.bits.link_status ||
466944961713Sgirish 		bmsr_ints.bits.auto_neg_complete) &&
467044961713Sgirish 		soft_bmsr->bits.link_status &&
467144961713Sgirish 		soft_bmsr->bits.auto_neg_complete) {
467244961713Sgirish 		statsp->mac_stats.link_up = 1;
4673d81011f0Ssbehera 
4674d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4675d81011f0Ssbehera 		    "==> nxge_mii_check "
4676d81011f0Ssbehera 		    "(auto negotiation complete or link up) "
4677d81011f0Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
4678d81011f0Ssbehera 		    bmsr.value, bmsr_ints.value));
4679d81011f0Ssbehera 
4680d81011f0Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
4681d81011f0Ssbehera 		    param_arr[param_autoneg].value) {
468244961713Sgirish 			if ((status = nxge_mii_read(nxgep,
468344961713Sgirish 				statsp->mac_stats.xcvr_portn,
4684adfcba55Sjoycey #if defined(__i386)
4685adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anar),
4686adfcba55Sjoycey #else
468744961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anar),
4688adfcba55Sjoycey #endif
468944961713Sgirish 					&anar.value)) != NXGE_OK)
469044961713Sgirish 				goto fail;
469144961713Sgirish 			if ((status = nxge_mii_read(nxgep,
469244961713Sgirish 				statsp->mac_stats.xcvr_portn,
4693adfcba55Sjoycey #if defined(__i386)
4694adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
4695adfcba55Sjoycey #else
469644961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
4697adfcba55Sjoycey #endif
469844961713Sgirish 					&anlpar.value)) != NXGE_OK)
469944961713Sgirish 				goto fail;
470044961713Sgirish 			if ((status = nxge_mii_read(nxgep,
470144961713Sgirish 				statsp->mac_stats.xcvr_portn,
4702adfcba55Sjoycey #if defined(__i386)
4703adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->aner),
4704adfcba55Sjoycey #else
470544961713Sgirish 				(uint8_t)(uint64_t)(&mii_regs->aner),
4706adfcba55Sjoycey #endif
470744961713Sgirish 					&aner.value)) != NXGE_OK)
470844961713Sgirish 				goto fail;
470944961713Sgirish 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
471044961713Sgirish 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
471144961713Sgirish 			statsp->mac_stats.lp_cap_100fdx =
471244961713Sgirish 							anlpar.bits.cap_100fdx;
471344961713Sgirish 			statsp->mac_stats.lp_cap_100hdx =
471444961713Sgirish 							anlpar.bits.cap_100hdx;
471544961713Sgirish 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
471644961713Sgirish 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
471744961713Sgirish 			statsp->mac_stats.lp_cap_asmpause =
471844961713Sgirish 						anlpar.bits.cap_asmpause;
471944961713Sgirish 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
472044961713Sgirish 			an_common.value = anar.value & anlpar.value;
472144961713Sgirish 			if (param_arr[param_anar_1000fdx].value ||
472244961713Sgirish 				param_arr[param_anar_1000hdx].value) {
472344961713Sgirish 				if ((status = nxge_mii_read(nxgep,
472444961713Sgirish 					statsp->mac_stats.xcvr_portn,
4725adfcba55Sjoycey #if defined(__i386)
4726adfcba55Sjoycey 					(uint8_t)(uint32_t)(&mii_regs->gsr),
4727adfcba55Sjoycey #else
472844961713Sgirish 					(uint8_t)(uint64_t)(&mii_regs->gsr),
4729adfcba55Sjoycey #endif
473044961713Sgirish 						&gsr.value))
473144961713Sgirish 						!= NXGE_OK)
473244961713Sgirish 					goto fail;
473344961713Sgirish 				statsp->mac_stats.lp_cap_1000fdx =
473444961713Sgirish 					gsr.bits.link_1000fdx;
473544961713Sgirish 				statsp->mac_stats.lp_cap_1000hdx =
473644961713Sgirish 					gsr.bits.link_1000hdx;
473744961713Sgirish 				if (param_arr[param_anar_1000fdx].value &&
473844961713Sgirish 					gsr.bits.link_1000fdx) {
473944961713Sgirish 					statsp->mac_stats.link_speed = 1000;
474044961713Sgirish 					statsp->mac_stats.link_duplex = 2;
474144961713Sgirish 				} else if (
474244961713Sgirish 					param_arr[param_anar_1000hdx].value &&
474344961713Sgirish 						gsr.bits.link_1000hdx) {
474444961713Sgirish 					statsp->mac_stats.link_speed = 1000;
474544961713Sgirish 					statsp->mac_stats.link_duplex = 1;
474644961713Sgirish 				}
474744961713Sgirish 			}
474844961713Sgirish 			if ((an_common.value != 0) &&
474944961713Sgirish 					!(statsp->mac_stats.link_speed)) {
475044961713Sgirish 				if (an_common.bits.cap_100T4) {
475144961713Sgirish 					statsp->mac_stats.link_T4 = 1;
475244961713Sgirish 					statsp->mac_stats.link_speed = 100;
475344961713Sgirish 					statsp->mac_stats.link_duplex = 1;
475444961713Sgirish 				} else if (an_common.bits.cap_100fdx) {
475544961713Sgirish 					statsp->mac_stats.link_speed = 100;
475644961713Sgirish 					statsp->mac_stats.link_duplex = 2;
475744961713Sgirish 				} else if (an_common.bits.cap_100hdx) {
475844961713Sgirish 					statsp->mac_stats.link_speed = 100;
475944961713Sgirish 					statsp->mac_stats.link_duplex = 1;
476044961713Sgirish 				} else if (an_common.bits.cap_10fdx) {
476144961713Sgirish 					statsp->mac_stats.link_speed = 10;
476244961713Sgirish 					statsp->mac_stats.link_duplex = 2;
476344961713Sgirish 				} else if (an_common.bits.cap_10hdx) {
476444961713Sgirish 					statsp->mac_stats.link_speed = 10;
476544961713Sgirish 					statsp->mac_stats.link_duplex = 1;
476644961713Sgirish 				} else {
476744961713Sgirish 					goto fail;
476844961713Sgirish 				}
476944961713Sgirish 			}
477044961713Sgirish 			if (statsp->mac_stats.link_duplex != 1) {
477144961713Sgirish 				statsp->mac_stats.link_asmpause =
477244961713Sgirish 					an_common.bits.cap_asmpause;
477344961713Sgirish 				if (statsp->mac_stats.link_asmpause)
477444961713Sgirish 				if ((statsp->mac_stats.cap_pause == 0) &&
477544961713Sgirish 						(statsp->mac_stats.lp_cap_pause
477644961713Sgirish 						== 1))
477744961713Sgirish 						statsp->mac_stats.link_pause
477844961713Sgirish 						= 0;
477944961713Sgirish 					else
478044961713Sgirish 						statsp->mac_stats.link_pause
478144961713Sgirish 						= 1;
478244961713Sgirish 				else
478344961713Sgirish 					statsp->mac_stats.link_pause =
478444961713Sgirish 						an_common.bits.cap_pause;
478544961713Sgirish 			}
4786d81011f0Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
4787d81011f0Ssbehera 			statsp->mac_stats.link_speed = 1000;
4788d81011f0Ssbehera 			statsp->mac_stats.link_duplex = 2;
478944961713Sgirish 		}
4790a3c5bd6dSspeer 		*link_up = LINK_IS_UP;
4791a3c5bd6dSspeer 	}
4792a3c5bd6dSspeer 
4793a3c5bd6dSspeer 	if (nxgep->link_notify) {
4794a3c5bd6dSspeer 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
4795a3c5bd6dSspeer 				LINK_IS_DOWN);
4796a3c5bd6dSspeer 		nxgep->link_notify = B_FALSE;
479744961713Sgirish 	}
479844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
479944961713Sgirish 	return (NXGE_OK);
480044961713Sgirish fail:
480144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
480244961713Sgirish 			"nxge_mii_check: Unable to check MII"));
480344961713Sgirish 	return (status);
480444961713Sgirish }
480544961713Sgirish 
480600161856Syc /*
480700161856Syc  * Check PCS to see if there is any link status change.
480800161856Syc  * This function is called by PORT_1G_SERDES only.
480900161856Syc  */
481000161856Syc void
48112e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
48122e59129aSraghus {
48132e59129aSraghus 	p_nxge_stats_t	statsp;
48142e59129aSraghus 	boolean_t	linkup;
48152e59129aSraghus 
48162e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
48172e59129aSraghus 
48182e59129aSraghus 	statsp = nxgep->statsp;
48192e59129aSraghus 	*link_up = LINK_NO_CHANGE;
48202e59129aSraghus 
48212e59129aSraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
48222e59129aSraghus 	if (linkup) {
48232e59129aSraghus 		if (nxgep->link_notify ||
48242e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
48252e59129aSraghus 			statsp->mac_stats.link_up = 1;
48262e59129aSraghus 			statsp->mac_stats.link_speed = 1000;
48272e59129aSraghus 			statsp->mac_stats.link_duplex = 2;
48282e59129aSraghus 			*link_up = LINK_IS_UP;
48292e59129aSraghus 			nxgep->link_notify = B_FALSE;
48302e59129aSraghus 		}
48312e59129aSraghus 	} else {
48322e59129aSraghus 		if (nxgep->link_notify ||
48332e59129aSraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
48342e59129aSraghus 			statsp->mac_stats.link_up = 0;
48352e59129aSraghus 			statsp->mac_stats.link_speed = 0;
48362e59129aSraghus 			statsp->mac_stats.link_duplex = 0;
48372e59129aSraghus 			*link_up = LINK_IS_DOWN;
48382e59129aSraghus 			nxgep->link_notify = B_FALSE;
48392e59129aSraghus 		}
48402e59129aSraghus 	}
48412e59129aSraghus 
48422e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
48432e59129aSraghus }
48442e59129aSraghus 
484544961713Sgirish /* Add a multicast address entry into the HW hash table */
484644961713Sgirish 
484744961713Sgirish nxge_status_t
484844961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
484944961713Sgirish {
485044961713Sgirish 	uint32_t mchash;
485144961713Sgirish 	p_hash_filter_t hash_filter;
485244961713Sgirish 	uint16_t hash_bit;
485344961713Sgirish 	boolean_t rx_init = B_FALSE;
485444961713Sgirish 	uint_t j;
485544961713Sgirish 	nxge_status_t status = NXGE_OK;
485644961713Sgirish 
485744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
485844961713Sgirish 
485944961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
486044961713Sgirish 	mchash = crc32_mchash(addrp);
486144961713Sgirish 	if (nxgep->hash_filter == NULL) {
486244961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
486344961713Sgirish 			"Allocating hash filter storage."));
486444961713Sgirish 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
486544961713Sgirish 					KM_SLEEP);
486644961713Sgirish 	}
486744961713Sgirish 	hash_filter = nxgep->hash_filter;
486844961713Sgirish 	j = mchash / HASH_REG_WIDTH;
486944961713Sgirish 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
487044961713Sgirish 	hash_filter->hash_filter_regs[j] |= hash_bit;
487144961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]++;
487244961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
487344961713Sgirish 		hash_filter->hash_ref_cnt++;
487444961713Sgirish 		rx_init = B_TRUE;
487544961713Sgirish 	}
487644961713Sgirish 	if (rx_init) {
487744961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
487844961713Sgirish 			goto fail;
487944961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
488044961713Sgirish 			goto fail;
488144961713Sgirish 	}
488244961713Sgirish 
488344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
488444961713Sgirish 
488544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
488644961713Sgirish 
488744961713Sgirish 	return (NXGE_OK);
488844961713Sgirish fail:
488944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
489044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
489144961713Sgirish 					"Unable to add multicast address"));
489244961713Sgirish 	return (status);
489344961713Sgirish }
489444961713Sgirish 
489544961713Sgirish /* Remove a multicast address entry from the HW hash table */
489644961713Sgirish 
489744961713Sgirish nxge_status_t
489844961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
489944961713Sgirish {
490044961713Sgirish 	uint32_t mchash;
490144961713Sgirish 	p_hash_filter_t hash_filter;
490244961713Sgirish 	uint16_t hash_bit;
490344961713Sgirish 	boolean_t rx_init = B_FALSE;
490444961713Sgirish 	uint_t j;
490544961713Sgirish 	nxge_status_t status = NXGE_OK;
490644961713Sgirish 
490744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
490844961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
490944961713Sgirish 	mchash = crc32_mchash(addrp);
491044961713Sgirish 	if (nxgep->hash_filter == NULL) {
491144961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
491244961713Sgirish 			"Hash filter already de_allocated."));
491344961713Sgirish 		RW_EXIT(&nxgep->filter_lock);
491444961713Sgirish 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
491544961713Sgirish 		return (NXGE_OK);
491644961713Sgirish 	}
491744961713Sgirish 	hash_filter = nxgep->hash_filter;
491844961713Sgirish 	hash_filter->hash_bit_ref_cnt[mchash]--;
491944961713Sgirish 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
492044961713Sgirish 		j = mchash / HASH_REG_WIDTH;
492144961713Sgirish 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
492244961713Sgirish 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
492344961713Sgirish 		hash_filter->hash_ref_cnt--;
492444961713Sgirish 		rx_init = B_TRUE;
492544961713Sgirish 	}
492644961713Sgirish 	if (hash_filter->hash_ref_cnt == 0) {
492744961713Sgirish 		NXGE_DEBUG_MSG((NULL, STR_CTL,
492844961713Sgirish 			"De-allocating hash filter storage."));
492944961713Sgirish 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
493044961713Sgirish 		nxgep->hash_filter = NULL;
493144961713Sgirish 	}
493244961713Sgirish 
493344961713Sgirish 	if (rx_init) {
493444961713Sgirish 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
493544961713Sgirish 			goto fail;
493644961713Sgirish 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
493744961713Sgirish 			goto fail;
493844961713Sgirish 	}
493944961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
494044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
494144961713Sgirish 
494244961713Sgirish 	return (NXGE_OK);
494344961713Sgirish fail:
494444961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
494544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
494644961713Sgirish 			"Unable to remove multicast address"));
494744961713Sgirish 
494844961713Sgirish 	return (status);
494944961713Sgirish }
495044961713Sgirish 
495144961713Sgirish /* Set MAC address into MAC address HW registers */
495244961713Sgirish 
495344961713Sgirish nxge_status_t
495444961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
495544961713Sgirish {
495644961713Sgirish 	nxge_status_t status = NXGE_OK;
495744961713Sgirish 
495844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
495944961713Sgirish 
496044961713Sgirish 	MUTEX_ENTER(&nxgep->ouraddr_lock);
496144961713Sgirish 	/*
496244961713Sgirish 	 * Exit if the address is same as ouraddr or multicast or broadcast
496344961713Sgirish 	 */
496444961713Sgirish 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
496544961713Sgirish 		(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
496644961713Sgirish 		(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
496744961713Sgirish 		goto nxge_set_mac_addr_exit;
496844961713Sgirish 	}
496944961713Sgirish 	nxgep->ouraddr = *addrp;
497044961713Sgirish 	/*
497144961713Sgirish 	 * Set new interface local address and re-init device.
497244961713Sgirish 	 * This is destructive to any other streams attached
497344961713Sgirish 	 * to this device.
497444961713Sgirish 	 */
497544961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
497644961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
497744961713Sgirish 		goto fail;
497844961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
497944961713Sgirish 		goto fail;
498044961713Sgirish 
498144961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
498244961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
498344961713Sgirish 	goto nxge_set_mac_addr_end;
498444961713Sgirish nxge_set_mac_addr_exit:
498544961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
498644961713Sgirish nxge_set_mac_addr_end:
498744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
498844961713Sgirish 
498944961713Sgirish 	return (NXGE_OK);
499044961713Sgirish fail:
499144961713Sgirish 	MUTEX_EXIT(&nxgep->ouraddr_lock);
499244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
499344961713Sgirish 			"Unable to set mac address"));
499444961713Sgirish 	return (status);
499544961713Sgirish }
499644961713Sgirish 
499798ecde52Stm static
499898ecde52Stm check_link_state_t
499900161856Syc nxge_check_link_stop(nxge_t *nxge)
500098ecde52Stm {
500198ecde52Stm 	/* If the poll has been cancelled, return STOP. */
500298ecde52Stm 	MUTEX_ENTER(&nxge->poll_lock);
500398ecde52Stm 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
500498ecde52Stm 		nxge->poll_state = LINK_MONITOR_STOP;
500598ecde52Stm 		nxge->nxge_link_poll_timerid = 0;
500698ecde52Stm 		cv_broadcast(&nxge->poll_cv);
500798ecde52Stm 		MUTEX_EXIT(&nxge->poll_lock);
500898ecde52Stm 
500998ecde52Stm 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
501098ecde52Stm 		    "nxge_check_%s_link(port<%d>) stopped.",
501198ecde52Stm 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
501298ecde52Stm 		    nxge->mac.portnum));
501398ecde52Stm 		return (CHECK_LINK_STOP);
501498ecde52Stm 	}
501598ecde52Stm 	MUTEX_EXIT(&nxge->poll_lock);
501698ecde52Stm 
501798ecde52Stm 	return (CHECK_LINK_RESCHEDULE);
501898ecde52Stm }
501998ecde52Stm 
502000161856Syc /*
502100161856Syc  * Check status of MII (MIF or PCS) link.
502200161856Syc  * This function is called once per second, that is because this function
502300161856Syc  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
502400161856Syc  * call this function recursively.
502500161856Syc  */
502659ac0c16Sdavemq static nxge_status_t
502744961713Sgirish nxge_check_mii_link(p_nxge_t nxgep)
502844961713Sgirish {
502944961713Sgirish 	mii_bmsr_t bmsr_ints, bmsr_data;
503044961713Sgirish 	mii_anlpar_t anlpar;
503144961713Sgirish 	mii_gsr_t gsr;
503244961713Sgirish 	p_mii_regs_t mii_regs;
503344961713Sgirish 	nxge_status_t status = NXGE_OK;
503444961713Sgirish 	uint8_t portn;
5035a3c5bd6dSspeer 	nxge_link_state_t link_up;
503644961713Sgirish 
503798ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
503898ecde52Stm 		return (NXGE_ERROR);
503998ecde52Stm 
504098ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
504198ecde52Stm 		return (NXGE_OK);
504298ecde52Stm 
504344961713Sgirish 	portn = nxgep->mac.portnum;
504444961713Sgirish 
504544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
504698ecde52Stm 	    portn));
504744961713Sgirish 
504844961713Sgirish 	mii_regs = NULL;
504944961713Sgirish 
505044961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
505144961713Sgirish 
505244961713Sgirish 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
505344961713Sgirish 		goto nxge_check_mii_link_exit;
505444961713Sgirish 
50552e59129aSraghus 	switch (nxgep->mac.portmode) {
50562e59129aSraghus 	default:
5057d81011f0Ssbehera 		bmsr_data.value = 0;
505844961713Sgirish 		if ((status = nxge_mii_read(nxgep,
50592e59129aSraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
5060adfcba55Sjoycey #if defined(__i386)
5061adfcba55Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
5062adfcba55Sjoycey #else
50632e59129aSraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
5064adfcba55Sjoycey #endif
50652e59129aSraghus 		    &bmsr_data.value)) != NXGE_OK) {
506644961713Sgirish 			goto fail;
506744961713Sgirish 		}
506844961713Sgirish 
5069d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5070d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
5071d81011f0Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
50722d17280bSsbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
5073d81011f0Ssbehera 
50742e59129aSraghus 		if (nxgep->param_arr[param_autoneg].value) {
50752e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
50762e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
5077adfcba55Sjoycey #if defined(__i386)
5078adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->gsr),
5079adfcba55Sjoycey #else
50802e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->gsr),
5081adfcba55Sjoycey #endif
50822e59129aSraghus 				&gsr.value)) != NXGE_OK)
50832e59129aSraghus 				goto fail;
50842e59129aSraghus 			if ((status = nxge_mii_read(nxgep,
50852e59129aSraghus 				nxgep->statsp->mac_stats.xcvr_portn,
5086adfcba55Sjoycey #if defined(__i386)
5087adfcba55Sjoycey 				(uint8_t)(uint32_t)(&mii_regs->anlpar),
5088adfcba55Sjoycey #else
50892e59129aSraghus 				(uint8_t)(uint64_t)(&mii_regs->anlpar),
5090adfcba55Sjoycey #endif
50912e59129aSraghus 				&anlpar.value)) != NXGE_OK)
50922e59129aSraghus 				goto fail;
5093d81011f0Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
5094d81011f0Ssbehera 
5095d81011f0Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
5096d81011f0Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
5097d81011f0Ssbehera 				    gsr.bits.link_1000fdx) ||
5098d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
5099d81011f0Ssbehera 				    gsr.bits.link_1000hdx) ||
5100d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
5101d81011f0Ssbehera 				    anlpar.bits.cap_100T4) ||
5102d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
5103d81011f0Ssbehera 				    anlpar.bits.cap_100fdx) ||
5104d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
5105d81011f0Ssbehera 				    anlpar.bits.cap_100hdx) ||
5106d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
5107d81011f0Ssbehera 				    anlpar.bits.cap_10fdx) ||
5108d81011f0Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
5109d81011f0Ssbehera 				    anlpar.bits.cap_10hdx))) {
5110d81011f0Ssbehera 					bmsr_data.bits.link_status = 0;
5111d81011f0Ssbehera 				}
51122e59129aSraghus 			}
51132e59129aSraghus 		}
511444961713Sgirish 
51152e59129aSraghus 		/* Workaround for link down issue */
51162e59129aSraghus 		if (bmsr_data.value == 0) {
51172e59129aSraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
51182e59129aSraghus 			goto nxge_check_mii_link_exit;
51192e59129aSraghus 		}
51202e59129aSraghus 
5121d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5122d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
5123d81011f0Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
51242d17280bSsbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
5125d81011f0Ssbehera 
51262e59129aSraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
51272e59129aSraghus 		nxgep->bmsr.value = bmsr_data.value;
5128d81011f0Ssbehera 
5129d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5130d81011f0Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
5131d81011f0Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
51322d17280bSsbehera 		    portn, bmsr_data.value, bmsr_ints.value));
5133d81011f0Ssbehera 
51342e59129aSraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
51352e59129aSraghus 		    &link_up)) != NXGE_OK) {
51362e59129aSraghus 			goto fail;
51372e59129aSraghus 		}
51382e59129aSraghus 		break;
51392e59129aSraghus 
51402e59129aSraghus 	case PORT_1G_SERDES:
514100161856Syc 		/*
514200161856Syc 		 * Above default is for all cases except PORT_1G_SERDES.
514300161856Syc 		 * The default case gets information from the PHY, but a
514400161856Syc 		 * nxge whose portmode equals PORT_1G_SERDES does not
514500161856Syc 		 * have a PHY.
514600161856Syc 		 */
51472e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51482e59129aSraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
514900161856Syc 		nxge_pcs_check(nxgep, portn, &link_up);
51502e59129aSraghus 		break;
51512e59129aSraghus 	}
515244961713Sgirish 
515344961713Sgirish nxge_check_mii_link_exit:
515444961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
5155a3c5bd6dSspeer 	if (link_up == LINK_IS_UP) {
5156a3c5bd6dSspeer 		nxge_link_is_up(nxgep);
5157a3c5bd6dSspeer 	} else if (link_up == LINK_IS_DOWN) {
5158a3c5bd6dSspeer 		nxge_link_is_down(nxgep);
5159a3c5bd6dSspeer 	}
516044961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
516144961713Sgirish 
516244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
51632e59129aSraghus 				portn));
516444961713Sgirish 	return (NXGE_OK);
516544961713Sgirish 
516644961713Sgirish fail:
516744961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
516844961713Sgirish 
516944961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
517044961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51712e59129aSraghus 			"nxge_check_mii_link: Failed to check link port<%d>",
51722e59129aSraghus 			portn));
517344961713Sgirish 	return (status);
517444961713Sgirish }
517544961713Sgirish 
517644961713Sgirish /*ARGSUSED*/
517759ac0c16Sdavemq static nxge_status_t
517844961713Sgirish nxge_check_10g_link(p_nxge_t nxgep)
517944961713Sgirish {
518044961713Sgirish 	uint8_t		portn;
518144961713Sgirish 	nxge_status_t	status = NXGE_OK;
5182763fcc44Ssbehera 	boolean_t	link_up;
51832e59129aSraghus 	uint32_t	val;
51842e59129aSraghus 	npi_status_t	rs;
518544961713Sgirish 
518698ecde52Stm 	if (nxgep->nxge_magic != NXGE_MAGIC)
518798ecde52Stm 		return (NXGE_ERROR);
518898ecde52Stm 
518998ecde52Stm 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
519098ecde52Stm 		return (NXGE_OK);
519198ecde52Stm 
519244961713Sgirish 	portn = nxgep->mac.portnum;
5193d81011f0Ssbehera 	val = 0;
5194d81011f0Ssbehera 	rs = NPI_SUCCESS;
519544961713Sgirish 
519644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
519798ecde52Stm 	    portn));
519844961713Sgirish 
51992e59129aSraghus 	switch (nxgep->mac.portmode) {
52002e59129aSraghus 	default:
52012d17280bSsbehera 		/*
52022d17280bSsbehera 		 * Check if the phy is present in case of hot swappable phy
52032d17280bSsbehera 		 */
52042d17280bSsbehera 		if (nxgep->hot_swappable_phy) {
52052d17280bSsbehera 			boolean_t phy_present_now = B_FALSE;
52062d17280bSsbehera 
52072d17280bSsbehera 			/*
52082d17280bSsbehera 			 * If this is the 2nd Goa port, then check 2 addresses
52092d17280bSsbehera 			 * to take care of the Goa NEM card requirements.
52102d17280bSsbehera 			 */
52112d17280bSsbehera 			if (portn == 1) {
52122d17280bSsbehera 				if (nxge_is_phy_present(nxgep,
521300161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
52142d17280bSsbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
52152d17280bSsbehera 					phy_present_now = B_TRUE;
52162d17280bSsbehera 					nxgep->xcvr_addr =
521700161856Syc 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
52182d17280bSsbehera 					goto phy_check_done;
52192d17280bSsbehera 				}
52202d17280bSsbehera 			}
52212d17280bSsbehera 			if (nxge_is_phy_present(nxgep,
522200161856Syc 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
52232d17280bSsbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
52242d17280bSsbehera 				nxgep->xcvr_addr =
522500161856Syc 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
52262d17280bSsbehera 				phy_present_now = B_TRUE;
52272d17280bSsbehera 			}
52282d17280bSsbehera 
52292d17280bSsbehera phy_check_done:
52302d17280bSsbehera 			if (nxgep->phy_absent) {
52312d17280bSsbehera 				if (phy_present_now) {
52322d17280bSsbehera 				/*
52332d17280bSsbehera 				 * Detect, Initialize phy and do link up
52342d17280bSsbehera 				 * set xcvr vals, link_init, nxge_init
52352d17280bSsbehera 				 */
52362d17280bSsbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
52372d17280bSsbehera 					    "Hot swappable phy DETECTED!!"));
52382d17280bSsbehera 					nxgep->phy_absent = B_FALSE;
52392d17280bSsbehera 					(void) nxge_xcvr_find(nxgep);
52402d17280bSsbehera 					(void) nxge_link_init(nxgep);
52412d17280bSsbehera 					if (!(nxgep->drv_state &
52422d17280bSsbehera 					    STATE_HW_INITIALIZED)) {
52432d17280bSsbehera 						status = nxge_init(nxgep);
52442d17280bSsbehera 						if (status != NXGE_OK) {
52452d17280bSsbehera 							NXGE_ERROR_MSG((nxgep,
52462d17280bSsbehera 							    NXGE_ERR_CTL,
52472d17280bSsbehera 							    "Hot swappable "
52482d17280bSsbehera 							    "phy present, but"
52492d17280bSsbehera 							    " driver init"
52502d17280bSsbehera 							    "  failed..."));
52512d17280bSsbehera 							goto fail;
52522d17280bSsbehera 						}
52532d17280bSsbehera 					}
52542d17280bSsbehera 				}
52552d17280bSsbehera 
52562d17280bSsbehera 				goto start_link_check;
52572d17280bSsbehera 
52582d17280bSsbehera 			} else if (!phy_present_now) {
52592d17280bSsbehera 				/*
52602d17280bSsbehera 				 * Phy gone, bring link down reset xcvr vals
52612d17280bSsbehera 				 */
52622d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
52632d17280bSsbehera 				    "Hot swappable phy REMOVED!!"));
52642d17280bSsbehera 				nxgep->phy_absent = B_TRUE;
52652d17280bSsbehera 				nxgep->statsp->mac_stats.link_up = 0;
52662d17280bSsbehera 				nxgep->statsp->mac_stats.link_speed = 0;
52672d17280bSsbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
52682d17280bSsbehera 				nxge_link_is_down(nxgep);
52692d17280bSsbehera 				nxgep->link_notify = B_FALSE;
52702d17280bSsbehera 
52712d17280bSsbehera 				(void) nxge_xcvr_find(nxgep);
52722d17280bSsbehera 
52732d17280bSsbehera 				goto start_link_check;
52742d17280bSsbehera 
52752d17280bSsbehera 			}
52762d17280bSsbehera 		}
527752cdd236Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
527800161856Syc 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
527952cdd236Ssbehera 		} else {
528052cdd236Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
528152cdd236Ssbehera 		}
52822e59129aSraghus 		if (status != NXGE_OK)
52832e59129aSraghus 			goto fail;
52842e59129aSraghus 		break;
52852e59129aSraghus 	case PORT_10G_SERDES:
52862e59129aSraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
5287763fcc44Ssbehera 		    XPCS_REG_STATUS, &val);
52882e59129aSraghus 		if (rs != 0)
52892e59129aSraghus 			goto fail;
52902e59129aSraghus 
52912e59129aSraghus 		link_up = B_FALSE;
5292763fcc44Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
5293763fcc44Ssbehera 			link_up = B_TRUE;
52942e59129aSraghus 		}
52952e59129aSraghus 
52962e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
52972e59129aSraghus 		    "==> nxge_check_10g_link port<%d> "
5298763fcc44Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
5299763fcc44Ssbehera 		    portn, val, link_up));
53002e59129aSraghus 
53012e59129aSraghus 		break;
53022e59129aSraghus 	}
530344961713Sgirish 
530444961713Sgirish 	if (link_up) {
5305a3c5bd6dSspeer 		if (nxgep->link_notify ||
5306a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 0) {
530744961713Sgirish 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
530844961713Sgirish 				goto fail;
530944961713Sgirish 			nxgep->statsp->mac_stats.link_up = 1;
531044961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 10000;
531144961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 2;
531244961713Sgirish 
531344961713Sgirish 			nxge_link_is_up(nxgep);
5314a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
531544961713Sgirish 		}
531644961713Sgirish 	} else {
5317a3c5bd6dSspeer 		if (nxgep->link_notify ||
5318a3c5bd6dSspeer 			nxgep->statsp->mac_stats.link_up == 1) {
531944961713Sgirish 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
532044961713Sgirish 				goto fail;
532144961713Sgirish 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53222e59129aSraghus 					"Link down cable problem"));
532344961713Sgirish 			nxgep->statsp->mac_stats.link_up = 0;
532444961713Sgirish 			nxgep->statsp->mac_stats.link_speed = 0;
532544961713Sgirish 			nxgep->statsp->mac_stats.link_duplex = 0;
532644961713Sgirish 
532744961713Sgirish 			nxge_link_is_down(nxgep);
5328a3c5bd6dSspeer 			nxgep->link_notify = B_FALSE;
532944961713Sgirish 		}
533044961713Sgirish 	}
533144961713Sgirish 
53322d17280bSsbehera start_link_check:
533344961713Sgirish 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
533444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
533598ecde52Stm 	    portn));
533644961713Sgirish 	return (NXGE_OK);
533744961713Sgirish 
533844961713Sgirish fail:
533998ecde52Stm 	(void) nxge_check_link_stop(nxgep);
534098ecde52Stm 
534144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
534298ecde52Stm 	    "nxge_check_10g_link: Failed to check link port<%d>",
534398ecde52Stm 	    portn));
534444961713Sgirish 	return (status);
534544961713Sgirish }
534644961713Sgirish 
534744961713Sgirish 
534844961713Sgirish /* Declare link down */
534944961713Sgirish 
535044961713Sgirish void
535144961713Sgirish nxge_link_is_down(p_nxge_t nxgep)
535244961713Sgirish {
535359ac0c16Sdavemq 	p_nxge_stats_t statsp;
535459ac0c16Sdavemq 	char link_stat_msg[64];
535559ac0c16Sdavemq 
535644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
535744961713Sgirish 
535859ac0c16Sdavemq 	statsp = nxgep->statsp;
535959ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
536059ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn);
536159ac0c16Sdavemq 
536259ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
536359ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
536459ac0c16Sdavemq 	}
536559ac0c16Sdavemq 
536644961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
536744961713Sgirish 
536844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
536944961713Sgirish }
537044961713Sgirish 
537144961713Sgirish /* Declare link up */
537244961713Sgirish 
537344961713Sgirish void
537444961713Sgirish nxge_link_is_up(p_nxge_t nxgep)
537544961713Sgirish {
537659ac0c16Sdavemq 	p_nxge_stats_t statsp;
537759ac0c16Sdavemq 	char link_stat_msg[64];
537844961713Sgirish 	uint32_t val;
537944961713Sgirish 
538044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
538144961713Sgirish 
538259ac0c16Sdavemq 	statsp = nxgep->statsp;
538359ac0c16Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
538459ac0c16Sdavemq 	    statsp->mac_stats.xcvr_portn,
538559ac0c16Sdavemq 	    statsp->mac_stats.link_speed);
538659ac0c16Sdavemq 
538759ac0c16Sdavemq 	if (statsp->mac_stats.link_T4)
538859ac0c16Sdavemq 		(void) strcat(link_stat_msg, "T4");
538959ac0c16Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
539059ac0c16Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
539159ac0c16Sdavemq 	else
539259ac0c16Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
539359ac0c16Sdavemq 
539444961713Sgirish 
539544961713Sgirish 	/* Clean up symbol errors incurred during link transition */
53962e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
53972e59129aSraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
539844961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
539944961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
540044961713Sgirish 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
540144961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
540244961713Sgirish 	}
540344961713Sgirish 
540400161856Syc 	/*
540500161856Syc 	 * If the driver was plumbed without a link (therefore auto-negotiation
540600161856Syc 	 * could not complete), the driver will detect a link up when a cable
540700161856Syc 	 * conneting to a link partner is plugged into the port. By the time
540800161856Syc 	 * link-up is detected, auto-negotiation should have completed (The
540900161856Syc 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
541000161856Syc 	 * configure the Neptune/NIU according to the newly negotiated speed.
541100161856Syc 	 * This is necessary only for the TN1010 basad device because only the
541200161856Syc 	 * TN1010 supports dual speeds.
541300161856Syc 	 */
541400161856Syc 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
541500161856Syc 	    nxgep->mac.portmode == PORT_10G_TN1010) {
541600161856Syc 
541700161856Syc 		(void) nxge_set_tn1010_param(nxgep);
541800161856Syc 
541900161856Syc 		/*
542000161856Syc 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
542100161856Syc 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
542200161856Syc 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
542300161856Syc 		 */
542400161856Syc 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
542500161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
542600161856Syc 			    "nxge_link_is_up: nxge_xcvr_find failed"));
542700161856Syc 		}
542800161856Syc 
542900161856Syc 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
543000161856Syc 		if (nxge_link_init(nxgep) != NXGE_OK) {
543100161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
543200161856Syc 			    "nxge_link_is_up: nxge_link_init failed"));
543300161856Syc 		}
543400161856Syc 
543500161856Syc 		/*
543600161856Syc 		 * nxge_mac_init calls many subroutines including
543700161856Syc 		 * nxge_xif_init which sets XGMII or GMII mode
543800161856Syc 		 */
543900161856Syc 		if (nxge_mac_init(nxgep) != NXGE_OK) {
544000161856Syc 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
544100161856Syc 			    "nxge_link_is_up: nxge_mac_init failed"));
544200161856Syc 		}
544300161856Syc 	} else {
544400161856Syc 		(void) nxge_xif_init(nxgep);
544500161856Syc 	}
544600161856Syc 
544759ac0c16Sdavemq 	if (nxge_no_msg == B_FALSE) {
544859ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
544959ac0c16Sdavemq 	}
545059ac0c16Sdavemq 
545144961713Sgirish 	mac_link_update(nxgep->mach, LINK_STATE_UP);
545244961713Sgirish 
545344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
545444961713Sgirish }
545544961713Sgirish 
545600161856Syc #ifdef NXGE_DEBUG
545700161856Syc /* Dump all TN1010 Status registers */
545800161856Syc static void
545900161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
546000161856Syc {
546100161856Syc 	uint16_t val;
546200161856Syc 
546300161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
546400161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
546500161856Syc 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
546600161856Syc 
546700161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
546800161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
546900161856Syc 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
547000161856Syc 
547100161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
547200161856Syc 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
547300161856Syc 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
547400161856Syc 
547500161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
547600161856Syc 	    TN1010_PCS_DEV_ADDR, 1, &val);
547700161856Syc 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
547800161856Syc 
547900161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
548000161856Syc 	    TN1010_PCS_DEV_ADDR, 8, &val);
548100161856Syc 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
548200161856Syc 
548300161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
548400161856Syc 	    TN1010_PCS_DEV_ADDR, 32, &val);
548500161856Syc 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
548600161856Syc 
548700161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
548800161856Syc 	    TN1010_PCS_DEV_ADDR, 33, &val);
548900161856Syc 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
549000161856Syc 
549100161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
549200161856Syc 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
549300161856Syc 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
549400161856Syc 
549500161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
549600161856Syc 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
549700161856Syc 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
549800161856Syc 
549900161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
550000161856Syc 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
550100161856Syc 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
550200161856Syc 
550300161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
550400161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
550500161856Syc 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
550600161856Syc 
550700161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
550800161856Syc 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
550900161856Syc 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
551000161856Syc 
551100161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
551200161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
551300161856Syc 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
551400161856Syc 
551500161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
551600161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
551700161856Syc 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
551800161856Syc 
551900161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
552000161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
552100161856Syc 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
552200161856Syc 
552300161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
552400161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
552500161856Syc 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
552600161856Syc 
552700161856Syc 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
552800161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
552900161856Syc 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
553000161856Syc 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
553100161856Syc }
553200161856Syc #endif
553300161856Syc 
553444961713Sgirish /*
553544961713Sgirish  * Calculate the bit in the multicast address filter
553644961713Sgirish  * that selects the given * address.
553744961713Sgirish  * Note: For GEM, the last 8-bits are used.
553844961713Sgirish  */
553944961713Sgirish uint32_t
554044961713Sgirish crc32_mchash(p_ether_addr_t addr)
554144961713Sgirish {
554244961713Sgirish 	uint8_t *cp;
554344961713Sgirish 	uint32_t crc;
554444961713Sgirish 	uint32_t c;
554544961713Sgirish 	int byte;
554644961713Sgirish 	int bit;
554744961713Sgirish 
554844961713Sgirish 	cp = (uint8_t *)addr;
554944961713Sgirish 	crc = (uint32_t)0xffffffff;
555044961713Sgirish 	for (byte = 0; byte < 6; byte++) {
555144961713Sgirish 		c = (uint32_t)cp[byte];
555244961713Sgirish 		for (bit = 0; bit < 8; bit++) {
555344961713Sgirish 			if ((c & 0x1) ^ (crc & 0x1))
555444961713Sgirish 				crc = (crc >> 1)^0xedb88320;
555544961713Sgirish 			else
555644961713Sgirish 				crc = (crc >> 1);
555744961713Sgirish 			c >>= 1;
555844961713Sgirish 		}
555944961713Sgirish 	}
556044961713Sgirish 	return ((~crc) >> (32 - HASH_BITS));
556144961713Sgirish }
556244961713Sgirish 
556344961713Sgirish /* Reset serdes */
556444961713Sgirish 
556544961713Sgirish nxge_status_t
556644961713Sgirish nxge_serdes_reset(p_nxge_t nxgep)
556744961713Sgirish {
556844961713Sgirish 	npi_handle_t		handle;
556944961713Sgirish 
557044961713Sgirish 	handle = nxgep->npi_handle;
557144961713Sgirish 
557244961713Sgirish 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
557344961713Sgirish 	drv_usecwait(500);
557444961713Sgirish 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
557544961713Sgirish 
557644961713Sgirish 	return (NXGE_OK);
557744961713Sgirish }
557844961713Sgirish 
557900161856Syc /*
558000161856Syc  * This function monitors link status using interrupt or polling.
558100161856Syc  * It calls nxgep->xcvr.check_link, a member function of
558200161856Syc  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
558300161856Syc  * function back, that is why the check_link routine is
558400161856Syc  * executed periodically.
558500161856Syc  */
558644961713Sgirish nxge_status_t
558744961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
558844961713Sgirish {
558944961713Sgirish 	nxge_status_t status = NXGE_OK;
559044961713Sgirish 
5591678453a8Sspeer 	/* If we are a guest domain driver, don't bother. */
5592678453a8Sspeer 	if (isLDOMguest(nxgep))
5593678453a8Sspeer 		return (status);
5594678453a8Sspeer 
559544961713Sgirish 	/*
559698ecde52Stm 	 * Return immediately if this is an imaginary XMAC port.
559798ecde52Stm 	 * (At least, we don't have 4-port XMAC cards yet.)
559844961713Sgirish 	 */
55992e59129aSraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
56002e59129aSraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
56012e59129aSraghus 	    (nxgep->mac.portnum > 1))
560244961713Sgirish 		return (NXGE_OK);
560344961713Sgirish 
560444961713Sgirish 	if (nxgep->statsp == NULL) {
560544961713Sgirish 		/* stats has not been allocated. */
560644961713Sgirish 		return (NXGE_OK);
560744961713Sgirish 	}
5608321febdeSsbehera 	/* Don't check link if we're in internal loopback mode */
5609321febdeSsbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
561044961713Sgirish 		return (NXGE_OK);
561144961713Sgirish 
561244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
561398ecde52Stm 	    "==> nxge_link_monitor port<%d> enable=%d",
561498ecde52Stm 	    nxgep->mac.portnum, enable));
561544961713Sgirish 	if (enable == LINK_MONITOR_START) {
561644961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
561744961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
561898ecde52Stm 			    != NXGE_OK)
561944961713Sgirish 				goto fail;
562044961713Sgirish 		} else {
562198ecde52Stm 			timeout_id_t timerid;
562200161856Syc 			/*
562300161856Syc 			 * check_link_stop means "Stop the link check", so
562400161856Syc 			 * we return without starting the timer.
562500161856Syc 			 */
562698ecde52Stm 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
562798ecde52Stm 				return (NXGE_OK);
562898ecde52Stm 
562900161856Syc 			/*
563000161856Syc 			 * Otherwise fire the timer for the nxge to check
563100161856Syc 			 * the link using the check_link function
563200161856Syc 			 * of the nxge_xcvr_table and pass "nxgep" as the
563300161856Syc 			 * argument to the check_link function.
563400161856Syc 			 */
563559ac0c16Sdavemq 			if (nxgep->xcvr.check_link) {
563659ac0c16Sdavemq 				timerid = timeout(
563759ac0c16Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
563898ecde52Stm 				    nxgep,
563998ecde52Stm 				    drv_usectohz(LINK_MONITOR_PERIOD));
564059ac0c16Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
564159ac0c16Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
564259ac0c16Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
564359ac0c16Sdavemq 			} else {
564498ecde52Stm 				return (NXGE_ERROR);
564544961713Sgirish 			}
564644961713Sgirish 		}
564744961713Sgirish 	} else {
564844961713Sgirish 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
564944961713Sgirish 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
565098ecde52Stm 			    != NXGE_OK)
565144961713Sgirish 				goto fail;
565244961713Sgirish 		} else {
565398ecde52Stm 			clock_t rv;
565498ecde52Stm 
565598ecde52Stm 			MUTEX_ENTER(&nxgep->poll_lock);
565698ecde52Stm 
565798ecde52Stm 			/* If <timerid> == 0, the link monitor has */
565898ecde52Stm 			/* never been started, or just now stopped. */
565998ecde52Stm 			if (nxgep->nxge_link_poll_timerid == 0) {
566098ecde52Stm 				MUTEX_EXIT(&nxgep->poll_lock);
566198ecde52Stm 				return (NXGE_OK);
566298ecde52Stm 			}
566398ecde52Stm 
566498ecde52Stm 			nxgep->poll_state = LINK_MONITOR_STOPPING;
566598ecde52Stm 			rv = cv_timedwait(&nxgep->poll_cv,
566698ecde52Stm 			    &nxgep->poll_lock,
566798ecde52Stm 			    ddi_get_lbolt() +
566898ecde52Stm 			    drv_usectohz(LM_WAIT_MULTIPLIER *
566998ecde52Stm 			    LINK_MONITOR_PERIOD));
567098ecde52Stm 			if (rv == -1) {
567198ecde52Stm 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
567298ecde52Stm 				    "==> stopping port %d: "
567398ecde52Stm 				    "cv_timedwait(%d) timed out",
567498ecde52Stm 				    nxgep->mac.portnum, nxgep->poll_state));
567598ecde52Stm 				nxgep->poll_state = LINK_MONITOR_STOP;
567644961713Sgirish 				nxgep->nxge_link_poll_timerid = 0;
567744961713Sgirish 			}
567898ecde52Stm 
567998ecde52Stm 			MUTEX_EXIT(&nxgep->poll_lock);
568044961713Sgirish 		}
568144961713Sgirish 	}
568244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
568398ecde52Stm 	    "<== nxge_link_monitor port<%d> enable=%d",
568498ecde52Stm 	    nxgep->mac.portnum, enable));
5685678453a8Sspeer 
568644961713Sgirish 	return (NXGE_OK);
568744961713Sgirish fail:
568844961713Sgirish 	return (status);
568900161856Syc 
569000161856Syc }
569100161856Syc 
569200161856Syc nxge_status_t
569300161856Syc nxge_check_tn1010_link(p_nxge_t nxgep)
569400161856Syc {
569500161856Syc 	nxge_status_t	status = NXGE_OK;
569600161856Syc 	nxge_link_state_t link_up;
569700161856Syc 
569800161856Syc 	if (nxgep->nxge_magic != NXGE_MAGIC) {
569900161856Syc 		/* magic is 0 if driver is not attached */
570000161856Syc 		return (NXGE_ERROR);
570100161856Syc 	}
570200161856Syc 
570300161856Syc 	/* Link has been stopped, no need to continue */
570400161856Syc 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
570500161856Syc 		return (NXGE_OK);
570600161856Syc 	}
570700161856Syc 
570800161856Syc 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
570900161856Syc 		goto nxge_check_tn1010_link_exit;
571000161856Syc 
571100161856Syc 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
571200161856Syc 		goto fail;
571300161856Syc 
571400161856Syc nxge_check_tn1010_link_exit:
571500161856Syc 	if (link_up == LINK_IS_UP)
571600161856Syc 		nxge_link_is_up(nxgep);
571700161856Syc 	else if (link_up == LINK_IS_DOWN)
571800161856Syc 		nxge_link_is_down(nxgep);
571900161856Syc 
572000161856Syc 	/*
572100161856Syc 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
572200161856Syc 	 * which could be THIS function.
572300161856Syc 	 */
572400161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
572500161856Syc 
572600161856Syc 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_tn1010_link port<%d>",
572700161856Syc 	    portn));
572800161856Syc 	return (NXGE_OK);
572900161856Syc 
573000161856Syc fail:
573100161856Syc 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
573200161856Syc 
573300161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
573400161856Syc 	    "nxge_check_tn1010_link: Failed to check link"));
573500161856Syc 	return (status);
573600161856Syc }
573700161856Syc 
573800161856Syc 
573900161856Syc /*
574000161856Syc  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
574100161856Syc  */
574200161856Syc static nxge_status_t
574300161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
574400161856Syc {
574500161856Syc 	nxge_status_t	status = NXGE_OK;
574600161856Syc 	p_nxge_stats_t	statsp;
574700161856Syc 	uint8_t		phy_port_addr, portn;
574800161856Syc 	uint16_t	val;
574900161856Syc 
575000161856Syc 	*link_up = LINK_NO_CHANGE;
575100161856Syc 
575200161856Syc 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
575300161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
575400161856Syc 	statsp = nxgep->statsp;
575500161856Syc 
575600161856Syc 	/* Check if link is up */
575700161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
575800161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
575900161856Syc 	    != NXGE_OK) {
576000161856Syc 		goto fail;
576100161856Syc 	}
576200161856Syc 	/*
576300161856Syc 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
576400161856Syc 	 * portmode and link_speed
576500161856Syc 	 */
576600161856Syc 	if (val & TN1010_AN_LINK_STAT_BIT) {
576700161856Syc 		if (nxgep->link_notify ||
576800161856Syc 		    nxgep->statsp->mac_stats.link_up == 0) {
576900161856Syc 			statsp->mac_stats.link_up = 1;
577000161856Syc 			statsp->mac_stats.link_duplex = 2;
577100161856Syc 			*link_up = LINK_IS_UP;
577200161856Syc 			nxgep->link_notify = B_FALSE;
577300161856Syc 		}
577400161856Syc 	} else {
577500161856Syc 		if (nxgep->link_notify ||
577600161856Syc 		    nxgep->statsp->mac_stats.link_up == 1) {
577700161856Syc 			statsp->mac_stats.link_up = 0;
577800161856Syc 			statsp->mac_stats.link_speed = 0;
577900161856Syc 			statsp->mac_stats.link_duplex = 0;
578000161856Syc 			*link_up = LINK_IS_DOWN;
578100161856Syc 			nxgep->link_notify = B_FALSE;
578200161856Syc 		}
578300161856Syc 	}
578400161856Syc 	return (NXGE_OK);
578500161856Syc 
578600161856Syc fail:
578700161856Syc 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
578800161856Syc 	    "nxge_tn1010_check: Unable to check TN1010"));
578900161856Syc 	return (status);
579044961713Sgirish }
579144961713Sgirish 
579200161856Syc 
579344961713Sgirish /* Set promiscous mode */
579444961713Sgirish 
579544961713Sgirish nxge_status_t
579644961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
579744961713Sgirish {
579844961713Sgirish 	nxge_status_t status = NXGE_OK;
579944961713Sgirish 
580059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
580144961713Sgirish 
580244961713Sgirish 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
580344961713Sgirish 
580444961713Sgirish 	RW_ENTER_WRITER(&nxgep->filter_lock);
580544961713Sgirish 
580644961713Sgirish 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
580744961713Sgirish 		goto fail;
580844961713Sgirish 	}
580944961713Sgirish 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
581044961713Sgirish 		goto fail;
581144961713Sgirish 	}
581244961713Sgirish 
581344961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
581444961713Sgirish 
581544961713Sgirish 	if (on)
581644961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_TRUE;
581744961713Sgirish 	else
581844961713Sgirish 		nxgep->statsp->mac_stats.promisc = B_FALSE;
581944961713Sgirish 
582044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
582144961713Sgirish 
582244961713Sgirish 	return (NXGE_OK);
582344961713Sgirish fail:
582444961713Sgirish 	RW_EXIT(&nxgep->filter_lock);
582544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
582659ac0c16Sdavemq 	    "Unable to set promisc (%d)", on));
582744961713Sgirish 
582844961713Sgirish 	return (status);
582944961713Sgirish }
583044961713Sgirish 
583144961713Sgirish /*ARGSUSED*/
583244961713Sgirish uint_t
583344961713Sgirish nxge_mif_intr(void *arg1, void *arg2)
583444961713Sgirish {
583544961713Sgirish #ifdef	NXGE_DEBUG
583644961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
583744961713Sgirish #endif
583844961713Sgirish #if NXGE_MIF
583944961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
584044961713Sgirish 	uint32_t		status;
584144961713Sgirish 	npi_handle_t		handle;
584244961713Sgirish 	uint8_t			portn;
584344961713Sgirish 	p_nxge_stats_t		statsp;
584444961713Sgirish #endif
584544961713Sgirish 
584644961713Sgirish #ifdef	NXGE_MIF
584744961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
584844961713Sgirish 		nxgep = ldvp->nxgep;
584944961713Sgirish 	}
585044961713Sgirish 	nxgep = ldvp->nxgep;
585144961713Sgirish #endif
585244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
585344961713Sgirish 
585444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
585544961713Sgirish 	return (DDI_INTR_CLAIMED);
585644961713Sgirish 
585744961713Sgirish mif_intr_fail:
585844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
585944961713Sgirish 	return (DDI_INTR_UNCLAIMED);
586044961713Sgirish }
586144961713Sgirish 
586244961713Sgirish /*ARGSUSED*/
586344961713Sgirish uint_t
586444961713Sgirish nxge_mac_intr(void *arg1, void *arg2)
586544961713Sgirish {
586644961713Sgirish 	p_nxge_t		nxgep = (p_nxge_t)arg2;
586744961713Sgirish 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
586844961713Sgirish 	p_nxge_ldg_t		ldgp;
586944961713Sgirish 	uint32_t		status;
587044961713Sgirish 	npi_handle_t		handle;
587144961713Sgirish 	uint8_t			portn;
587244961713Sgirish 	p_nxge_stats_t		statsp;
587344961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
587444961713Sgirish 
587544961713Sgirish 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
587644961713Sgirish 		nxgep = ldvp->nxgep;
587744961713Sgirish 	}
587844961713Sgirish 
587944961713Sgirish 	ldgp = ldvp->ldgp;
588044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
588159ac0c16Sdavemq 	    "group %d", ldgp->ldg));
588244961713Sgirish 
588344961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
588444961713Sgirish 	/*
588544961713Sgirish 	 * This interrupt handler is for a specific
588644961713Sgirish 	 * mac port.
588744961713Sgirish 	 */
588844961713Sgirish 	statsp = (p_nxge_stats_t)nxgep->statsp;
588944961713Sgirish 	portn = nxgep->mac.portnum;
589044961713Sgirish 
589144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
589259ac0c16Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
589344961713Sgirish 
589444961713Sgirish 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
589544961713Sgirish 		rs = npi_xmac_tx_get_istatus(handle, portn,
589644961713Sgirish 					(xmac_tx_iconfig_t *)&status);
589744961713Sgirish 		if (rs != NPI_SUCCESS)
589844961713Sgirish 			goto npi_fail;
589944961713Sgirish 		if (status & ICFG_XMAC_TX_ALL) {
590044961713Sgirish 			if (status & ICFG_XMAC_TX_UNDERRUN) {
590144961713Sgirish 				statsp->xmac_stats.tx_underflow_err++;
590244961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
590344961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
590444961713Sgirish 			}
590544961713Sgirish 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
590644961713Sgirish 				statsp->xmac_stats.tx_maxpktsize_err++;
5907f6485eecSyc 				/*
5908f6485eecSyc 				 * Do not send FMA ereport because this
5909f6485eecSyc 				 * error does not indicate HW failure.
5910f6485eecSyc 				 */
591144961713Sgirish 			}
591244961713Sgirish 			if (status & ICFG_XMAC_TX_OVERFLOW) {
591344961713Sgirish 				statsp->xmac_stats.tx_overflow_err++;
591444961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
591544961713Sgirish 					NXGE_FM_EREPORT_TXMAC_OVERFLOW);
591644961713Sgirish 			}
591744961713Sgirish 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
591844961713Sgirish 				statsp->xmac_stats.tx_fifo_xfr_err++;
591944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
592044961713Sgirish 					NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
592144961713Sgirish 			}
592244961713Sgirish 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
592344961713Sgirish 				statsp->xmac_stats.tx_byte_cnt +=
592444961713Sgirish 							XTXMAC_BYTE_CNT_MASK;
592544961713Sgirish 			}
592644961713Sgirish 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
592744961713Sgirish 				statsp->xmac_stats.tx_frame_cnt +=
592844961713Sgirish 							XTXMAC_FRM_CNT_MASK;
592944961713Sgirish 			}
593044961713Sgirish 		}
593144961713Sgirish 
593244961713Sgirish 		rs = npi_xmac_rx_get_istatus(handle, portn,
593344961713Sgirish 					(xmac_rx_iconfig_t *)&status);
593444961713Sgirish 		if (rs != NPI_SUCCESS)
593544961713Sgirish 			goto npi_fail;
593644961713Sgirish 		if (status & ICFG_XMAC_RX_ALL) {
593744961713Sgirish 			if (status & ICFG_XMAC_RX_OVERFLOW)
593844961713Sgirish 				statsp->xmac_stats.rx_overflow_err++;
593944961713Sgirish 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
594044961713Sgirish 				statsp->xmac_stats.rx_underflow_err++;
594144961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
594244961713Sgirish 					NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
594344961713Sgirish 			}
5944f6485eecSyc 			/*
5945f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5946f6485eecSyc 			 * because they do not indicate HW failures.
5947f6485eecSyc 			 */
594844961713Sgirish 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
594944961713Sgirish 				statsp->xmac_stats.rx_crc_err_cnt +=
595044961713Sgirish 							XRXMAC_CRC_ER_CNT_MASK;
595144961713Sgirish 			}
595244961713Sgirish 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
595344961713Sgirish 				statsp->xmac_stats.rx_len_err_cnt +=
595444961713Sgirish 							MAC_LEN_ER_CNT_MASK;
595544961713Sgirish 			}
595644961713Sgirish 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
595744961713Sgirish 				statsp->xmac_stats.rx_viol_err_cnt +=
595844961713Sgirish 							XRXMAC_CD_VIO_CNT_MASK;
595944961713Sgirish 			}
596044961713Sgirish 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
596144961713Sgirish 				statsp->xmac_stats.rx_byte_cnt +=
596244961713Sgirish 							XRXMAC_BT_CNT_MASK;
596344961713Sgirish 			}
596444961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
596544961713Sgirish 				statsp->xmac_stats.rx_hist1_cnt +=
596644961713Sgirish 							XRXMAC_HIST_CNT1_MASK;
596744961713Sgirish 			}
596844961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
596944961713Sgirish 				statsp->xmac_stats.rx_hist2_cnt +=
597044961713Sgirish 							XRXMAC_HIST_CNT2_MASK;
597144961713Sgirish 			}
597244961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
597344961713Sgirish 				statsp->xmac_stats.rx_hist3_cnt +=
597444961713Sgirish 							XRXMAC_HIST_CNT3_MASK;
597544961713Sgirish 			}
597644961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
597744961713Sgirish 				statsp->xmac_stats.rx_hist4_cnt +=
597844961713Sgirish 							XRXMAC_HIST_CNT4_MASK;
597944961713Sgirish 			}
598044961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
598144961713Sgirish 				statsp->xmac_stats.rx_hist5_cnt +=
598244961713Sgirish 							XRXMAC_HIST_CNT5_MASK;
598344961713Sgirish 			}
598444961713Sgirish 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
598544961713Sgirish 				statsp->xmac_stats.rx_hist6_cnt +=
598644961713Sgirish 							XRXMAC_HIST_CNT6_MASK;
598744961713Sgirish 			}
598844961713Sgirish 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
598944961713Sgirish 				statsp->xmac_stats.rx_broadcast_cnt +=
599044961713Sgirish 							XRXMAC_BC_FRM_CNT_MASK;
599144961713Sgirish 			}
599244961713Sgirish 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
599344961713Sgirish 				statsp->xmac_stats.rx_mult_cnt +=
599444961713Sgirish 							XRXMAC_MC_FRM_CNT_MASK;
599544961713Sgirish 			}
5996f6485eecSyc 			/*
5997f6485eecSyc 			 * Do not send FMA ereport for the following 3 errors
5998f6485eecSyc 			 * because they do not indicate HW failures.
5999f6485eecSyc 			 */
600044961713Sgirish 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
600144961713Sgirish 				statsp->xmac_stats.rx_frag_cnt +=
600244961713Sgirish 							XRXMAC_FRAG_CNT_MASK;
600344961713Sgirish 			}
600444961713Sgirish 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
600544961713Sgirish 				statsp->xmac_stats.rx_frame_align_err_cnt +=
600644961713Sgirish 							XRXMAC_AL_ER_CNT_MASK;
600744961713Sgirish 			}
600844961713Sgirish 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
600944961713Sgirish 				statsp->xmac_stats.rx_linkfault_err_cnt +=
601044961713Sgirish 							XMAC_LINK_FLT_CNT_MASK;
601144961713Sgirish 			}
601244961713Sgirish 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
601344961713Sgirish 				statsp->xmac_stats.rx_remotefault_err++;
601444961713Sgirish 			}
601544961713Sgirish 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
601644961713Sgirish 				statsp->xmac_stats.rx_localfault_err++;
601744961713Sgirish 			}
601844961713Sgirish 		}
601944961713Sgirish 
602044961713Sgirish 		rs = npi_xmac_ctl_get_istatus(handle, portn,
602144961713Sgirish 						(xmac_ctl_iconfig_t *)&status);
602244961713Sgirish 		if (rs != NPI_SUCCESS)
602344961713Sgirish 			goto npi_fail;
602444961713Sgirish 		if (status & ICFG_XMAC_CTRL_ALL) {
602544961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
602644961713Sgirish 				statsp->xmac_stats.rx_pause_cnt++;
602744961713Sgirish 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
602844961713Sgirish 				statsp->xmac_stats.tx_pause_state++;
602944961713Sgirish 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
603044961713Sgirish 				statsp->xmac_stats.tx_nopause_state++;
603144961713Sgirish 		}
603244961713Sgirish 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
603344961713Sgirish 		rs = npi_bmac_tx_get_istatus(handle, portn,
603444961713Sgirish 						(bmac_tx_iconfig_t *)&status);
603544961713Sgirish 		if (rs != NPI_SUCCESS)
603644961713Sgirish 			goto npi_fail;
603744961713Sgirish 		if (status & ICFG_BMAC_TX_ALL) {
603844961713Sgirish 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
603944961713Sgirish 				statsp->bmac_stats.tx_underrun_err++;
604044961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
604144961713Sgirish 					NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
604244961713Sgirish 			}
604344961713Sgirish 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
604444961713Sgirish 				statsp->bmac_stats.tx_max_pkt_err++;
604544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
604644961713Sgirish 					NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
604744961713Sgirish 			}
604844961713Sgirish 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
604944961713Sgirish 				statsp->bmac_stats.tx_byte_cnt +=
605044961713Sgirish 							BTXMAC_BYTE_CNT_MASK;
605144961713Sgirish 			}
605244961713Sgirish 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
605344961713Sgirish 				statsp->bmac_stats.tx_frame_cnt +=
605444961713Sgirish 							BTXMAC_FRM_CNT_MASK;
605544961713Sgirish 			}
605644961713Sgirish 		}
605744961713Sgirish 
605844961713Sgirish 		rs = npi_bmac_rx_get_istatus(handle, portn,
605944961713Sgirish 						(bmac_rx_iconfig_t *)&status);
606044961713Sgirish 		if (rs != NPI_SUCCESS)
606144961713Sgirish 			goto npi_fail;
606244961713Sgirish 		if (status & ICFG_BMAC_RX_ALL) {
606344961713Sgirish 			if (status & ICFG_BMAC_RX_OVERFLOW) {
606444961713Sgirish 				statsp->bmac_stats.rx_overflow_err++;
606544961713Sgirish 			}
606644961713Sgirish 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
606744961713Sgirish 				statsp->bmac_stats.rx_frame_cnt +=
606844961713Sgirish 							RXMAC_FRM_CNT_MASK;
606944961713Sgirish 			}
607044961713Sgirish 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
607144961713Sgirish 				statsp->bmac_stats.rx_crc_err_cnt +=
607244961713Sgirish 							BMAC_CRC_ER_CNT_MASK;
607344961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
607444961713Sgirish 					NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
607544961713Sgirish 			}
607644961713Sgirish 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
607744961713Sgirish 				statsp->bmac_stats.rx_len_err_cnt +=
607844961713Sgirish 							MAC_LEN_ER_CNT_MASK;
607944961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
608044961713Sgirish 				NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
608144961713Sgirish 			}
608244961713Sgirish 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
608344961713Sgirish 				statsp->bmac_stats.rx_viol_err_cnt +=
608444961713Sgirish 							BMAC_CD_VIO_CNT_MASK;
608544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
608644961713Sgirish 					NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
608744961713Sgirish 			}
608844961713Sgirish 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
608944961713Sgirish 				statsp->bmac_stats.rx_byte_cnt +=
609044961713Sgirish 							BRXMAC_BYTE_CNT_MASK;
609144961713Sgirish 			}
609244961713Sgirish 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
609344961713Sgirish 				statsp->bmac_stats.rx_align_err_cnt +=
609444961713Sgirish 							BMAC_AL_ER_CNT_MASK;
609544961713Sgirish 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
609644961713Sgirish 					NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
609744961713Sgirish 			}
609844961713Sgirish 
609944961713Sgirish 			rs = npi_bmac_ctl_get_istatus(handle, portn,
610044961713Sgirish 						(bmac_ctl_iconfig_t *)&status);
610144961713Sgirish 			if (rs != NPI_SUCCESS)
610244961713Sgirish 				goto npi_fail;
610344961713Sgirish 
610444961713Sgirish 			if (status & ICFG_BMAC_CTL_ALL) {
610544961713Sgirish 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
610644961713Sgirish 					statsp->bmac_stats.rx_pause_cnt++;
610744961713Sgirish 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
610844961713Sgirish 					statsp->bmac_stats.tx_pause_state++;
610944961713Sgirish 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
611044961713Sgirish 					statsp->bmac_stats.tx_nopause_state++;
611144961713Sgirish 			}
611244961713Sgirish 		}
611344961713Sgirish 
611444961713Sgirish 	if (ldgp->nldvs == 1) {
611544961713Sgirish 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
611644961713Sgirish 			B_TRUE, ldgp->ldg_timer);
611744961713Sgirish 	}
611844961713Sgirish 
611944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
612044961713Sgirish 	return (DDI_INTR_CLAIMED);
612144961713Sgirish 
612244961713Sgirish npi_fail:
612344961713Sgirish 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
612444961713Sgirish 	return (DDI_INTR_UNCLAIMED);
612544961713Sgirish }
612644961713Sgirish 
612744961713Sgirish nxge_status_t
612844961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
612944961713Sgirish {
613044961713Sgirish 	uint8_t		phy_port_addr;
613144961713Sgirish 	nxge_status_t	status = NXGE_OK;
613244961713Sgirish 	boolean_t	rx_sig_ok;
613344961713Sgirish 	boolean_t	pcs_blk_lock;
613444961713Sgirish 	boolean_t	link_align;
613544961713Sgirish 	uint16_t	val1, val2, val3;
613644961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
613744961713Sgirish 	uint16_t	val_debug;
613844961713Sgirish 	uint16_t	val;
613944961713Sgirish #endif
614044961713Sgirish 
614144961713Sgirish 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
614244961713Sgirish 
614344961713Sgirish #ifdef	NXGE_DEBUG_SYMBOL_ERR
614444961713Sgirish 	/* Check Device 3 Register Device 3 0xC809 */
614544961713Sgirish 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
614644961713Sgirish 	if ((val_debug & ~0x200) != 0) {
614744961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
614844961713Sgirish 				nxgep->mac.portnum, val_debug);
614944961713Sgirish 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
615044961713Sgirish 				&val_debug);
615144961713Sgirish 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
615244961713Sgirish 				nxgep->mac.portnum, val_debug);
615344961713Sgirish 	}
615444961713Sgirish 
615544961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
615644961713Sgirish 					XPCS_REG_DESCWERR_COUNTER, &val);
615744961713Sgirish 	if (val != 0)
615844961713Sgirish 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
615944961713Sgirish 
616044961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
616144961713Sgirish 					XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
616244961713Sgirish 	if (val != 0)
616344961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
616444961713Sgirish 
616544961713Sgirish 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
616644961713Sgirish 					XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
616744961713Sgirish 	if (val != 0)
616844961713Sgirish 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
616944961713Sgirish #endif
617044961713Sgirish 
617144961713Sgirish 	/* Check from BCM8704 if 10G link is up or down */
617244961713Sgirish 
617344961713Sgirish 	/* Check Device 1 Register 0xA bit0 */
617444961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
617544961713Sgirish 			BCM8704_PMA_PMD_DEV_ADDR,
617644961713Sgirish 			BCM8704_PMD_RECEIVE_SIG_DETECT,
617744961713Sgirish 			&val1);
617844961713Sgirish 	if (status != NXGE_OK)
617944961713Sgirish 		goto fail;
618044961713Sgirish 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
618144961713Sgirish 
618244961713Sgirish 	/* Check Device 3 Register 0x20 bit0 */
618344961713Sgirish 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
618444961713Sgirish 			BCM8704_PCS_DEV_ADDR,
618544961713Sgirish 			BCM8704_10GBASE_R_PCS_STATUS_REG,
618644961713Sgirish 			&val2)) != NPI_SUCCESS)
618744961713Sgirish 		goto fail;
618844961713Sgirish 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
618944961713Sgirish 
619044961713Sgirish 	/* Check Device 4 Register 0x18 bit12 */
619144961713Sgirish 	status = nxge_mdio_read(nxgep, phy_port_addr,
619244961713Sgirish 			BCM8704_PHYXS_ADDR,
619344961713Sgirish 			BCM8704_PHYXS_XGXS_LANE_STATUS_REG,
619444961713Sgirish 			&val3);
619544961713Sgirish 	if (status != NXGE_OK)
619644961713Sgirish 		goto fail;
61972d17280bSsbehera 
61982d17280bSsbehera 	switch (nxgep->chip_id) {
61992d17280bSsbehera 	case BCM8704_CHIP_ID:
62002d17280bSsbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
62012d17280bSsbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
62022d17280bSsbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
62032d17280bSsbehera 		break;
62042d17280bSsbehera 	case BCM8706_CHIP_ID:
62052d17280bSsbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
62062d17280bSsbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
62072d17280bSsbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
62082d17280bSsbehera 		    B_TRUE : B_FALSE;
62092d17280bSsbehera 		break;
62102d17280bSsbehera 	default:
62112d17280bSsbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
62122d17280bSsbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
62132d17280bSsbehera 		goto fail;
62142d17280bSsbehera 	}
62152d17280bSsbehera 
621644961713Sgirish 
621744961713Sgirish #ifdef	NXGE_DEBUG_ALIGN_ERR
621844961713Sgirish 	/* Temp workaround for link down issue */
621944961713Sgirish 	if (pcs_blk_lock == B_FALSE) {
622044961713Sgirish 		if (val2 != 0x4) {
622144961713Sgirish 			pcs_blk_lock = B_TRUE;
622244961713Sgirish 			cmn_err(CE_NOTE,
622344961713Sgirish 				"!LINK DEBUG: port%d PHY Dev3 "
622444961713Sgirish 				"Reg 0x20 = 0x%x\n",
622544961713Sgirish 				nxgep->mac.portnum, val2);
622644961713Sgirish 		}
622744961713Sgirish 	}
622844961713Sgirish 
622944961713Sgirish 	if (link_align == B_FALSE) {
623044961713Sgirish 		if (val3 != 0x140f) {
623144961713Sgirish 			link_align = B_TRUE;
623244961713Sgirish 			cmn_err(CE_NOTE,
623344961713Sgirish 				"!LINK DEBUG: port%d PHY Dev4 "
623444961713Sgirish 				"Reg 0x18 = 0x%x\n",
623544961713Sgirish 				nxgep->mac.portnum, val3);
623644961713Sgirish 		}
623744961713Sgirish 	}
623844961713Sgirish 
623944961713Sgirish 	if (rx_sig_ok == B_FALSE) {
624044961713Sgirish 		if ((val2 == 0) || (val3 == 0)) {
624144961713Sgirish 			rx_sig_ok = B_TRUE;
624244961713Sgirish 			cmn_err(CE_NOTE,
624344961713Sgirish 				"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
624444961713Sgirish 				nxgep->mac.portnum);
624544961713Sgirish 		}
624644961713Sgirish 	}
624744961713Sgirish #endif
624844961713Sgirish 
624944961713Sgirish 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
625044961713Sgirish 			(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
625144961713Sgirish 
625244961713Sgirish 	return (NXGE_OK);
625344961713Sgirish fail:
625444961713Sgirish 	return (status);
625544961713Sgirish }
625644961713Sgirish 
625752cdd236Ssbehera static nxge_status_t
625800161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
625952cdd236Ssbehera {
626052cdd236Ssbehera 	uint8_t		phy;
626152cdd236Ssbehera 	nxge_status_t   status = NXGE_OK;
626252cdd236Ssbehera 	boolean_t	pma_status;
626352cdd236Ssbehera 	boolean_t	pcs_status;
626452cdd236Ssbehera 	boolean_t	xgxs_status;
626552cdd236Ssbehera 	uint16_t	val;
626652cdd236Ssbehera 
626752cdd236Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
626852cdd236Ssbehera 
626952cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
627052cdd236Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
627152cdd236Ssbehera 
627252cdd236Ssbehera 	*link_up = B_FALSE;
627352cdd236Ssbehera 
627452cdd236Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
627552cdd236Ssbehera 
627652cdd236Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
627752cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
627852cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
627952cdd236Ssbehera 
628052cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
628152cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
628252cdd236Ssbehera 
628352cdd236Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
628452cdd236Ssbehera 
628552cdd236Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
628652cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
628752cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
628852cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
628952cdd236Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
629052cdd236Ssbehera 
629152cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
629252cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
629352cdd236Ssbehera 
629452cdd236Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
629552cdd236Ssbehera 
629652cdd236Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
629752cdd236Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
629852cdd236Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
629952cdd236Ssbehera 
630052cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
630152cdd236Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
630252cdd236Ssbehera 
630352cdd236Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
630452cdd236Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
630552cdd236Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
630652cdd236Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
630752cdd236Ssbehera 
630852cdd236Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
630952cdd236Ssbehera 	    B_TRUE : B_FALSE;
631052cdd236Ssbehera 
631152cdd236Ssbehera fail:
631252cdd236Ssbehera 
631352cdd236Ssbehera 	if (*link_up == B_FALSE) {
631452cdd236Ssbehera 		/* PCS OFF */
631552cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
631652cdd236Ssbehera 	} else {
631752cdd236Ssbehera 		/* PCS Activity */
631852cdd236Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
631952cdd236Ssbehera 	}
632052cdd236Ssbehera 
632152cdd236Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
632252cdd236Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
632352cdd236Ssbehera 
632452cdd236Ssbehera 	return (status);
632552cdd236Ssbehera }
632652cdd236Ssbehera 
632759ac0c16Sdavemq nxge_status_t
632859ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep)
632959ac0c16Sdavemq {
633059ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
633159ac0c16Sdavemq 	    != NPI_SUCCESS)
633259ac0c16Sdavemq 		return (NXGE_ERROR);
633359ac0c16Sdavemq 	else
633459ac0c16Sdavemq 		return (NXGE_OK);
633559ac0c16Sdavemq }
633644961713Sgirish 
633744961713Sgirish nxge_status_t
633859ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep)
633944961713Sgirish {
634059ac0c16Sdavemq 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
634159ac0c16Sdavemq 	    != NPI_SUCCESS)
634259ac0c16Sdavemq 		return (NXGE_ERROR);
634359ac0c16Sdavemq 	else
634459ac0c16Sdavemq 		return (NXGE_OK);
634559ac0c16Sdavemq }
634644961713Sgirish 
63472d17280bSsbehera static boolean_t
63482d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
63492d17280bSsbehera {
63502d17280bSsbehera 	uint32_t pma_pmd_id = 0;
63512d17280bSsbehera 	uint32_t pcs_id = 0;
63522d17280bSsbehera 	uint32_t phy_id = 0;
63532d17280bSsbehera 
63542d17280bSsbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
63552d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63562d17280bSsbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
63572d17280bSsbehera 	if ((pma_pmd_id & mask) == (id & mask))
63582d17280bSsbehera 		goto found_phy;
63592d17280bSsbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
63602d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63612d17280bSsbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
63622d17280bSsbehera 	if ((pcs_id & mask) == (id & mask))
63632d17280bSsbehera 		goto found_phy;
63642d17280bSsbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
63652d17280bSsbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63662d17280bSsbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
63672d17280bSsbehera 	if ((phy_id & mask) == (id & mask))
63682d17280bSsbehera 		goto found_phy;
63692d17280bSsbehera 
63702d17280bSsbehera 	return (B_FALSE);
63712d17280bSsbehera 
63722d17280bSsbehera found_phy:
63732d17280bSsbehera 	return (B_TRUE);
63742d17280bSsbehera }
63752d17280bSsbehera 
637659ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
637759ac0c16Sdavemq 
637859ac0c16Sdavemq static boolean_t
637959ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
638059ac0c16Sdavemq {
638159ac0c16Sdavemq 	int		i;
638259ac0c16Sdavemq 	boolean_t	found = B_FALSE;
638359ac0c16Sdavemq 
638459ac0c16Sdavemq 	switch (type) {
638559ac0c16Sdavemq 	case CLAUSE_45_TYPE:
638600161856Syc 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
638700161856Syc 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
638800161856Syc 			    (id & BCM_PHY_ID_MASK)) ||
638900161856Syc 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
639059ac0c16Sdavemq 				found = B_TRUE;
639159ac0c16Sdavemq 				break;
639259ac0c16Sdavemq 			}
639359ac0c16Sdavemq 		}
639459ac0c16Sdavemq 		break;
639559ac0c16Sdavemq 	case CLAUSE_22_TYPE:
639600161856Syc 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
639730505775Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
639830505775Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
639959ac0c16Sdavemq 				found = B_TRUE;
640059ac0c16Sdavemq 				break;
640156d930aeSspeer 			}
640244961713Sgirish 		}
640359ac0c16Sdavemq 		break;
640459ac0c16Sdavemq 	default:
640559ac0c16Sdavemq 		break;
640656d930aeSspeer 	}
640756d930aeSspeer 
640859ac0c16Sdavemq 	return (found);
640959ac0c16Sdavemq }
641059ac0c16Sdavemq 
64112e59129aSraghus static uint32_t
64122e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
64132e59129aSraghus {
64142e59129aSraghus 	uint16_t	val1 = 0;
64152e59129aSraghus 	uint16_t	val2 = 0;
64162e59129aSraghus 	uint32_t	pma_pmd_dev_id = 0;
64172e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
64182e59129aSraghus 
641953560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
64202e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
64212e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
64222e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
64232e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
642453560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
64252e59129aSraghus 
642600161856Syc 	/* Concatenate the Device ID stored in two registers. */
64272e59129aSraghus 	pma_pmd_dev_id = val1;
64282e59129aSraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
64292e59129aSraghus 	pma_pmd_dev_id |= val2;
64302e59129aSraghus 
64312e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
64322e59129aSraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
64332e59129aSraghus 
64342e59129aSraghus 	return (pma_pmd_dev_id);
64352e59129aSraghus }
64362e59129aSraghus 
64372e59129aSraghus static uint32_t
64382e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
64392e59129aSraghus {
64402e59129aSraghus 	uint16_t	val1 = 0;
64412e59129aSraghus 	uint16_t	val2 = 0;
64422e59129aSraghus 	uint32_t	pcs_dev_id = 0;
64432e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
64442e59129aSraghus 
644553560810Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
64462e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
64472e59129aSraghus 	    NXGE_DEV_ID_REG_1, &val1);
64482e59129aSraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
64492e59129aSraghus 	    NXGE_DEV_ID_REG_2, &val2);
645053560810Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
64512e59129aSraghus 
64522e59129aSraghus 	pcs_dev_id = val1;
64532e59129aSraghus 	pcs_dev_id = (pcs_dev_id << 16);
64542e59129aSraghus 	pcs_dev_id |= val2;
64552e59129aSraghus 
64562e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
64572e59129aSraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
64582e59129aSraghus 
64592e59129aSraghus 	return (pcs_dev_id);
64602e59129aSraghus }
64612e59129aSraghus 
64622e59129aSraghus static uint32_t
64632e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
64642e59129aSraghus {
64652e59129aSraghus 	uint16_t	val1 = 0;
64662e59129aSraghus 	uint16_t	val2 = 0;
64672e59129aSraghus 	uint32_t	phy_id = 0;
64682e59129aSraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
64692e59129aSraghus 	npi_status_t	npi_status = NPI_SUCCESS;
64702e59129aSraghus 
6471321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
64722e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
64732e59129aSraghus 	    &val1);
64742e59129aSraghus 	if (npi_status != NPI_SUCCESS) {
64752e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
64762e59129aSraghus 		    "clause 22 read to reg 2 failed!!!"));
64772e59129aSraghus 		goto exit;
64782e59129aSraghus 	}
64792e59129aSraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
64802e59129aSraghus 	    &val2);
64812e59129aSraghus 	if (npi_status != 0) {
64822e59129aSraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
64832e59129aSraghus 		    "clause 22 read to reg 3 failed!!!"));
64842e59129aSraghus 		goto exit;
64852e59129aSraghus 	}
64862e59129aSraghus 	phy_id = val1;
64872e59129aSraghus 	phy_id = (phy_id << 16);
64882e59129aSraghus 	phy_id |= val2;
64892e59129aSraghus 
64902e59129aSraghus exit:
6491321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
64922e59129aSraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
64932e59129aSraghus 	    phy_port, phy_id));
64942e59129aSraghus 
64952e59129aSraghus 	return (phy_id);
64962e59129aSraghus }
64972e59129aSraghus 
649859ac0c16Sdavemq /*
649959ac0c16Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
650059ac0c16Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
650159ac0c16Sdavemq  * read. Then use the values obtained to determine the phy type of each port
650259ac0c16Sdavemq  * and the Neptune type.
650300161856Syc  *
650400161856Syc  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
650500161856Syc  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
650600161856Syc  * in case the portmode information is not available via OBP, nxge.conf,
650700161856Syc  * VPD or SEEPROM.
650859ac0c16Sdavemq  */
650959ac0c16Sdavemq nxge_status_t
651059ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
651159ac0c16Sdavemq {
651259a835ddSjoycey 	int		i, j, l;
651359ac0c16Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
651459ac0c16Sdavemq 	uint32_t	pcs_dev_id = 0;
651559ac0c16Sdavemq 	uint32_t	phy_id = 0;
651630505775Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
651730505775Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
651830505775Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
651959ac0c16Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
652059ac0c16Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
65212d17280bSsbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
65222d17280bSsbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
652359ac0c16Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
652400161856Syc 	uint8_t		num_xaui;
652559ac0c16Sdavemq 	nxge_status_t	status = NXGE_OK;
652656d930aeSspeer 
652759ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
652856d930aeSspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
652959ac0c16Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
653059ac0c16Sdavemq 	    nxgep->niu_type));
653159ac0c16Sdavemq 
6532678453a8Sspeer 	if (isLDOMguest(nxgep)) {
6533678453a8Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
6534678453a8Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
6535678453a8Sspeer 		return (NXGE_OK);
6536678453a8Sspeer 	}
6537678453a8Sspeer 
653859a835ddSjoycey 	j = l = 0;
653959ac0c16Sdavemq 	total_port_fd = total_phy_fd = 0;
654056d930aeSspeer 	/*
654159ac0c16Sdavemq 	 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved
654200161856Syc 	 * for on chip serdes usages. "i" in the following for loop starts at 8.
654356d930aeSspeer 	 */
654459ac0c16Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
65452e59129aSraghus 
65462e59129aSraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
654759ac0c16Sdavemq 
654859ac0c16Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
654959ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 1;
655059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
655152cdd236Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
655230505775Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
655300161856Syc 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
655400161856Syc 				    == TN1010_DEV_ID) {
655500161856Syc 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
655600161856Syc 				} else {
655700161856Syc 					port_pma_pmd_dev_id[j] =
655800161856Syc 					pma_pmd_dev_id & BCM_PHY_ID_MASK;
655900161856Syc 				}
65602d17280bSsbehera 				port_fd_arr[j] = (uint8_t)i;
656159ac0c16Sdavemq 				j++;
656259ac0c16Sdavemq 			}
656359ac0c16Sdavemq 		} else {
656459ac0c16Sdavemq 			pma_pmd_dev_fd[i] = 0;
656559ac0c16Sdavemq 		}
656659ac0c16Sdavemq 
65672e59129aSraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
656859ac0c16Sdavemq 
656959ac0c16Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
657059ac0c16Sdavemq 			pcs_dev_fd[i] = 1;
657159ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
657252cdd236Ssbehera 			    "dev %x found", i, pcs_dev_id));
657359a835ddSjoycey 			if (pma_pmd_dev_fd[i] == 1) {
657400161856Syc 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
657500161856Syc 				    == TN1010_DEV_ID) {
657600161856Syc 					port_pcs_dev_id[j - 1] =
657700161856Syc 					    TN1010_DEV_ID;
657800161856Syc 				} else {
657900161856Syc 					port_pcs_dev_id[j - 1] =
658000161856Syc 					    pcs_dev_id &
658100161856Syc 					    BCM_PHY_ID_MASK;
658200161856Syc 				}
658359a835ddSjoycey 			} else {
658459a835ddSjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
658500161856Syc 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
658600161856Syc 						== TN1010_DEV_ID) {
658700161856Syc 						port_pcs_dev_id[j] =
658800161856Syc 						    TN1010_DEV_ID;
658900161856Syc 					} else {
659000161856Syc 						port_pcs_dev_id[j] =
659100161856Syc 						    pcs_dev_id &
659200161856Syc 						    BCM_PHY_ID_MASK;
659300161856Syc 					}
659459a835ddSjoycey 					port_fd_arr[j] = (uint8_t)i;
659559a835ddSjoycey 					j++;
659659a835ddSjoycey 				}
659759ac0c16Sdavemq 			}
659859ac0c16Sdavemq 		} else {
659959ac0c16Sdavemq 			pcs_dev_fd[i] = 0;
660059ac0c16Sdavemq 		}
660159ac0c16Sdavemq 
66022d17280bSsbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
66032d17280bSsbehera 			total_port_fd ++;
66042d17280bSsbehera 		}
660559ac0c16Sdavemq 
66062e59129aSraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
660759ac0c16Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
66082d17280bSsbehera 			total_phy_fd ++;
660959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
661052cdd236Ssbehera 			    "%x found", i, phy_id));
661130505775Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
661200161856Syc 				if ((phy_id & TN1010_DEV_ID_MASK)
661300161856Syc 				    == TN1010_DEV_ID) {
661400161856Syc 					port_phy_id[l] = TN1010_DEV_ID;
661500161856Syc 				} else {
661600161856Syc 					port_phy_id[l]
661700161856Syc 					    = phy_id & BCM_PHY_ID_MASK;
661800161856Syc 				}
66192d17280bSsbehera 				phy_fd_arr[l] = (uint8_t)i;
662059ac0c16Sdavemq 				l++;
662159ac0c16Sdavemq 			}
662259ac0c16Sdavemq 		}
662359ac0c16Sdavemq 	}
662459ac0c16Sdavemq 
662559ac0c16Sdavemq 	switch (total_port_fd) {
662659ac0c16Sdavemq 	case 2:
662759ac0c16Sdavemq 		switch (total_phy_fd) {
662859ac0c16Sdavemq 		case 2:
662959a835ddSjoycey 			/* 2 10G, 2 1G RGMII Fiber */
663059a835ddSjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
663159a835ddSjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
663259a835ddSjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
663359a835ddSjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
663459a835ddSjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
663559a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
663659a835ddSjoycey 
663759a835ddSjoycey 				hw_p->platform_type =
663859a835ddSjoycey 					    P_NEPTUNE_GENERIC;
663959a835ddSjoycey 
664059a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
664159a835ddSjoycey 
664259a835ddSjoycey 				hw_p->xcvr_addr[0] = port_fd_arr[0];
664359a835ddSjoycey 				hw_p->xcvr_addr[1] = port_fd_arr[1];
664459a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
664559a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
664659a835ddSjoycey 
664759a835ddSjoycey 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
664859a835ddSjoycey 				    "ARTM card with 2 10G, 2 1G"));
664959a835ddSjoycey 			} else {
665059a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
665159a835ddSjoycey 				    "Unsupported neptune type 1"));
665259a835ddSjoycey 				goto error_exit;
665359a835ddSjoycey 			}
665459a835ddSjoycey 			break;
665559a835ddSjoycey 
665659ac0c16Sdavemq 		case 1:
665759ac0c16Sdavemq 			/* TODO - 2 10G, 1 1G */
665859ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
665959ac0c16Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
666059ac0c16Sdavemq 			goto error_exit;
666159ac0c16Sdavemq 		case 0:
666200161856Syc 			/*
666300161856Syc 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
666400161856Syc 			 * cards, etc.
666500161856Syc 			 */
666630505775Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
666730505775Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
666830505775Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
666952cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
667052cdd236Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
667152cdd236Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
667252cdd236Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
667352cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
667452cdd236Ssbehera 			    (port_pma_pmd_dev_id[1] ==
667552cdd236Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
66762e59129aSraghus 
66772e59129aSraghus 				/*
66782e59129aSraghus 				 * Check the first phy port address against
66792e59129aSraghus 				 * the known phy start addresses to determine
66802e59129aSraghus 				 * the platform type.
66812e59129aSraghus 				 */
66822d17280bSsbehera 
66832d17280bSsbehera 				switch (port_fd_arr[0]) {
668400161856Syc 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
668552cdd236Ssbehera 					/*
668652cdd236Ssbehera 					 * The Marvell case also falls into
668752cdd236Ssbehera 					 * this case as
668852cdd236Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
668900161856Syc 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
669052cdd236Ssbehera 					 * This is OK for the 2 10G case.
669152cdd236Ssbehera 					 */
66922e59129aSraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
66932e59129aSraghus 					hw_p->platform_type =
66942e59129aSraghus 					    P_NEPTUNE_ATLAS_2PORT;
66952d17280bSsbehera 					break;
669600161856Syc 				case GOA_CLAUSE45_PORT_ADDR_BASE:
66972d17280bSsbehera 					if (hw_p->platform_type !=
66982d17280bSsbehera 					    P_NEPTUNE_NIU) {
66992d17280bSsbehera 						hw_p->platform_type =
67002d17280bSsbehera 						    P_NEPTUNE_GENERIC;
67012d17280bSsbehera 						hw_p->niu_type =
67022d17280bSsbehera 						    NEPTUNE_2_10GF;
67032d17280bSsbehera 					}
67042d17280bSsbehera 					break;
67052d17280bSsbehera 				default:
67062d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67072e59129aSraghus 					    "Unsupported neptune type 2 - 1"));
67082e59129aSraghus 					goto error_exit;
67092e59129aSraghus 				}
67102d17280bSsbehera 
67112d17280bSsbehera 				for (i = 0; i < 2; i++) {
67122d17280bSsbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
67132d17280bSsbehera 				}
671400161856Syc 
671500161856Syc 			/* Both XAUI slots have copper XAUI cards */
671600161856Syc 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
671700161856Syc 			    == TN1010_DEV_ID) &&
671800161856Syc 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
671900161856Syc 			    == TN1010_DEV_ID)) ||
672000161856Syc 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
672100161856Syc 			    == TN1010_DEV_ID) &&
672200161856Syc 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
672300161856Syc 			    == TN1010_DEV_ID))) {
672400161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010;
672500161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
672600161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
672700161856Syc 
672800161856Syc 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
672900161856Syc 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
673000161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
673100161856Syc 			    == TN1010_DEV_ID) ||
673200161856Syc 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
673300161856Syc 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
673400161856Syc 			    TN1010_DEV_ID)) {
673500161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
673600161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
673700161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
673800161856Syc 
673900161856Syc 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
674000161856Syc 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
674100161856Syc 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
674200161856Syc 			    == TN1010_DEV_ID) ||
674300161856Syc 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
674400161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
674500161856Syc 			    == TN1010_DEV_ID)) {
674600161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
674700161856Syc 				hw_p->xcvr_addr[0] = port_fd_arr[0];
674800161856Syc 				hw_p->xcvr_addr[1] = port_fd_arr[1];
674900161856Syc 
675059ac0c16Sdavemq 			} else {
675159ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
675259ac0c16Sdavemq 				    "Unsupported neptune type 2"));
675359ac0c16Sdavemq 				goto error_exit;
675459ac0c16Sdavemq 			}
675559ac0c16Sdavemq 			break;
675600161856Syc 
675759ac0c16Sdavemq 		case 4:
675800161856Syc 			if (nxge_get_num_of_xaui(
675900161856Syc 			    port_pma_pmd_dev_id, port_pcs_dev_id,
676000161856Syc 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
676100161856Syc 				goto error_exit;
676200161856Syc 			}
676300161856Syc 			if (num_xaui != 2)
676400161856Syc 				goto error_exit;
676559ac0c16Sdavemq 
676600161856Syc 			/*
676700161856Syc 			 *  Maramba with 2 XAUIs (either fiber or copper)
676800161856Syc 			 *
676900161856Syc 			 * Check the first phy port address against
677000161856Syc 			 * the known phy start addresses to determine
677100161856Syc 			 * the platform type.
677200161856Syc 			 */
677300161856Syc 			switch (phy_fd_arr[0]) {
677400161856Syc 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
677500161856Syc 				hw_p->platform_type =
677600161856Syc 				    P_NEPTUNE_MARAMBA_P0;
677700161856Syc 				break;
677800161856Syc 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
677900161856Syc 				hw_p->platform_type =
678000161856Syc 				    P_NEPTUNE_MARAMBA_P1;
678100161856Syc 				break;
678200161856Syc 			default:
678300161856Syc 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
678400161856Syc 				    "Unknown port %d...Cannot "
678500161856Syc 				    "determine platform type", i));
678600161856Syc 				goto error_exit;
678700161856Syc 			}
67882d17280bSsbehera 
678900161856Syc 			hw_p->xcvr_addr[0] = port_fd_arr[0];
679000161856Syc 			hw_p->xcvr_addr[1] = port_fd_arr[1];
679100161856Syc 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
679200161856Syc 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
679300161856Syc 
679400161856Syc 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
679500161856Syc 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
679600161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
679700161856Syc 			    == TN1010_DEV_ID) {
679800161856Syc 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
679900161856Syc 
680000161856Syc 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
680100161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
680200161856Syc 			    == TN1010_DEV_ID) &&
680300161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
680400161856Syc 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
680500161856Syc 
680600161856Syc 			/* Both slots have fiber XAUI */
680700161856Syc 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
680800161856Syc 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
68092e59129aSraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
68102e59129aSraghus 
681100161856Syc 			/* Both slots have copper XAUI */
681200161856Syc 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
681300161856Syc 			    == TN1010_DEV_ID) &&
681400161856Syc 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
681500161856Syc 			    == TN1010_DEV_ID) {
681600161856Syc 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
68172d17280bSsbehera 
681859ac0c16Sdavemq 			} else {
681959ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
682059ac0c16Sdavemq 				    "Unsupported neptune type 3"));
682159ac0c16Sdavemq 				goto error_exit;
682259ac0c16Sdavemq 			}
682359ac0c16Sdavemq 			break;
682459ac0c16Sdavemq 		default:
682559ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
682659ac0c16Sdavemq 			    "Unsupported neptune type 5"));
682759ac0c16Sdavemq 			goto error_exit;
682859ac0c16Sdavemq 		}
682930505775Ssbehera 		break;
683000161856Syc 	case 1: 	/* Only one clause45 port */
683100161856Syc 		switch (total_phy_fd) {	/* Number of clause22 ports */
683259ac0c16Sdavemq 		case 3:
68332e59129aSraghus 			/*
68342e59129aSraghus 			 * TODO 3 1G, 1 10G mode.
68352e59129aSraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
68362e59129aSraghus 			 * 1_10G_3_1G
68372e59129aSraghus 			 */
68382e59129aSraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68392e59129aSraghus 			    "Unsupported neptune type 7"));
68402e59129aSraghus 			goto error_exit;
684159ac0c16Sdavemq 		case 2:
684259ac0c16Sdavemq 			/*
684359ac0c16Sdavemq 			 * TODO 2 1G, 1 10G mode.
684459ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
684559ac0c16Sdavemq 			 * 1_10G_2_1G
684659ac0c16Sdavemq 			 */
684759ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
684859ac0c16Sdavemq 			    "Unsupported neptune type 8"));
684959ac0c16Sdavemq 			goto error_exit;
685059ac0c16Sdavemq 		case 1:
685159ac0c16Sdavemq 			/*
685259ac0c16Sdavemq 			 * TODO 1 1G, 1 10G mode.
685359ac0c16Sdavemq 			 * Differentiate between 1_1G_1_10G and
685459ac0c16Sdavemq 			 * 1_10G_1_1G
685559ac0c16Sdavemq 			 */
685659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
685759ac0c16Sdavemq 			    "Unsupported neptune type 9"));
685859ac0c16Sdavemq 			goto error_exit;
685900161856Syc 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
686000161856Syc 			/* Fiber XAUI */
68612d17280bSsbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
68622d17280bSsbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
68632d17280bSsbehera 
68642d17280bSsbehera 				/*
68652d17280bSsbehera 				 * Check the first phy port address against
68662d17280bSsbehera 				 * the known phy start addresses to determine
68672d17280bSsbehera 				 * the platform type.
68682d17280bSsbehera 				 */
68692d17280bSsbehera 
68702d17280bSsbehera 				switch (port_fd_arr[0]) {
687100161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
687200161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
687300161856Syc 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
687400161856Syc 					/*
687500161856Syc 					 * If hw_p->platform_type ==
687600161856Syc 					 * P_NEPTUNE_NIU, then portmode
687700161856Syc 					 * is already known, so there is
687800161856Syc 					 * no need to figure out hw_p->
687900161856Syc 					 * platform_type because
688000161856Syc 					 * platform_type is only for
688100161856Syc 					 * figuring out portmode.
688200161856Syc 					 */
68832d17280bSsbehera 					if (hw_p->platform_type !=
68842d17280bSsbehera 					    P_NEPTUNE_NIU) {
68852d17280bSsbehera 						hw_p->platform_type =
68862d17280bSsbehera 						    P_NEPTUNE_GENERIC;
68872d17280bSsbehera 						hw_p->niu_type =
68882d17280bSsbehera 						    NEPTUNE_2_10GF;
68892d17280bSsbehera 					}
68902d17280bSsbehera 					break;
68912d17280bSsbehera 				default:
68922d17280bSsbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68932d17280bSsbehera 					    "Unsupported neptune type 10"));
68942d17280bSsbehera 					goto error_exit;
68952d17280bSsbehera 				}
6896321febdeSsbehera 				/*
6897321febdeSsbehera 				 * For GOA, which is a hot swappable PHY, the
6898321febdeSsbehera 				 * phy address to function number mapping
6899321febdeSsbehera 				 * should be preserved, i.e., addr 16 is
6900321febdeSsbehera 				 * assigned to function 0 and 20 to function 1
6901321febdeSsbehera 				 * But for Huron XAUI, the assignment should
6902321febdeSsbehera 				 * be by function number, i.e., whichever
6903321febdeSsbehera 				 * function number attaches should be
6904321febdeSsbehera 				 * assigned the available PHY (this is required
6905321febdeSsbehera 				 * primarily to support pre-production Huron
6906321febdeSsbehera 				 * boards where function 0 is mapped to addr 17
6907321febdeSsbehera 				 */
6908321febdeSsbehera 				if (port_fd_arr[0] ==
690900161856Syc 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
6910321febdeSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
6911321febdeSsbehera 				} else {
6912321febdeSsbehera 					hw_p->xcvr_addr[nxgep->function_num] =
6913321febdeSsbehera 					    port_fd_arr[0];
6914321febdeSsbehera 				}
691500161856Syc 
691600161856Syc 			/* A 10G copper XAUI in either slot0 or slot1 */
691700161856Syc 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
691800161856Syc 			    == TN1010_DEV_ID ||
691900161856Syc 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
692000161856Syc 			    == TN1010_DEV_ID) {
692100161856Syc 				switch (port_fd_arr[0]) {
692200161856Syc 				/* The XAUI is in slot0 */
692300161856Syc 				case N2_CLAUSE45_PORT_ADDR_BASE:
692400161856Syc 					hw_p->niu_type = NEPTUNE_1_TN1010;
692500161856Syc 					break;
692600161856Syc 
692700161856Syc 				/* The XAUI is in slot1 */
692800161856Syc 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
692900161856Syc 					hw_p->niu_type
693000161856Syc 					    = NEPTUNE_1_NONE_1_TN1010;
693100161856Syc 					break;
693200161856Syc 				default:
693300161856Syc 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
693400161856Syc 					    "Unsupported XAUI port address"));
693500161856Syc 					goto error_exit;
693600161856Syc 				}
693700161856Syc 				hw_p->xcvr_addr[nxgep->function_num]
693800161856Syc 				    = port_fd_arr[0];
693900161856Syc 
69402d17280bSsbehera 			} else {
69412d17280bSsbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
694200161856Syc 				    "Unsupported PHY type"));
69432d17280bSsbehera 				goto error_exit;
69442d17280bSsbehera 			}
69452d17280bSsbehera 			break;
694600161856Syc 		case 4: /* Maramba always have 4 clause 45 ports */
694759ac0c16Sdavemq 
694800161856Syc 			/* Maramba with 1 XAUI */
694900161856Syc 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
695000161856Syc 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY ||
695100161856Syc 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
695200161856Syc 			    == TN1010_DEV_ID) ||
695300161856Syc 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
695400161856Syc 			    == TN1010_DEV_ID)) {
695559ac0c16Sdavemq 				/*
695659ac0c16Sdavemq 				 * Check the first phy port address against
695759ac0c16Sdavemq 				 * the known phy start addresses to determine
695859ac0c16Sdavemq 				 * the platform type.
695959ac0c16Sdavemq 				 */
69602d17280bSsbehera 				switch (phy_fd_arr[0]) {
696100161856Syc 				case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
696259ac0c16Sdavemq 					hw_p->platform_type =
696359ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P0;
69642d17280bSsbehera 					break;
696500161856Syc 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
696659ac0c16Sdavemq 					hw_p->platform_type =
696759ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
69682d17280bSsbehera 					break;
69692d17280bSsbehera 				default:
697059ac0c16Sdavemq 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
697159ac0c16Sdavemq 					    "Unknown port %d...Cannot "
69722d17280bSsbehera 					    "determine platform type 10 - 2",
69732d17280bSsbehera 					    i));
69742e59129aSraghus 					goto error_exit;
69752e59129aSraghus 				}
69762e59129aSraghus 
69772d17280bSsbehera 				/*
697800161856Syc 				 * Check the clause45 address to determine
69792d17280bSsbehera 				 * if XAUI is in port 0 or port 1.
69802d17280bSsbehera 				 */
69812d17280bSsbehera 				switch (port_fd_arr[0]) {
698200161856Syc 				case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
698300161856Syc 					if (port_pcs_dev_id[0]
698400161856Syc 					    == PHY_BCM8704_FAMILY ||
698500161856Syc 					    port_pma_pmd_dev_id[0]
698600161856Syc 					    == PHY_BCM8704_FAMILY) {
698700161856Syc 						hw_p->niu_type
698800161856Syc 						    = NEPTUNE_1_10GF_3_1GC;
698900161856Syc 					} else {
699000161856Syc 						hw_p->niu_type
699100161856Syc 						    = NEPTUNE_1_TN1010_3_1GC;
699200161856Syc 					}
69932d17280bSsbehera 					hw_p->xcvr_addr[0] = port_fd_arr[0];
69942d17280bSsbehera 					for (i = 1; i < NXGE_MAX_PORTS; i++) {
69952d17280bSsbehera 						hw_p->xcvr_addr[i] =
69962d17280bSsbehera 						    phy_fd_arr[i];
69972d17280bSsbehera 					}
69982d17280bSsbehera 					break;
699900161856Syc 				case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
700000161856Syc 					if (port_pcs_dev_id[0]
700100161856Syc 					    == PHY_BCM8704_FAMILY ||
700200161856Syc 					    port_pma_pmd_dev_id[0]
700300161856Syc 					    == PHY_BCM8704_FAMILY) {
700400161856Syc 						hw_p->niu_type =
700500161856Syc 						    NEPTUNE_1_1GC_1_10GF_2_1GC;
700600161856Syc 					} else {
700700161856Syc 						hw_p->niu_type =
700800161856Syc 						NEPTUNE_1_1GC_1_TN1010_2_1GC;
700900161856Syc 					}
70102d17280bSsbehera 					hw_p->xcvr_addr[0] = phy_fd_arr[0];
70112d17280bSsbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
70122d17280bSsbehera 					hw_p->xcvr_addr[2] = phy_fd_arr[2];
70132d17280bSsbehera 					hw_p->xcvr_addr[3] = phy_fd_arr[3];
70142d17280bSsbehera 					break;
70152d17280bSsbehera 				default:
70162e59129aSraghus 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70172e59129aSraghus 					    "Unsupported neptune type 11"));
70182e59129aSraghus 					goto error_exit;
701959ac0c16Sdavemq 				}
702059ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
702100161856Syc 				    "Maramba with 1 XAUI (fiber or copper)"));
702259ac0c16Sdavemq 			} else {
702359ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
702459ac0c16Sdavemq 				    "Unsupported neptune type 12"));
702559ac0c16Sdavemq 				goto error_exit;
702659ac0c16Sdavemq 			}
702759ac0c16Sdavemq 			break;
702859ac0c16Sdavemq 		default:
702959ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
703059ac0c16Sdavemq 			    "Unsupported neptune type 13"));
703159ac0c16Sdavemq 			goto error_exit;
703259ac0c16Sdavemq 		}
703359ac0c16Sdavemq 		break;
703400161856Syc 	case 0: /* 4 ports Neptune based NIC */
703559ac0c16Sdavemq 		switch (total_phy_fd) {
703659ac0c16Sdavemq 		case 4:
703730505775Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
703830505775Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
703930505775Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
704030505775Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
704159ac0c16Sdavemq 
704259ac0c16Sdavemq 				/*
704359ac0c16Sdavemq 				 * Check the first phy port address against
704459ac0c16Sdavemq 				 * the known phy start addresses to determine
704559ac0c16Sdavemq 				 * the platform type.
704659ac0c16Sdavemq 				 */
70472d17280bSsbehera 				switch (phy_fd_arr[0]) {
704800161856Syc 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
704959ac0c16Sdavemq 					hw_p->platform_type =
705059ac0c16Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
70512d17280bSsbehera 					break;
705200161856Syc 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
70532e59129aSraghus 					hw_p->platform_type =
70542e59129aSraghus 					    P_NEPTUNE_ATLAS_4PORT;
70552d17280bSsbehera 					break;
70562d17280bSsbehera 				default:
70572e59129aSraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
70582e59129aSraghus 					    "Unknown port %d...Cannot "
70592e59129aSraghus 					    "determine platform type", i));
70602e59129aSraghus 					goto error_exit;
706159ac0c16Sdavemq 				}
70622e59129aSraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
70632d17280bSsbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
70642d17280bSsbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
70652d17280bSsbehera 				}
706659ac0c16Sdavemq 			} else {
706759ac0c16Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
706859ac0c16Sdavemq 				    "Unsupported neptune type 14"));
706959ac0c16Sdavemq 				goto error_exit;
707059ac0c16Sdavemq 			}
707159ac0c16Sdavemq 			break;
707259ac0c16Sdavemq 		case 3:
707359ac0c16Sdavemq 			/* TODO 3 1G mode */
707459ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
707559ac0c16Sdavemq 			    "Unsupported neptune type 15"));
707659ac0c16Sdavemq 			goto error_exit;
707759ac0c16Sdavemq 		case 2:
707859ac0c16Sdavemq 			/* TODO 2 1G mode */
707959a835ddSjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
708059a835ddSjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
708159a835ddSjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
708259a835ddSjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
708359a835ddSjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
708459a835ddSjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
708559a835ddSjoycey 			} else {
708659a835ddSjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
708759a835ddSjoycey 				    "Unsupported neptune type 16"));
708859a835ddSjoycey 				goto error_exit;
708959a835ddSjoycey 			}
709059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
709159a835ddSjoycey 			    "2 RGMII Fiber ports - RTM"));
709259a835ddSjoycey 			break;
709359a835ddSjoycey 
709459ac0c16Sdavemq 		case 1:
709559ac0c16Sdavemq 			/* TODO 1 1G mode */
709659ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
709759ac0c16Sdavemq 			    "Unsupported neptune type 17"));
709859ac0c16Sdavemq 			goto error_exit;
709959ac0c16Sdavemq 		default:
710059ac0c16Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
710159ac0c16Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
710259ac0c16Sdavemq 			    total_phy_fd));
710359ac0c16Sdavemq 			goto error_exit;
710459ac0c16Sdavemq 		}
710559ac0c16Sdavemq 		break;
710659ac0c16Sdavemq 	default:
710756d930aeSspeer 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
710859ac0c16Sdavemq 		    "Unsupported neptune type 19"));
710959ac0c16Sdavemq 		goto error_exit;
711044961713Sgirish 	}
711144961713Sgirish 
711259ac0c16Sdavemq scan_exit:
711344961713Sgirish 
711459ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
711559ac0c16Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
711659ac0c16Sdavemq 	return (status);
711744961713Sgirish 
711859ac0c16Sdavemq error_exit:
711959ac0c16Sdavemq 	return (NXGE_ERROR);
712044961713Sgirish }
712156d930aeSspeer 
712256d930aeSspeer boolean_t
712356d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
712456d930aeSspeer {
712556d930aeSspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
712656d930aeSspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
712756d930aeSspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
712856d930aeSspeer 		return (B_FALSE);
712956d930aeSspeer 	else
713056d930aeSspeer 		return (B_TRUE);
713156d930aeSspeer }
713259ac0c16Sdavemq 
713359ac0c16Sdavemq static void
713459ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
713559ac0c16Sdavemq 
713659ac0c16Sdavemq 	npi_status_t rs = NPI_SUCCESS;
713759ac0c16Sdavemq 	uint8_t xcvr_portn;
713859ac0c16Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
713959ac0c16Sdavemq 
714059ac0c16Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
714159ac0c16Sdavemq 
714259ac0c16Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
714300161856Syc 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
714459ac0c16Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
714500161856Syc 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
714659ac0c16Sdavemq 	}
714759ac0c16Sdavemq 	/*
714859ac0c16Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
714959ac0c16Sdavemq 	 * swapped with ethernet port number. This is
715059ac0c16Sdavemq 	 * designed for better signal integrity in routing.
715159ac0c16Sdavemq 	 */
715259ac0c16Sdavemq 	switch (portn) {
715359ac0c16Sdavemq 	case 0:
715459ac0c16Sdavemq 		xcvr_portn += 3;
715559ac0c16Sdavemq 		break;
715659ac0c16Sdavemq 	case 1:
715759ac0c16Sdavemq 		xcvr_portn += 2;
715859ac0c16Sdavemq 		break;
715959ac0c16Sdavemq 	case 2:
716059ac0c16Sdavemq 		xcvr_portn += 1;
716159ac0c16Sdavemq 		break;
716259ac0c16Sdavemq 	case 3:
716359ac0c16Sdavemq 	default:
716459ac0c16Sdavemq 		break;
716559ac0c16Sdavemq 	}
716659ac0c16Sdavemq 
7167321febdeSsbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
716859ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
716959ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
717059ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
717159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
717259ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
717359ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
7174321febdeSsbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
717559ac0c16Sdavemq 		return;
717659ac0c16Sdavemq 	}
717759ac0c16Sdavemq 
717859ac0c16Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
717959ac0c16Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
718059ac0c16Sdavemq 	if (rs != NPI_SUCCESS) {
718159ac0c16Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
718259ac0c16Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
718359ac0c16Sdavemq 		    "returned error 0x[%x]", rs));
718459ac0c16Sdavemq 	}
718559ac0c16Sdavemq 
7186321febdeSsbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
718759ac0c16Sdavemq }
7188d81011f0Ssbehera 
7189d81011f0Ssbehera static nxge_status_t
7190d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
7191d81011f0Ssbehera {
7192d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7193d81011f0Ssbehera 	uint8_t		xcvr_portn;
7194d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7195d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7196d81011f0Ssbehera 	int		status = NXGE_OK;
7197d81011f0Ssbehera 
7198d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
7199d81011f0Ssbehera 
7200d81011f0Ssbehera 	statsp = nxgep->statsp;
7201d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7202d81011f0Ssbehera 	mii_regs = NULL;
7203d81011f0Ssbehera 	mode.value = 0;
72046b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7205d81011f0Ssbehera #if defined(__i386)
7206d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7207d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7208d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7209d81011f0Ssbehera 		goto fail;
7210d81011f0Ssbehera #else
7211d81011f0Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
7212d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7213d81011f0Ssbehera 	    mode.value)) != NXGE_OK) {
7214d81011f0Ssbehera 		goto fail;
7215d81011f0Ssbehera #endif
7216d81011f0Ssbehera 	}
7217d81011f0Ssbehera #if defined(__i386)
7218d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7219d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
7220d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7221d81011f0Ssbehera 		goto fail;
7222d81011f0Ssbehera 	}
7223d81011f0Ssbehera #else
7224d81011f0Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
7225d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
7226d81011f0Ssbehera 	    &mode.value)) != NXGE_OK) {
7227d81011f0Ssbehera 		goto fail;
7228d81011f0Ssbehera 	}
7229d81011f0Ssbehera #endif
7230d81011f0Ssbehera 
7231d81011f0Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
7232d81011f0Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
7233d81011f0Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7234d81011f0Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
7235d81011f0Ssbehera 	}
7236d81011f0Ssbehera 
7237d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7238d81011f0Ssbehera 	    "nxge_mii_get_link_mode: "
7239d81011f0Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
72406b438925Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
7241d81011f0Ssbehera 	    mode.value, nxgep->mac.portmode));
7242d81011f0Ssbehera 
7243d81011f0Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7244d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode"));
7245d81011f0Ssbehera 	return (status);
7246d81011f0Ssbehera fail:
7247d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7248d81011f0Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
7249d81011f0Ssbehera 	return (NXGE_ERROR);
7250d81011f0Ssbehera }
7251d81011f0Ssbehera 
72521bd6825cSml nxge_status_t
72531bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep)
72541bd6825cSml {
72551bd6825cSml 	npi_attr_t		ap;
72561bd6825cSml 	uint8_t			portn;
72571bd6825cSml 	npi_handle_t		handle;
72581bd6825cSml 	npi_status_t		rs = NPI_SUCCESS;
72591bd6825cSml 
72601bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
72611bd6825cSml 
72621bd6825cSml 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
72631bd6825cSml 	handle = nxgep->npi_handle;
72641bd6825cSml 
72651bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
72661bd6825cSml 	    "==> nxge_mac_sec_framesize: port<%d> "
72671bd6825cSml 	    "min framesize %d max framesize %d ",
72681bd6825cSml 	    portn,
72691bd6825cSml 	    nxgep->mac.minframesize,
72701bd6825cSml 	    nxgep->mac.maxframesize));
72711bd6825cSml 
72721bd6825cSml 	SET_MAC_ATTR2(handle, ap, portn,
72731bd6825cSml 	    MAC_PORT_FRAME_SIZE,
72741bd6825cSml 	    nxgep->mac.minframesize,
72751bd6825cSml 	    nxgep->mac.maxframesize,
72761bd6825cSml 	    rs);
72771bd6825cSml 	if (rs != NPI_SUCCESS) {
72781bd6825cSml 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
72791bd6825cSml 		    "<== nxge_mac_set_framesize: failed to configure "
72801bd6825cSml 		    "max/min frame size port %d", portn));
72811bd6825cSml 
72821bd6825cSml 		return (NXGE_ERROR | rs);
72831bd6825cSml 	}
72841bd6825cSml 
72851bd6825cSml 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
72861bd6825cSml 	    "<== nxge_mac_set_framesize: port<%d>", portn));
72871bd6825cSml 
72881bd6825cSml 	return (NXGE_OK);
72891bd6825cSml }
72901bd6825cSml 
729100161856Syc static nxge_status_t
729200161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
729300161856Syc     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
729400161856Syc {
729500161856Syc 	uint8_t i;
729600161856Syc 
729700161856Syc 	for (i = 0; i < 4; i++) {
729800161856Syc 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
729900161856Syc 			return (NXGE_ERROR);
730000161856Syc 	}
730100161856Syc 
730200161856Syc 	*num_xaui = 0;
730300161856Syc 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
730400161856Syc 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
730500161856Syc 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
730600161856Syc 	    == TN1010_DEV_ID) &&
730700161856Syc 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
730800161856Syc 	    == TN1010_DEV_ID))) {
730900161856Syc 		(*num_xaui) ++;
731000161856Syc 	}
731100161856Syc 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
731200161856Syc 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
731300161856Syc 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
731400161856Syc 	    == TN1010_DEV_ID) &&
731500161856Syc 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
731600161856Syc 	    == TN1010_DEV_ID))) {
731700161856Syc 		(*num_xaui) ++;
731800161856Syc 	}
731900161856Syc 	return (NXGE_OK);
732000161856Syc }
732100161856Syc 
732200161856Syc /*
732300161856Syc  * Instruction from Teranetics:  Once you detect link is up, go
732400161856Syc  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
732500161856Syc  * may want to qualify it by first checking Register 30.1.7:6 and
732600161856Syc  * making sure it reads "01" (Auto-Neg Complete).
732700161856Syc  *
732800161856Syc  * If this function is called when the link is down or before auto-
732900161856Syc  * negotiation has completed, then the speed of the PHY is not certain.
733000161856Syc  * In such cases, this function returns 1G as the default speed with
733100161856Syc  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
733200161856Syc  * driver based on a default speed because this function will be called
733300161856Syc  * again when the link comes up.  Returning NXGE_ERROR, which may
733400161856Syc  * cause brutal chain reaction in caller functions, is not necessary.
733500161856Syc  */
733600161856Syc static nxge_status_t
733700161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
733800161856Syc {
733900161856Syc 	uint8_t		phy_port_addr, autoneg_stat, link_up;
734000161856Syc 	nxge_status_t	status = NXGE_OK;
734100161856Syc 	uint16_t	val;
734200161856Syc 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
734300161856Syc 
734400161856Syc 	/* Set default speed to 10G */
734500161856Syc 	*speed = TN1010_SPEED_10G;
734600161856Syc 
734700161856Syc 	/* Set Clause 45 */
734800161856Syc 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
734900161856Syc 
735000161856Syc 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
735100161856Syc 
735200161856Syc 	/* Check Device 1 Register 0xA bit0 for link up status */
735300161856Syc 	status = nxge_mdio_read(nxgep, phy_port_addr,
735400161856Syc 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
735500161856Syc 	if (status != NXGE_OK)
735600161856Syc 		goto fail;
735700161856Syc 
735800161856Syc 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
735900161856Syc 	    ? B_TRUE : B_FALSE);
736000161856Syc 	if (link_up == B_FALSE) {
736100161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
736200161856Syc 		    "nxge_get_tn1010_speed: link is down"));
736300161856Syc 		goto nxge_get_tn1010_speed_exit;
736400161856Syc 	}
736500161856Syc 
736600161856Syc 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
736700161856Syc 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
736800161856Syc 	    &val)) != NXGE_OK) {
736900161856Syc 		goto fail;
737000161856Syc 	}
737100161856Syc 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
737200161856Syc 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
737300161856Syc 
737400161856Syc 	/*
737500161856Syc 	 * Return NXGE_OK even when we can not get a settled speed. In
737600161856Syc 	 * such case, the speed reported should not be trusted but that
737700161856Syc 	 * is OK, we will call this function periodically and will get
737800161856Syc 	 * the correct speed after the link is up.
737900161856Syc 	 */
738000161856Syc 	switch (autoneg_stat) {
738100161856Syc 	case TN1010_AN_IN_PROG:
738200161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
738300161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
738400161856Syc 		break;
738500161856Syc 	case TN1010_AN_COMPLETE:
738600161856Syc 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
738700161856Syc 		    TN1010_VENDOR_MMD1_DEV_ADDR,
738800161856Syc 		    TN1010_VENDOR_MMD1_STATUS_REG,
738900161856Syc 		    &val)) != NXGE_OK) {
739000161856Syc 			goto fail;
739100161856Syc 		}
739200161856Syc 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
739300161856Syc 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
739400161856Syc 		break;
739500161856Syc 	case TN1010_AN_RSVD:
739600161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
739700161856Syc 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
739800161856Syc 		break;
739900161856Syc 	case TN1010_AN_FAILED:
740000161856Syc 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
740100161856Syc 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
740200161856Syc 		break;
740300161856Syc 	default:
740400161856Syc 		break;
740500161856Syc 	}
740600161856Syc nxge_get_tn1010_speed_exit:
740700161856Syc 	return (NXGE_OK);
740800161856Syc fail:
740900161856Syc 	return (status);
741000161856Syc }
741100161856Syc 
741200161856Syc 
741300161856Syc /*
741400161856Syc  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
741500161856Syc  * figures out the speed of the PHY determined by the autonegotiation
741600161856Syc  * process and sets the following 3 parameters,
741700161856Syc  * 	nxgep->mac.portmode
741800161856Syc  *     	nxgep->statsp->mac_stats.link_speed
741900161856Syc  *	nxgep->statsp->mac_stats.xcvr_inuse
742000161856Syc  */
742100161856Syc static nxge_status_t
742200161856Syc nxge_set_tn1010_param(p_nxge_t nxgep)
742300161856Syc {
742400161856Syc 	uint16_t speed;
742500161856Syc 
742600161856Syc 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
742700161856Syc 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
742800161856Syc 		    "nxge_set_tn1010_param: "
742900161856Syc 		    "Failed to get TN1010 speed"));
743000161856Syc 		return (NXGE_ERROR);
743100161856Syc 	}
743200161856Syc 	if (speed == TN1010_SPEED_1G) {
743300161856Syc 		nxgep->mac.portmode = PORT_1G_TN1010;
743400161856Syc 		nxgep->statsp->mac_stats.link_speed = 1000;
743500161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
743600161856Syc 	} else {
743700161856Syc 		nxgep->mac.portmode = PORT_10G_TN1010;
743800161856Syc 		nxgep->statsp->mac_stats.link_speed = 10000;
743900161856Syc 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
744000161856Syc 	}
744100161856Syc 	return (NXGE_OK);
744200161856Syc }
744300161856Syc 
7444d81011f0Ssbehera #ifdef NXGE_DEBUG
7445d81011f0Ssbehera static void
7446d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep)
7447d81011f0Ssbehera {
7448d81011f0Ssbehera 	p_nxge_stats_t	statsp;
7449d81011f0Ssbehera 	uint8_t		xcvr_portn;
7450d81011f0Ssbehera 	p_mii_regs_t	mii_regs;
7451d81011f0Ssbehera 	mii_bmcr_t	bmcr;
7452d81011f0Ssbehera 	mii_bmsr_t	bmsr;
7453d81011f0Ssbehera 	mii_idr1_t	idr1;
7454d81011f0Ssbehera 	mii_idr2_t	idr2;
7455d81011f0Ssbehera 	mii_mode_control_stat_t	mode;
7456678453a8Sspeer 	p_nxge_param_t	param_arr;
7457d81011f0Ssbehera 
7458d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
7459d81011f0Ssbehera 
7460d81011f0Ssbehera 	statsp = nxgep->statsp;
7461d81011f0Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
7462d81011f0Ssbehera 
7463d81011f0Ssbehera 	mii_regs = NULL;
7464d81011f0Ssbehera 
7465d81011f0Ssbehera #if defined(__i386)
7466d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7467d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
7468d81011f0Ssbehera #else
7469d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
7470d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
7471d81011f0Ssbehera #endif
7472d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7473d81011f0Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
7474d81011f0Ssbehera 	    xcvr_portn, bmcr.value));
7475d81011f0Ssbehera 
7476d81011f0Ssbehera #if defined(__i386)
7477d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7478d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7479d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
7480d81011f0Ssbehera #else
7481d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7482d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7483d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
7484d81011f0Ssbehera #endif
7485d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7486d81011f0Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
7487d81011f0Ssbehera 	    xcvr_portn, bmsr.value));
7488d81011f0Ssbehera 
7489d81011f0Ssbehera #if defined(__i386)
7490d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7491d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7492d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
7493d81011f0Ssbehera #else
7494d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7495d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7496d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
7497d81011f0Ssbehera #endif
7498d81011f0Ssbehera 
7499d81011f0Ssbehera 
7500d81011f0Ssbehera #if defined(__i386)
7501d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7502d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7503d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
7504d81011f0Ssbehera #else
7505d81011f0Ssbehera 	(void) nxge_mii_read(nxgep,
7506d81011f0Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
7507d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
7508d81011f0Ssbehera #endif
7509d81011f0Ssbehera 
7510d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7511d81011f0Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
7512d81011f0Ssbehera 	    xcvr_portn, idr1.value));
7513d81011f0Ssbehera 
7514d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7515d81011f0Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
7516d81011f0Ssbehera 	    xcvr_portn, idr2.value));
7517d81011f0Ssbehera 
7518d81011f0Ssbehera 	mode.value = 0;
75196b438925Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
7520d81011f0Ssbehera 
7521d81011f0Ssbehera #if defined(__i386)
7522d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7523d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
7524d81011f0Ssbehera 
7525d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7526d81011f0Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
7527d81011f0Ssbehera #else
7528d81011f0Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
7529d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
7530d81011f0Ssbehera 
7531d81011f0Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
7532d81011f0Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
7533d81011f0Ssbehera #endif
7534d81011f0Ssbehera 
7535d81011f0Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7536d81011f0Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
7537d81011f0Ssbehera 	    xcvr_portn, mode.value));
7538d81011f0Ssbehera }
7539d81011f0Ssbehera #endif
7540