xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 9599:326809db8118)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
229232SMichael.Speer@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #include <sys/nxge/nxge_impl.h>
273859Sml29623 #include <sys/nxge/nxge_mac.h>
286495Sspeer #include <sys/nxge/nxge_hio.h>
293859Sml29623 
304693Stm144005 #define	LINK_MONITOR_PERIOD	(1000 * 1000)
314693Stm144005 #define	LM_WAIT_MULTIPLIER	8
324693Stm144005 
336075Ssbehera #define	SERDES_RDY_WT_INTERVAL	50
346075Ssbehera #define	MAX_SERDES_RDY_RETRIES	10
356075Ssbehera 
366835Syc148097 #define	TN1010_SPEED_1G		1
376835Syc148097 #define	TN1010_SPEED_10G	0
386835Syc148097 #define	TN1010_AN_IN_PROG	0	/* Auto negotiation in progress */
396835Syc148097 #define	TN1010_AN_COMPLETE	1
406835Syc148097 #define	TN1010_AN_RSVD		2
416835Syc148097 #define	TN1010_AN_FAILED	3
426835Syc148097 
433859Sml29623 extern uint32_t nxge_no_link_notify;
444732Sdavemq extern boolean_t nxge_no_msg;
453859Sml29623 extern uint32_t nxge_lb_dbg;
463859Sml29623 extern boolean_t nxge_jumbo_enable;
476028Ssbehera extern uint32_t nxge_jumbo_mtu;
483859Sml29623 
496495Sspeer 
504693Stm144005 typedef enum {
514693Stm144005 	CHECK_LINK_RESCHEDULE,
524693Stm144005 	CHECK_LINK_STOP
534693Stm144005 } check_link_state_t;
544693Stm144005 
554693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *);
564693Stm144005 
573859Sml29623 /*
583859Sml29623  * Ethernet broadcast address definition.
593859Sml29623  */
603859Sml29623 static ether_addr_st etherbroadcastaddr =
613859Sml29623 				{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
624732Sdavemq /*
634732Sdavemq  * Ethernet zero address definition.
644732Sdavemq  */
654185Sspeer static ether_addr_st etherzeroaddr =
664185Sspeer 				{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
674732Sdavemq /*
684732Sdavemq  * Supported chip types
694732Sdavemq  */
706604Ssbehera static uint32_t nxge_supported_cl45_ids[] = {
716604Ssbehera 	BCM8704_DEV_ID,
726604Ssbehera 	MARVELL_88X_201X_DEV_ID,
736835Syc148097 	BCM8706_DEV_ID,
746835Syc148097 	TN1010_DEV_ID
756604Ssbehera };
766604Ssbehera 
776909Sml29623 static uint32_t nxge_supported_cl22_ids[] = {
786909Sml29623     BCM5464R_PHY_ID,
796909Sml29623     BCM5482_PHY_ID
806909Sml29623 };
814732Sdavemq 
824732Sdavemq #define	NUM_CLAUSE_45_IDS	(sizeof (nxge_supported_cl45_ids) /	\
834732Sdavemq 				sizeof (uint32_t))
844732Sdavemq #define	NUM_CLAUSE_22_IDS	(sizeof (nxge_supported_cl22_ids) /	\
854732Sdavemq 				sizeof (uint32_t))
864732Sdavemq /*
874732Sdavemq  * static functions
884732Sdavemq  */
894977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
904977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
914977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
924732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
935572Ssbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
944732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
954732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
964732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
974732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
984732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
994732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
1004732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
1014732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
1024732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
1034732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t);
1044732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t);
1054732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
1065572Ssbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
1075572Ssbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
1084732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
1094732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t);
1106835Syc148097 static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
1116604Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
1126835Syc148097 static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
1136835Syc148097 	uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
1146835Syc148097 static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
1156835Syc148097 static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
1166835Syc148097 static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
1176835Syc148097 	nxge_link_state_t *link_up);
1186835Syc148097 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
1196835Syc148097 static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
1206835Syc148097 
1216835Syc148097 nxge_status_t nxge_mac_init(p_nxge_t);
1226835Syc148097 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
1236835Syc148097 
1246835Syc148097 #ifdef NXGE_DEBUG
1256835Syc148097 static void nxge_mii_dump(p_nxge_t);
1266835Syc148097 static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
1276835Syc148097 static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
1286835Syc148097 #endif
1294732Sdavemq 
1304732Sdavemq /*
1314732Sdavemq  * xcvr tables for supported transceivers
1324732Sdavemq  */
1334732Sdavemq 
1346835Syc148097 /*
1356835Syc148097  * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
1366835Syc148097  * The Teranetics TN1010 based copper XAUI card can also be used
1376835Syc148097  * on N2-NIU systems in 10G mode, but it uses its own table
1386835Syc148097  * nxge_n2_10G_tn1010_table below.
1396835Syc148097  */
1404977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = {
1414732Sdavemq 	nxge_n2_serdes_init,
1424732Sdavemq 	nxge_10G_xcvr_init,
1434732Sdavemq 	nxge_10G_link_intr_stop,
1444732Sdavemq 	nxge_10G_link_intr_start,
1454732Sdavemq 	nxge_check_10g_link,
1465572Ssbehera 	PCS_XCVR
1474732Sdavemq };
1484732Sdavemq 
1496835Syc148097 /*
1506835Syc148097  * For the Teranetics TN1010 based copper XAUI card
1516835Syc148097  */
1526835Syc148097 static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
1536835Syc148097 	nxge_n2_serdes_init,		/* Handle both 1G and 10G */
1546835Syc148097 	nxge_tn1010_xcvr_init,		/* Handle both 1G and 10G */
1556835Syc148097 	nxge_10G_link_intr_stop,
1566835Syc148097 	nxge_10G_link_intr_start,
1576835Syc148097 	nxge_check_tn1010_link,		/* Will figure out speed */
1586835Syc148097 	XPCS_XCVR
1596835Syc148097 };
1606835Syc148097 
1614977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = {
1624977Sraghus 	nxge_n2_serdes_init,
1634977Sraghus 	nxge_1G_xcvr_init,
1644977Sraghus 	nxge_1G_fiber_link_intr_stop,
1654977Sraghus 	nxge_1G_fiber_link_intr_start,
1664977Sraghus 	nxge_check_mii_link,
1675572Ssbehera 	PCS_XCVR
1684977Sraghus };
1694977Sraghus 
1706835Syc148097 static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
1716835Syc148097 	nxge_n2_serdes_init,
1726835Syc148097 	nxge_tn1010_xcvr_init,
1736835Syc148097 	nxge_1G_fiber_link_intr_stop,	/* TN1010 is a Cu PHY, but it uses */
1746835Syc148097 	nxge_1G_fiber_link_intr_start,	/* PCS for 1G, so call fiber func */
1756835Syc148097 	nxge_check_tn1010_link,
1766835Syc148097 	PCS_XCVR
1776835Syc148097 };
1786835Syc148097 
1796835Syc148097 static nxge_xcvr_table_t nxge_10G_tn1010_table = {
1806835Syc148097 	nxge_neptune_10G_serdes_init,
1816835Syc148097 	nxge_tn1010_xcvr_init,
1826835Syc148097 	nxge_10G_link_intr_stop,
1836835Syc148097 	nxge_10G_link_intr_start,
1846835Syc148097 	nxge_check_tn1010_link,
1856835Syc148097 	XPCS_XCVR
1866835Syc148097 };
1876835Syc148097 
1886835Syc148097 static nxge_xcvr_table_t nxge_1G_tn1010_table = {
1896835Syc148097 	nxge_1G_serdes_init,
1906835Syc148097 	nxge_tn1010_xcvr_init,
1916835Syc148097 	nxge_1G_fiber_link_intr_stop,
1926835Syc148097 	nxge_1G_fiber_link_intr_start,
1936835Syc148097 	nxge_check_tn1010_link,
1946835Syc148097 	PCS_XCVR
1956835Syc148097 };
1966835Syc148097 
1974732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = {
1984732Sdavemq 	nxge_neptune_10G_serdes_init,
1994732Sdavemq 	nxge_10G_xcvr_init,
2004732Sdavemq 	nxge_10G_link_intr_stop,
2014732Sdavemq 	nxge_10G_link_intr_start,
2024732Sdavemq 	nxge_check_10g_link,
2035572Ssbehera 	PCS_XCVR
2044732Sdavemq };
2054732Sdavemq 
2064732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = {
2074732Sdavemq 	NULL,
2084732Sdavemq 	nxge_1G_xcvr_init,
2094732Sdavemq 	nxge_1G_copper_link_intr_stop,
2104732Sdavemq 	nxge_1G_copper_link_intr_start,
2114732Sdavemq 	nxge_check_mii_link,
2125572Ssbehera 	INT_MII_XCVR
2134732Sdavemq };
2144732Sdavemq 
2156835Syc148097 /* This table is for Neptune portmode == PORT_1G_SERDES cases */
2164732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = {
2174732Sdavemq 	nxge_1G_serdes_init,
2184732Sdavemq 	nxge_1G_xcvr_init,
2194732Sdavemq 	nxge_1G_fiber_link_intr_stop,
2204732Sdavemq 	nxge_1G_fiber_link_intr_start,
2214732Sdavemq 	nxge_check_mii_link,
2225572Ssbehera 	PCS_XCVR
2234732Sdavemq };
2244732Sdavemq 
2254732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = {
2264732Sdavemq 	nxge_neptune_10G_serdes_init,
2274732Sdavemq 	NULL,
2284732Sdavemq 	NULL,
2294732Sdavemq 	NULL,
2304977Sraghus 	NULL,
2315572Ssbehera 	PCS_XCVR
2324732Sdavemq };
2333859Sml29623 
2346835Syc148097 /*
2356835Syc148097  * NXGE_PORT_TN1010 is defined as,
2366835Syc148097  *      NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
2376835Syc148097  *	= 0 | 5 << 16 = 0x50000
2386835Syc148097  *
2396835Syc148097  * So NEPTUNE_2_TN1010 =
2406835Syc148097  *      (NXGE_PORT_TN1010 |
2416835Syc148097  *      (NXGE_PORT_TN1010 << 4) |
2426835Syc148097  *      (NXGE_PORT_NONE << 8) |
2436835Syc148097  *      (NXGE_PORT_NONE << 12)),
2446835Syc148097  *      = 0x50000 | (0x50000 << 4)
2456835Syc148097  *	= 0x550000
2466835Syc148097  *
2476835Syc148097  * This function partitions nxgep->nxge_hw_p->niu_type (which may have
2486835Syc148097  * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
2496835Syc148097  * = 0x50000
2506835Syc148097  */
2516835Syc148097 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
2526835Syc148097 {
2536835Syc148097 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
2546835Syc148097 
2556835Syc148097 	if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
2566835Syc148097 	    & NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
2576835Syc148097 		return (B_TRUE);
2586835Syc148097 	} else {
2596835Syc148097 		return (B_FALSE);
2606835Syc148097 	}
2616835Syc148097 }
2626835Syc148097 
2636835Syc148097 
2646835Syc148097 /*
2656835Syc148097  * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
2666835Syc148097  * serial EEPROM or VPD if possible.  Note that not all systems could get
2676835Syc148097  * the portmode information by calling this function.  For example, the
2686835Syc148097  * Maramba system figures out the portmode information by calling function
2696835Syc148097  * nxge_setup_xcvr_table.
2706835Syc148097  */
2714977Sraghus nxge_status_t
2724977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep)
2734977Sraghus {
2744977Sraghus 	nxge_status_t status = NXGE_OK;
2754977Sraghus 	char *phy_type;
2764977Sraghus 	char *prop_val;
2776835Syc148097 	uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
278*9599Stc99174@train 	uint32_t	val;
279*9599Stc99174@train 	npi_status_t	rs;
280*9599Stc99174@train 
281*9599Stc99174@train 	/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
282*9599Stc99174@train 	if (nxgep->mac.portmode == PORT_10G_SERDES &&
283*9599Stc99174@train 	    nxgep->statsp->mac_stats.link_up) {
284*9599Stc99174@train 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
285*9599Stc99174@train 		return (status);
286*9599Stc99174@train 	}
2874977Sraghus 
2884977Sraghus 	nxgep->mac.portmode = 0;
2895572Ssbehera 	nxgep->xcvr_addr = 0;
2905572Ssbehera 
2915572Ssbehera 	/*
2925572Ssbehera 	 * First check for hot swappable phy property.
2935572Ssbehera 	 */
2945572Ssbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
2955572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2965572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2975572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
2985572Ssbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
2995572Ssbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3005572Ssbehera 	    "hot-swappable-phy") == 1) {
3015572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3025572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3035572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
3045572Ssbehera 	} else if (nxgep->niu_type == N2_NIU &&
3055572Ssbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
3065572Ssbehera 	    "hot-swappable-phy") == 1) {
3075572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
3085572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3095572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3105572Ssbehera 	}
3115572Ssbehera 
3125572Ssbehera 	/*
3135572Ssbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3145572Ssbehera 	 */
3155572Ssbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3165572Ssbehera 		nxgep->hot_swappable_phy = B_TRUE;
3175572Ssbehera 		/*
3185572Ssbehera 		 * If this is the 2nd NIU port, then check 2 addresses
3195572Ssbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
3205572Ssbehera 		 * (in the eval board) or 20 (in the P0 board).
3215572Ssbehera 		 */
3225572Ssbehera 		if (portn == 1) {
3235572Ssbehera 			if (nxge_is_phy_present(nxgep,
3246835Syc148097 			    ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID,
3255572Ssbehera 			    BCM_PHY_ID_MASK)) {
3265572Ssbehera 				nxgep->xcvr_addr =
3276835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR;
3285572Ssbehera 				goto found_phy;
3295572Ssbehera 			}
3305572Ssbehera 		}
3315572Ssbehera 		if (nxge_is_phy_present(nxgep,
3326835Syc148097 		    GOA_CLAUSE45_PORT_ADDR_BASE + portn,
3335572Ssbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
3346835Syc148097 			nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE +
3355572Ssbehera 			    portn;
3365572Ssbehera 			goto found_phy;
3375572Ssbehera 		}
3385572Ssbehera 
3395572Ssbehera 		nxgep->phy_absent = B_TRUE;
340*9599Stc99174@train 
341*9599Stc99174@train 		/* Check Serdes link to detect Opus NEM */
342*9599Stc99174@train 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
343*9599Stc99174@train 		    XPCS_REG_STATUS, &val);
344*9599Stc99174@train 
345*9599Stc99174@train 		if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
346*9599Stc99174@train 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
347*9599Stc99174@train 			nxgep->mac.portmode = PORT_10G_SERDES;
348*9599Stc99174@train 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
349*9599Stc99174@train 			    "HSP 10G Serdes FOUND!!"));
350*9599Stc99174@train 		}
3515572Ssbehera 		goto check_phy_done;
3525572Ssbehera found_phy:
3535572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3545572Ssbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3555572Ssbehera 		nxgep->phy_absent = B_FALSE;
3565572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3575572Ssbehera 		    "found for hot swappable phy"));
3585572Ssbehera check_phy_done:
3595572Ssbehera 		return (status);
3605572Ssbehera 	}
3615572Ssbehera 
3626835Syc148097 	/* Get phy-type property (May have been set by nxge.conf) */
3634977Sraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3644977Sraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3654977Sraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3664977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3674977Sraghus 		    "found  conf file: phy-type %s", prop_val));
3684977Sraghus 		if (strcmp("xgsd", prop_val) == 0) {
3694977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3704977Sraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3714977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3724977Sraghus 			    "found: 10G Serdes"));
3734977Sraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3744977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3754977Sraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3764977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3774977Sraghus 		} else if (strcmp("mif", prop_val) == 0) {
3784977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3794977Sraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3804977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3814977Sraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3824977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3834977Sraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3844977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
3856075Ssbehera 		} else if (strcmp("xgf", prop_val) == 0) {
3866835Syc148097 			/*
3876835Syc148097 			 * Before OBP supports new phy-type property
3886835Syc148097 			 * value "xgc", the 10G copper XAUI may carry
3896835Syc148097 			 * "xgf" instead of "xgc". If the OBP is
3906835Syc148097 			 * upgraded to a newer version which supports
3916835Syc148097 			 * "xgc", then the TN1010 related code in this
3926835Syc148097 			 * "xgf" case will not be used anymore.
3936835Syc148097 			 */
3946835Syc148097 			if (nxge_is_tn1010_phy(nxgep)) {
3956835Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
3966835Syc148097 				    != NXGE_OK) {
3976835Syc148097 					return (status);
3986835Syc148097 				}
3996835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4006835Syc148097 			} else {  /* For Fiber XAUI */
4016835Syc148097 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4026835Syc148097 				nxgep->mac.portmode = PORT_10G_FIBER;
4036835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4046835Syc148097 				    "10G Fiber Xcvr"));
4056835Syc148097 			}
4066835Syc148097 		} else if (strcmp("xgc", prop_val) == 0) {
4076835Syc148097 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
4086835Syc148097 				return (status);
4096835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4104977Sraghus 		}
4114977Sraghus 
4124977Sraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
4134977Sraghus 		    "phy-type", prop_val);
4144977Sraghus 		ddi_prop_free(prop_val);
4154977Sraghus 
4164977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4174977Sraghus 		    "Got phy type [0x%x] from conf file",
4184977Sraghus 		    nxgep->mac.portmode));
4194977Sraghus 
4204977Sraghus 		return (NXGE_OK);
4214977Sraghus 	}
4225572Ssbehera 
4235572Ssbehera 	/* Get phy-type property from OBP */
4244977Sraghus 	if (nxgep->niu_type == N2_NIU) {
4254977Sraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4264977Sraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4274977Sraghus 			if (strcmp("xgf", prop_val) == 0) {
4286835Syc148097 				/*
4296835Syc148097 				 * Before OBP supports new phy-type property
4306835Syc148097 				 * value "xgc", the 10G copper XAUI may carry
4316835Syc148097 				 * "xgf" instead of "xgc". If the OBP is
4326835Syc148097 				 * upgraded to a newer version which supports
4336835Syc148097 				 * "xgc", then the TN1010 related code in this
4346835Syc148097 				 * "xgf" case will not be used anymore.
4356835Syc148097 				 */
4366835Syc148097 				if (nxge_is_tn1010_phy(nxgep)) {
4376835Syc148097 					if ((status =
4386835Syc148097 					    nxge_set_tn1010_param(nxgep))
4396835Syc148097 					    != NXGE_OK) {
4406835Syc148097 						return (status);
4416835Syc148097 					}
4426835Syc148097 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4436835Syc148097 					    "TN1010 Xcvr"));
4446835Syc148097 				} else {  /* For Fiber XAUI */
4456835Syc148097 					nxgep->statsp->mac_stats.xcvr_inuse
4466835Syc148097 					    = XPCS_XCVR;
4476835Syc148097 					nxgep->mac.portmode = PORT_10G_FIBER;
4486835Syc148097 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4496835Syc148097 					    "10G Fiber Xcvr"));
4506835Syc148097 				}
4514977Sraghus 			} else if (strcmp("mif", prop_val) == 0) {
4524977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4534977Sraghus 				    INT_MII_XCVR;
4544977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4554977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4564977Sraghus 				    "1G Copper Xcvr"));
4574977Sraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4584977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4594977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4604977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4614977Sraghus 				    "1G Fiber Xcvr"));
4624977Sraghus 			} else if (strcmp("xgc", prop_val) == 0) {
4636835Syc148097 				status = nxge_set_tn1010_param(nxgep);
4646835Syc148097 				if (status != NXGE_OK)
4656835Syc148097 					return (status);
4666835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4674977Sraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4684977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4694977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4704977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4714977Sraghus 				    "OBP: 10G Serdes"));
4724977Sraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4734977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4744977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4754977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4764977Sraghus 				    "OBP: 1G Serdes"));
4774977Sraghus 			} else {
4784977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4794977Sraghus 				    "Unknown phy-type: %s", prop_val));
4804977Sraghus 				ddi_prop_free(prop_val);
4814977Sraghus 				return (NXGE_ERROR);
4824977Sraghus 			}
4834977Sraghus 			status = NXGE_OK;
4844977Sraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4854977Sraghus 			    nxgep->dip, "phy-type", prop_val);
4864977Sraghus 			ddi_prop_free(prop_val);
4874977Sraghus 
4884977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4894977Sraghus 			    "Got phy type [0x%x] from OBP",
4904977Sraghus 			    nxgep->mac.portmode));
4914977Sraghus 
4924977Sraghus 			return (status);
4934977Sraghus 		} else {
4944977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4954977Sraghus 			    "Exiting...phy-type property not found"));
4964977Sraghus 			return (NXGE_ERROR);
4974977Sraghus 		}
4984977Sraghus 	}
4994977Sraghus 
5004977Sraghus 
5014977Sraghus 	if (!nxgep->vpd_info.present) {
5024977Sraghus 		return (NXGE_OK);
5034977Sraghus 	}
5044977Sraghus 
5054977Sraghus 	if (!nxgep->vpd_info.ver_valid) {
5064977Sraghus 		goto read_seeprom;
5074977Sraghus 	}
5084977Sraghus 
5094977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5104977Sraghus 	    "Reading phy type from expansion ROM"));
5114977Sraghus 	/*
5124977Sraghus 	 * Try to read the phy type from the vpd data read off the
5134977Sraghus 	 * expansion ROM.
5144977Sraghus 	 */
5154977Sraghus 	phy_type = nxgep->vpd_info.phy_type;
5164977Sraghus 
5175196Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
5184977Sraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
5194977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
5205196Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5214977Sraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5224977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
5235196Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5244977Sraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5254977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5265196Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
5276835Syc148097 		status = nxge_set_tn1010_param(nxgep);
5286835Syc148097 		if (status != NXGE_OK) {
5296835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5306835Syc148097 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
5316835Syc148097 			goto read_seeprom;
5326835Syc148097 		}
5335196Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
5345196Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
5355196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
5365196Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
5375196Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
5385196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5394977Sraghus 	} else {
5405196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5414977Sraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5424977Sraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5434977Sraghus 		goto read_seeprom;
5444977Sraghus 	}
5454977Sraghus 
5464977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5474977Sraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5484977Sraghus 
5494977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5504977Sraghus 	return (status);
5514977Sraghus 
5524977Sraghus read_seeprom:
5534977Sraghus 	/*
5544977Sraghus 	 * read the phy type from the SEEPROM - NCR registers
5554977Sraghus 	 */
5564977Sraghus 	status = nxge_espc_phy_type_get(nxgep);
5574977Sraghus 	if (status != NXGE_OK) {
5584977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5594977Sraghus 		    "Failed to get phy type"));
5604977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5614977Sraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5624977Sraghus 	}
5634977Sraghus 
5644977Sraghus 	return (status);
5654977Sraghus 
5664977Sraghus }
5674977Sraghus 
5684732Sdavemq /* Set up the PHY specific values. */
5694732Sdavemq 
5704732Sdavemq nxge_status_t
5714732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
5724732Sdavemq {
5734732Sdavemq 	nxge_status_t	status = NXGE_OK;
5744732Sdavemq 	uint32_t	port_type;
5754732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5764977Sraghus 	uint32_t	pcs_id = 0;
5774977Sraghus 	uint32_t	pma_pmd_id = 0;
5784977Sraghus 	uint32_t	phy_id = 0;
5795572Ssbehera 	uint16_t	chip_id = 0;
5804732Sdavemq 
5814732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
5824732Sdavemq 	    portn));
5834732Sdavemq 
5844977Sraghus 	switch (nxgep->niu_type) {
5854977Sraghus 	case N2_NIU:
5864977Sraghus 		switch (nxgep->mac.portmode) {
5874977Sraghus 		case PORT_1G_FIBER:
5884977Sraghus 		case PORT_1G_SERDES:
5894977Sraghus 			nxgep->xcvr = nxge_n2_1G_table;
5905572Ssbehera 			nxgep->xcvr_addr = portn;
5914977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5924977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5934977Sraghus 			    "Serdes"));
5944977Sraghus 			break;
5954977Sraghus 		case PORT_10G_FIBER:
5964977Sraghus 		case PORT_10G_SERDES:
5974977Sraghus 			nxgep->xcvr = nxge_n2_10G_table;
5985572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5995572Ssbehera 				nxgep->xcvr_addr =
6005572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
6015572Ssbehera 			}
6024977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
6034977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
6044977Sraghus 			    "Serdes"));
6054977Sraghus 			break;
6066835Syc148097 		case PORT_1G_TN1010:
6076835Syc148097 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
6086835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
6096835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6106835Syc148097 			    "TN1010 Copper Xcvr in 1G"));
6116835Syc148097 			break;
6126835Syc148097 		case PORT_10G_TN1010:
6136835Syc148097 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
6146835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
6156835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
6166835Syc148097 			    "TN1010 Copper Xcvr in 10G"));
6176835Syc148097 			break;
6185572Ssbehera 		case PORT_HSP_MODE:
6195572Ssbehera 			nxgep->xcvr = nxge_n2_10G_table;
6205572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6215572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6225572Ssbehera 			    "Swappable Xcvr (not present)"));
6235572Ssbehera 			break;
6244977Sraghus 		default:
6254977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6264977Sraghus 			    "<== nxge_setup_xcvr_table: "
6274977Sraghus 			    "Unable to determine NIU portmode"));
6284977Sraghus 			return (NXGE_ERROR);
6294977Sraghus 		}
6304977Sraghus 		break;
6314977Sraghus 	default:
6324977Sraghus 		if (nxgep->mac.portmode == 0) {
6334977Sraghus 			/*
6344977Sraghus 			 * Would be the case for platforms like Maramba
6354977Sraghus 			 * in which the phy type could not be got from conf
6364977Sraghus 			 * file, OBP, VPD or Serial PROM.
6374977Sraghus 			 */
6384977Sraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6394977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6404977Sraghus 				    "<== nxge_setup_xcvr_table:"
6414977Sraghus 				    " Invalid Neptune type [0x%x]",
6424977Sraghus 				    nxgep->niu_type));
6434977Sraghus 				return (NXGE_ERROR);
6444977Sraghus 			}
6454977Sraghus 
6464977Sraghus 			port_type = nxgep->niu_type >>
6474977Sraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
6484977Sraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6494977Sraghus 
6504977Sraghus 			switch (port_type) {
6514977Sraghus 
6524977Sraghus 			case NXGE_PORT_1G_COPPER:
6534977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
6544977Sraghus 				break;
6554977Sraghus 			case NXGE_PORT_10G_COPPER:
6564977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6574977Sraghus 				break;
6584977Sraghus 			case NXGE_PORT_1G_FIBRE:
6594977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6604977Sraghus 				break;
6614977Sraghus 			case NXGE_PORT_10G_FIBRE:
6624977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6634977Sraghus 				break;
6644977Sraghus 			case NXGE_PORT_1G_SERDES:
6654977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6664977Sraghus 				break;
6674977Sraghus 			case NXGE_PORT_10G_SERDES:
6684977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6694977Sraghus 				break;
6706835Syc148097 			/* Ports 2 and 3 of Alonso or ARTM */
6714977Sraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6724977Sraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6734977Sraghus 				break;
6746835Syc148097 			case NXGE_PORT_TN1010:
6756835Syc148097 				/*
6766835Syc148097 				 * If this port uses the TN1010 copper
6776835Syc148097 				 * PHY, then its speed is not known yet
6786835Syc148097 				 * because nxge_scan_ports_phy could only
6796835Syc148097 				 * figure out the vendor of the PHY but
6806835Syc148097 				 * not its speed. nxge_set_tn1010_param
6816835Syc148097 				 * will read the PHY speed and set
6826835Syc148097 				 * portmode accordingly.
6836835Syc148097 				 */
6846835Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
6856835Syc148097 				    != NXGE_OK) {
6866835Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6876835Syc148097 					    "nxge_set_tn1010_param failed"));
6886835Syc148097 					return (status);
6896835Syc148097 				}
6906835Syc148097 				break;
6914977Sraghus 			default:
6924977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6934977Sraghus 				    "<== nxge_setup_xcvr_table: "
6944977Sraghus 				    "Unknown port-type: 0x%x", port_type));
6954977Sraghus 				return (NXGE_ERROR);
6964977Sraghus 			}
6974977Sraghus 		}
6984977Sraghus 
6996835Syc148097 		/*
7006835Syc148097 		 * Above switch has figured out nxge->mac.portmode, now set
7016835Syc148097 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
7026835Syc148097 		 * to portmode.
7036835Syc148097 		 */
7044977Sraghus 		switch (nxgep->mac.portmode) {
7054977Sraghus 		case PORT_1G_COPPER:
7064977Sraghus 		case PORT_1G_RGMII_FIBER:
7074732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
7085572Ssbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7094732Sdavemq 			/*
7104732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
7114732Sdavemq 			 * swapped with ethernet port number. This is
7124977Sraghus 			 * designed for better signal integrity in
7134977Sraghus 			 * routing. This is also the case for the
7144977Sraghus 			 * on-board Neptune copper ports on the Maramba
7154977Sraghus 			 * platform.
7164732Sdavemq 			 */
7174977Sraghus 			switch (nxgep->platform_type) {
7184977Sraghus 			case P_NEPTUNE_ATLAS_4PORT:
7194977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
7204977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
7214977Sraghus 				switch (portn) {
7224977Sraghus 				case 0:
7235572Ssbehera 					nxgep->xcvr_addr += 3;
7244977Sraghus 					break;
7254977Sraghus 				case 1:
7265572Ssbehera 					nxgep->xcvr_addr += 1;
7274977Sraghus 					break;
7284977Sraghus 				case 2:
7295572Ssbehera 					nxgep->xcvr_addr -= 1;
7304977Sraghus 					break;
7314977Sraghus 				case 3:
7325572Ssbehera 					nxgep->xcvr_addr -= 3;
7334977Sraghus 					break;
7344977Sraghus 				default:
7354977Sraghus 					return (NXGE_ERROR);
7364977Sraghus 				}
7374732Sdavemq 				break;
7384732Sdavemq 			default:
7394977Sraghus 				break;
7404732Sdavemq 			}
7415196Ssbehera 
7424977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7434977Sraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7444977Sraghus 			    "Copper" : "RGMII Fiber"));
7454732Sdavemq 			break;
7466835Syc148097 
7474977Sraghus 		case PORT_10G_COPPER:
7484732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
7494732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
7504732Sdavemq 			break;
7516835Syc148097 
7526835Syc148097 		case PORT_1G_TN1010:
7536835Syc148097 			nxgep->xcvr = nxge_1G_tn1010_table;
7546835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7556835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7566835Syc148097 			    "1G TN1010 copper Xcvr"));
7576835Syc148097 			break;
7586835Syc148097 
7596835Syc148097 		case PORT_10G_TN1010:
7606835Syc148097 			nxgep->xcvr = nxge_10G_tn1010_table;
7616835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7626835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7636835Syc148097 			    "10G TN1010 copper Xcvr"));
7646835Syc148097 			break;
7656835Syc148097 
7664977Sraghus 		case PORT_1G_FIBER:
7674977Sraghus 		case PORT_1G_SERDES:
7684732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7695572Ssbehera 			nxgep->xcvr_addr = portn;
7704977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7714977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7724977Sraghus 			    "Fiber" : "Serdes"));
7734732Sdavemq 			break;
7744977Sraghus 		case PORT_10G_FIBER:
7754977Sraghus 		case PORT_10G_SERDES:
7764732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7775572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7785572Ssbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7795572Ssbehera 			    "nxgep->xcvr_addr = [%d]",
7805572Ssbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7815572Ssbehera 			    nxgep->xcvr_addr));
7825572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7835572Ssbehera 				nxgep->xcvr_addr =
7845572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7855572Ssbehera 			}
7864977Sraghus 			switch (nxgep->platform_type) {
7874977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
7884977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
7894732Sdavemq 				/*
7904732Sdavemq 				 * Switch off LED for corresponding copper
7914732Sdavemq 				 * port
7924732Sdavemq 				 */
7934732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7944977Sraghus 				break;
7954977Sraghus 			default:
7964977Sraghus 				break;
7974732Sdavemq 			}
7984977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
7994977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
8004977Sraghus 			    "Fiber" : "Serdes"));
8014732Sdavemq 			break;
8025572Ssbehera 
8035572Ssbehera 		case PORT_HSP_MODE:
8045572Ssbehera 			nxgep->xcvr = nxge_10G_fiber_table;
8055572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
8065572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
8075572Ssbehera 			    "Swappable Xcvr (not present)"));
8085572Ssbehera 			break;
8094732Sdavemq 		default:
8104732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8114732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
8124732Sdavemq 			return (NXGE_ERROR);
8134732Sdavemq 		}
8144732Sdavemq 	}
8154732Sdavemq 
8165572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
8176604Ssbehera 		uint32_t pma_pmd_id;
8186604Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
8196604Ssbehera 		    nxgep->xcvr_addr);
8206604Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
8216604Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
8226604Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8236604Ssbehera 			    "nxge_setup_xcvr_table: "
8246604Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
8256604Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8265572Ssbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8275572Ssbehera 		    &chip_id)) == NXGE_OK) {
8285572Ssbehera 
8295572Ssbehera 			switch (chip_id) {
8305572Ssbehera 			case BCM8704_CHIP_ID:
8315572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8325572Ssbehera 				    "nxge_setup_xcvr_table: "
8335572Ssbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8345572Ssbehera 				    chip_id));
8355572Ssbehera 				break;
8365572Ssbehera 			case BCM8706_CHIP_ID:
8375572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8385572Ssbehera 				    "nxge_setup_xcvr_table: "
8395572Ssbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8405572Ssbehera 				    chip_id));
8415572Ssbehera 				break;
8425572Ssbehera 			default:
8435572Ssbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8445572Ssbehera 				    "nxge_setup_xcvr_table: "
8455572Ssbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8465572Ssbehera 				    chip_id));
8475572Ssbehera 				break;
8485572Ssbehera 			}
8495572Ssbehera 		}
8505572Ssbehera 	}
8515572Ssbehera 
8524732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8535572Ssbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8545572Ssbehera 	nxgep->chip_id = chip_id;
8554977Sraghus 
8564977Sraghus 	/*
8574977Sraghus 	 * Get the actual device ID value returned by MDIO read.
8584977Sraghus 	 */
8594977Sraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8604977Sraghus 
8615572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8624977Sraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8634977Sraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8644977Sraghus 	} else {
8655572Ssbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8664977Sraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8674977Sraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8684977Sraghus 		} else {
8694977Sraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8705572Ssbehera 			    nxgep->xcvr_addr);
8714977Sraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8724977Sraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8734977Sraghus 			}
8744977Sraghus 		}
8754977Sraghus 	}
8764977Sraghus 
8774732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
8784732Sdavemq 
8794977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
8807801SSantwona.Behera@Sun.COM 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
8815572Ssbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8824977Sraghus 
8834732Sdavemq 	return (status);
8844732Sdavemq }
8854732Sdavemq 
8863859Sml29623 /* Initialize the entire MAC and physical layer */
8873859Sml29623 
8883859Sml29623 nxge_status_t
8893859Sml29623 nxge_mac_init(p_nxge_t nxgep)
8903859Sml29623 {
8913859Sml29623 	uint8_t			portn;
8923859Sml29623 	nxge_status_t		status = NXGE_OK;
8933859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8943859Sml29623 
8953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
8963859Sml29623 
8973859Sml29623 	nxgep->mac.portnum = portn;
8983859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
8993859Sml29623 
9003859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
9013859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
9023859Sml29623 
9036835Syc148097 
9043859Sml29623 	/* Initialize XIF to configure a network mode */
9053859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
9063859Sml29623 		goto fail;
9073859Sml29623 	}
9083859Sml29623 
9093859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
9103859Sml29623 		goto fail;
9113859Sml29623 	}
9123859Sml29623 
9133859Sml29623 	/* Initialize TX and RX MACs */
9143859Sml29623 	/*
9153859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
9163859Sml29623 	 */
9173859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
9183859Sml29623 		goto fail;
9193859Sml29623 
9203859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
9213859Sml29623 		goto fail;
9223859Sml29623 
9233859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
9243859Sml29623 		goto fail;
9253859Sml29623 
9263859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
9273859Sml29623 		goto fail;
9283859Sml29623 
9293859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
9303859Sml29623 		goto fail;
9313859Sml29623 
9329232SMichael.Speer@Sun.COM 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
9339232SMichael.Speer@Sun.COM 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
9349232SMichael.Speer@Sun.COM 			goto fail;
9359232SMichael.Speer@Sun.COM 	}
9363859Sml29623 
9375553Smisaki 	/* Initialize MAC control configuration */
9385553Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
9395553Smisaki 		goto fail;
9405553Smisaki 	}
9415553Smisaki 
9423859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
9433859Sml29623 
9445196Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
9455196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
9465196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
9476835Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
9485196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
9495196Ssbehera 	    ((portn == 0) || (portn == 1))) {
9505196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9515196Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
9525196Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
9535196Ssbehera 			goto fail;
9545196Ssbehera 		}
9555196Ssbehera 	}
9565196Ssbehera 
9574977Sraghus 
9583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
9593859Sml29623 
9603859Sml29623 	return (NXGE_OK);
9613859Sml29623 fail:
9623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9636929Smisaki 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
9643859Sml29623 	return (status);
9653859Sml29623 }
9663859Sml29623 
9673859Sml29623 /* Initialize the Ethernet Link */
9683859Sml29623 
9693859Sml29623 nxge_status_t
9703859Sml29623 nxge_link_init(p_nxge_t nxgep)
9713859Sml29623 {
9723859Sml29623 	nxge_status_t		status = NXGE_OK;
9734977Sraghus 	nxge_port_mode_t	portmode;
9743859Sml29623 #ifdef	NXGE_DEBUG
9753859Sml29623 	uint8_t			portn;
9763859Sml29623 
9773859Sml29623 	portn = nxgep->mac.portnum;
9783859Sml29623 
9793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
9803859Sml29623 #endif
981*9599Stc99174@train 	/* For Opus NEM, Serdes always needs to be initialized */
9823859Sml29623 
9834977Sraghus 	portmode = nxgep->mac.portmode;
9845572Ssbehera 
9856835Syc148097 	/*
9866835Syc148097 	 * Workaround to get link up in both NIU ports. Some portmodes require
9876835Syc148097 	 * that the xcvr be initialized twice, the first time before calling
9886835Syc148097 	 * nxge_serdes_init.
9896835Syc148097 	 */
9904977Sraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
9916835Syc148097 	    (portmode != PORT_10G_TN1010) &&
9926835Syc148097 	    (portmode != PORT_1G_TN1010) &&
9934977Sraghus 	    (portmode != PORT_1G_SERDES)) {
9944977Sraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
9953859Sml29623 			goto fail;
9964977Sraghus 		}
9973859Sml29623 	}
9986835Syc148097 
9993859Sml29623 	NXGE_DELAY(200000);
10003859Sml29623 	/* Initialize internal serdes */
10013859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
10023859Sml29623 		goto fail;
10033859Sml29623 	NXGE_DELAY(200000);
10043859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
10053859Sml29623 		goto fail;
10063859Sml29623 
10073859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
10083859Sml29623 
10093859Sml29623 	return (NXGE_OK);
10103859Sml29623 
10113859Sml29623 fail:
10126929Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
10136929Smisaki 	    "failed to initialize Ethernet link on port<%d>", portn));
10143859Sml29623 
10153859Sml29623 	return (status);
10163859Sml29623 }
10173859Sml29623 
10183859Sml29623 
10193859Sml29623 /* Initialize the XIF sub-block within the MAC */
10203859Sml29623 
10213859Sml29623 nxge_status_t
10223859Sml29623 nxge_xif_init(p_nxge_t nxgep)
10233859Sml29623 {
10243859Sml29623 	uint32_t		xif_cfg = 0;
10253859Sml29623 	npi_attr_t		ap;
10263859Sml29623 	uint8_t			portn;
10273859Sml29623 	nxge_port_t		portt;
10283859Sml29623 	nxge_port_mode_t	portmode;
10293859Sml29623 	p_nxge_stats_t		statsp;
10303859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
10313859Sml29623 	npi_handle_t		handle;
10323859Sml29623 
10333859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
10343859Sml29623 
10353859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
10363859Sml29623 
10373859Sml29623 	handle = nxgep->npi_handle;
10383859Sml29623 	portmode = nxgep->mac.portmode;
10393859Sml29623 	portt = nxgep->mac.porttype;
10403859Sml29623 	statsp = nxgep->statsp;
10413859Sml29623 
10425196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
10435196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
10446835Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
10455196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
10465196Ssbehera 	    ((portn == 0) || (portn == 1))) {
10475196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10485196Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
10495196Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
10505196Ssbehera 	}
10515196Ssbehera 
10523859Sml29623 	if (portt == PORT_TYPE_XMAC) {
10533859Sml29623 
10543859Sml29623 		/* Setup XIF Configuration for XMAC */
10553859Sml29623 
10563859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
10574977Sraghus 		    (portmode == PORT_10G_COPPER) ||
10586835Syc148097 		    (portmode == PORT_10G_TN1010) ||
1059*9599Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
10604977Sraghus 		    (portmode == PORT_10G_SERDES))
10613859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
10623859Sml29623 
10636835Syc148097 		/* Bypass PCS so that RGMII will be used */
10643859Sml29623 		if (portmode == PORT_1G_COPPER) {
10653859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
10663859Sml29623 		}
10673859Sml29623 
10683859Sml29623 		/* Set MAC Internal Loopback if necessary */
10693859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
10703859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
10713859Sml29623 
10723859Sml29623 		if (statsp->mac_stats.link_speed == 100)
10733859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
10743859Sml29623 
10753859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
10763859Sml29623 
10774977Sraghus 		if ((portmode == PORT_10G_FIBER) ||
10786835Syc148097 		    (portmode == PORT_10G_TN1010) ||
10796835Syc148097 		    (portmode == PORT_1G_TN1010) ||
1080*9599Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
10814977Sraghus 		    (portmode == PORT_10G_SERDES)) {
10826835Syc148097 			/* Assume LED same for 1G and 10G */
10833859Sml29623 			if (statsp->mac_stats.link_up) {
10843859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
10853859Sml29623 			} else {
10863859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
10873859Sml29623 			}
10883859Sml29623 		}
10893859Sml29623 
10903859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
10913859Sml29623 		if (rs != NPI_SUCCESS)
10923859Sml29623 			goto fail;
10933859Sml29623 
10943859Sml29623 		nxgep->mac.xif_config = xif_cfg;
10953859Sml29623 
10963859Sml29623 		/* Set Port Mode */
10973859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
10984977Sraghus 		    (portmode == PORT_10G_COPPER) ||
10996835Syc148097 		    (portmode == PORT_10G_TN1010) ||
1100*9599Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
11014977Sraghus 		    (portmode == PORT_10G_SERDES)) {
11023859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11036929Smisaki 			    MAC_XGMII_MODE, rs);
11043859Sml29623 			if (rs != NPI_SUCCESS)
11053859Sml29623 				goto fail;
11063859Sml29623 			if (statsp->mac_stats.link_up) {
11073859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
11083859Sml29623 					goto fail;
11093859Sml29623 			} else {
11103859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
11113859Sml29623 					goto fail;
11123859Sml29623 			}
11133859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
11144977Sraghus 		    (portmode == PORT_1G_COPPER) ||
11155196Ssbehera 		    (portmode == PORT_1G_SERDES) ||
11166835Syc148097 		    (portmode == PORT_1G_TN1010) ||
11175196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
11185196Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11195196Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
11205196Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
11213859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
11223859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11236929Smisaki 				    MAC_GMII_MODE, rs);
11243859Sml29623 			} else {
11253859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11266929Smisaki 				    MAC_MII_MODE, rs);
11273859Sml29623 			}
11283859Sml29623 			if (rs != NPI_SUCCESS)
11293859Sml29623 				goto fail;
11303859Sml29623 		} else {
11313859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11326929Smisaki 			    "nxge_xif_init: Unknown port mode (%d)"
11336929Smisaki 			    " for port<%d>", portmode, portn));
11343859Sml29623 			goto fail;
11353859Sml29623 		}
11363859Sml29623 
11375196Ssbehera 		/* Enable ATCA mode */
11385196Ssbehera 
11393859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
11403859Sml29623 
11413859Sml29623 		/* Setup XIF Configuration for BMAC */
11423859Sml29623 
11435196Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
11445196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
11453859Sml29623 			if (statsp->mac_stats.link_speed == 100)
11463859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
11473859Sml29623 		}
11483859Sml29623 
11493859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
11503859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
11513859Sml29623 
11523859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
11533859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
11543859Sml29623 
11553859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
11563859Sml29623 
11573859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
11583859Sml29623 		if (rs != NPI_SUCCESS)
11593859Sml29623 			goto fail;
11603859Sml29623 		nxgep->mac.xif_config = xif_cfg;
11613859Sml29623 	}
11623859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
11633859Sml29623 	return (NXGE_OK);
11643859Sml29623 fail:
11653859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11666929Smisaki 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
11673859Sml29623 	return (NXGE_ERROR | rs);
11683859Sml29623 }
11693859Sml29623 
11706835Syc148097 
11716835Syc148097 /*
11726835Syc148097  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
11736835Syc148097  * support loopback like XPCS.
11746835Syc148097  */
11753859Sml29623 nxge_status_t
11763859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
11773859Sml29623 {
11783859Sml29623 	pcs_cfg_t		pcs_cfg;
11793859Sml29623 	uint32_t		val;
11803859Sml29623 	uint8_t			portn;
11813859Sml29623 	nxge_port_mode_t	portmode;
11823859Sml29623 	npi_handle_t		handle;
11833859Sml29623 	p_nxge_stats_t		statsp;
11846835Syc148097 	pcs_ctrl_t		pcs_ctrl;
11853859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
11866835Syc148097 	uint8_t i;
11873859Sml29623 
11883859Sml29623 	handle = nxgep->npi_handle;
11893859Sml29623 	portmode = nxgep->mac.portmode;
11903859Sml29623 	portn = nxgep->mac.portnum;
11913859Sml29623 	statsp = nxgep->statsp;
11923859Sml29623 
11933859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
11943859Sml29623 
11956835Syc148097 	if (portmode == PORT_1G_FIBER ||
11966835Syc148097 	    portmode == PORT_1G_TN1010 ||
11976835Syc148097 	    portmode == PORT_1G_SERDES) {
11986835Syc148097 		if (portmode == PORT_1G_TN1010) {
11996835Syc148097 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
12006835Syc148097 			for (i = 0; i < 6; i ++) {
12016835Syc148097 				if ((rs = npi_mac_pcs_reset(handle, portn))
12026835Syc148097 				    != NPI_SUCCESS) {
12036835Syc148097 					goto fail;
12046835Syc148097 				}
12056835Syc148097 			}
12066835Syc148097 		} else {
12076835Syc148097 			if ((rs = npi_mac_pcs_reset(handle, portn))
12086835Syc148097 			    != NPI_SUCCESS)
12096835Syc148097 				goto fail;
12104977Sraghus 		}
12114977Sraghus 
12123859Sml29623 		/* Initialize port's PCS */
12133859Sml29623 		pcs_cfg.value = 0;
12143859Sml29623 		pcs_cfg.bits.w0.enable = 1;
12153859Sml29623 		pcs_cfg.bits.w0.mask = 1;
12163859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
12173859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
12184977Sraghus 
12194977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12204977Sraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12214977Sraghus 		    portn, pcs_cfg.value));
12226835Syc148097 
12236835Syc148097 		if (portmode == PORT_1G_TN1010) {
12246835Syc148097 			/*
12256835Syc148097 			 * Must disable PCS auto-negotiation when the the driver
12266835Syc148097 			 * is driving the TN1010 based XAUI card  Otherwise the
12276835Syc148097 			 * autonegotiation between the PCS and the TN1010 PCS
12286835Syc148097 			 * will never complete and the Neptune/NIU will not work
12296835Syc148097 			 */
12306835Syc148097 			pcs_ctrl.value = 0;
12316835Syc148097 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
12326835Syc148097 			    pcs_ctrl.value);
12336835Syc148097 		}
12346835Syc148097 	} else if (portmode == PORT_10G_FIBER ||
12356835Syc148097 	    portmode == PORT_10G_COPPER ||
12366835Syc148097 	    portmode == PORT_10G_TN1010 ||
1237*9599Stc99174@train 	    portmode == PORT_HSP_MODE ||
12386835Syc148097 	    portmode == PORT_10G_SERDES) {
12393859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
12403859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
12413859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
12423859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
12433859Sml29623 
12443859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
12453859Sml29623 			goto fail;
12463859Sml29623 
12473859Sml29623 		/* Set XPCS Internal Loopback if necessary */
12483859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12496929Smisaki 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
12503859Sml29623 			goto fail;
12516835Syc148097 
12523859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
12536929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
12543859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
12553859Sml29623 		else
12563859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
12573859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
12586929Smisaki 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
12593859Sml29623 			goto fail;
12603859Sml29623 
12613859Sml29623 		/* Clear descw errors */
12623859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
12636929Smisaki 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
12643859Sml29623 			goto fail;
12653859Sml29623 		/* Clear symbol errors */
12663859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12676929Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
12683859Sml29623 			goto fail;
12693859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12706929Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
12713859Sml29623 			goto fail;
12723859Sml29623 
12735196Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
12745196Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
12755196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12765196Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
12773859Sml29623 		if (portn < 4) {
12783859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
12796929Smisaki 			    PCS_DATAPATH_MODE_MII);
12803859Sml29623 		}
12813859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
12823859Sml29623 			goto fail;
12833859Sml29623 
12843859Sml29623 	} else {
12853859Sml29623 		goto fail;
12863859Sml29623 	}
12873859Sml29623 pass:
12883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
12893859Sml29623 	return (NXGE_OK);
12903859Sml29623 fail:
12913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12926929Smisaki 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
12933859Sml29623 	return (NXGE_ERROR | rs);
12943859Sml29623 }
12953859Sml29623 
12965553Smisaki /*
12975553Smisaki  * Initialize the MAC CTRL sub-block within the MAC
12985553Smisaki  * Only the receive-pause-cap is supported.
12995553Smisaki  */
13005553Smisaki nxge_status_t
13015553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
13025553Smisaki {
13035553Smisaki 	uint8_t			portn;
13045553Smisaki 	nxge_port_t		portt;
13055553Smisaki 	p_nxge_stats_t		statsp;
13065553Smisaki 	npi_handle_t		handle;
13075553Smisaki 	uint32_t		val;
13085553Smisaki 
13095553Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
13105553Smisaki 
13115553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
13125553Smisaki 	    portn));
13135553Smisaki 
13145553Smisaki 	handle = nxgep->npi_handle;
13155553Smisaki 	portt = nxgep->mac.porttype;
13165553Smisaki 	statsp = nxgep->statsp;
13175553Smisaki 
13185553Smisaki 	if (portt == PORT_TYPE_XMAC) {
13196835Syc148097 		/* Reading the current XMAC Config Register for XMAC */
13205553Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
13215553Smisaki 
13225553Smisaki 		/*
13235553Smisaki 		 * Setup XMAC Configuration for XMAC
13245553Smisaki 		 * XMAC only supports receive-pause
13255553Smisaki 		 */
13265553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
13275553Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
13285553Smisaki 				/*
13295553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13305553Smisaki 				 * is 0, enable receive pause.
13315553Smisaki 				 */
13325553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
13335553Smisaki 			} else {
13345553Smisaki 				/*
13355553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13365553Smisaki 				 * is 1, disable receive pause.  Send pause is
13375553Smisaki 				 * not supported.
13385553Smisaki 				 */
13395553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
13405553Smisaki 			}
13415553Smisaki 		} else {
13426439Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13436439Sml29623 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13446439Sml29623 			    portn));
13455553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13466439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13476439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13486439Sml29623 				    "enable pause", portn));
13495553Smisaki 				/*
13505553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13515553Smisaki 				 * is 1, enable receive pause.
13525553Smisaki 				 */
13535553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
13545553Smisaki 			} else {
13555553Smisaki 				/*
13565553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13575553Smisaki 				 * is 0, disable receive pause. Send pause is
13585553Smisaki 				 * not supported
13595553Smisaki 				 */
13606439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13616439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13626439Sml29623 				    "disable pause", portn));
13635553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
13645553Smisaki 			}
13655553Smisaki 		}
13665553Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
13675553Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
13686835Syc148097 		/* Reading the current MAC CTRL Config Register for BMAC */
13695553Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
13705553Smisaki 
13715553Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
13725553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
13735553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13745553Smisaki 				/*
13755553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13765553Smisaki 				 * is 1, disable receive pause. Send pause
13775553Smisaki 				 * is not supported
13785553Smisaki 				 */
13795553Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
13805553Smisaki 			} else {
13815553Smisaki 				/*
13825553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13835553Smisaki 				 * is 0, enable receive pause and disable
13845553Smisaki 				 * send pause.
13855553Smisaki 				 */
13865553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
13875553Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
13885553Smisaki 			}
13895553Smisaki 		} else {
13905553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13915553Smisaki 				/*
13925553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13935553Smisaki 				 * is 1, enable receive pause. Send pause is
13945553Smisaki 				 * not supported.
13955553Smisaki 				 */
13965553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
13975553Smisaki 			} else {
13985553Smisaki 				/*
13995553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
14005553Smisaki 				 * is 0, pause capability is not available in
14015553Smisaki 				 * either direction.
14025553Smisaki 				 */
14035553Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
14046929Smisaki 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
14055553Smisaki 			}
14065553Smisaki 		}
14075553Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
14085553Smisaki 	}
14095553Smisaki 
14105553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
14115553Smisaki 	    portn));
14125553Smisaki 
14135553Smisaki 	return (NXGE_OK);
14145553Smisaki }
14155553Smisaki 
14163859Sml29623 /* Initialize the Internal Serdes */
14173859Sml29623 
14183859Sml29623 nxge_status_t
14193859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
14203859Sml29623 {
14213859Sml29623 	p_nxge_stats_t		statsp;
14223859Sml29623 #ifdef	NXGE_DEBUG
14233859Sml29623 	uint8_t			portn;
14243859Sml29623 #endif
14253859Sml29623 	nxge_status_t		status = NXGE_OK;
14263859Sml29623 
14273859Sml29623 #ifdef	NXGE_DEBUG
14283859Sml29623 	portn = nxgep->mac.portnum;
14293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14304732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
14313859Sml29623 #endif
14323859Sml29623 
14334732Sdavemq 	if (nxgep->xcvr.serdes_init) {
14344732Sdavemq 		statsp = nxgep->statsp;
14354732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
14364732Sdavemq 		if (status != NXGE_OK)
14373859Sml29623 			goto fail;
14384732Sdavemq 		statsp->mac_stats.serdes_inits++;
14393859Sml29623 	}
14403859Sml29623 
14413859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
14424732Sdavemq 	    portn));
14433859Sml29623 
14443859Sml29623 	return (NXGE_OK);
14453859Sml29623 
14463859Sml29623 fail:
14473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14484732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
14494732Sdavemq 	    portn));
14503859Sml29623 
14513859Sml29623 	return (status);
14523859Sml29623 }
14533859Sml29623 
14543859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
14553859Sml29623 
14564732Sdavemq static nxge_status_t
14573859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
14583859Sml29623 {
14593859Sml29623 	uint8_t portn;
14603859Sml29623 	int chan;
14613859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
14624977Sraghus 	esr_ti_cfgpll_l_t pll_sts_l;
14633859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
14643859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
14653859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
14663859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
14674977Sraghus #ifdef NXGE_DEBUG
14684977Sraghus 	esr_ti_testcfg_t cfg;
14694977Sraghus #endif
14703859Sml29623 	esr_ti_testcfg_t test_cfg;
14713859Sml29623 	nxge_status_t status = NXGE_OK;
14723859Sml29623 
14733859Sml29623 	portn = nxgep->mac.portnum;
14743859Sml29623 
14753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
14766929Smisaki 	    portn));
14773859Sml29623 
14783859Sml29623 	tx_cfg_l.value = 0;
14793859Sml29623 	tx_cfg_h.value = 0;
14803859Sml29623 	rx_cfg_l.value = 0;
14813859Sml29623 	rx_cfg_h.value = 0;
14823859Sml29623 	pll_cfg_l.value = 0;
14834977Sraghus 	pll_sts_l.value = 0;
14843859Sml29623 	test_cfg.value = 0;
14853859Sml29623 
14866835Syc148097 	/*
14876835Syc148097 	 * If the nxge driver has been plumbed without a link, then it will
14886835Syc148097 	 * detect a link up when a cable connecting to an anto-negotiation
14896835Syc148097 	 * partner is plugged into the port. Because the TN1010 PHY supports
14906835Syc148097 	 * both 1G and 10G speeds, the driver must re-configure the
14916835Syc148097 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
14926835Syc148097 	 * is called at the post-link-up reconfiguration time. Here it calls
14936835Syc148097 	 * nxge_set_tn1010_param to set portmode before re-initializing
14946835Syc148097 	 * the serdes.
14956835Syc148097 	 */
14966835Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
14976835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
14986835Syc148097 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
14996835Syc148097 			goto fail;
15006835Syc148097 		}
15016835Syc148097 	}
15026835Syc148097 
15036835Syc148097 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
15046835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
1505*9599Stc99174@train 	    nxgep->mac.portmode == PORT_HSP_MODE ||
15066835Syc148097 	    nxgep->mac.portmode == PORT_10G_SERDES) {
15073859Sml29623 		/* 0x0E01 */
15083859Sml29623 		tx_cfg_l.bits.entx = 1;
15093859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
15103859Sml29623 
15113859Sml29623 		/* 0x9101 */
15123859Sml29623 		rx_cfg_l.bits.enrx = 1;
15133859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
15143859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
15153859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
15163859Sml29623 
15173859Sml29623 		/* 0x0008 */
15183859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15193859Sml29623 
15203859Sml29623 		/* Set loopback mode if necessary */
15213859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
15223859Sml29623 			tx_cfg_l.bits.entest = 1;
15233859Sml29623 			rx_cfg_l.bits.entest = 1;
15243859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
15253859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
15266929Smisaki 			    ESR_N2_DEV_ADDR,
15276929Smisaki 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
15283859Sml29623 			goto fail;
15293859Sml29623 		}
15303859Sml29623 
15316835Syc148097 		/* Initialize PLL for 10G */
15326835Syc148097 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
15336835Syc148097 		pll_cfg_l.bits.enpll = 1;
15346835Syc148097 		pll_sts_l.bits.enpll = 1;
15356835Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15366835Syc148097 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
15376835Syc148097 			goto fail;
15386835Syc148097 
15396835Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15406835Syc148097 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15416835Syc148097 			goto fail;
15426835Syc148097 
15436835Syc148097 #ifdef  NXGE_DEBUG
15446835Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15456835Syc148097 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15466835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15476835Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15486835Syc148097 		    portn, pll_cfg_l.value, cfg.value));
15496835Syc148097 
15506835Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15516835Syc148097 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15526835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15536835Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
15546835Syc148097 		    portn, pll_sts_l.value, cfg.value));
15556835Syc148097 #endif
15566835Syc148097 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
15576835Syc148097 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
15586835Syc148097 	    nxgep->mac.portmode == PORT_1G_SERDES) {
15593859Sml29623 		/* 0x0E21 */
15603859Sml29623 		tx_cfg_l.bits.entx = 1;
15613859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
15623859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
15633859Sml29623 
15643859Sml29623 		/* 0x9121 */
15653859Sml29623 		rx_cfg_l.bits.enrx = 1;
15663859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
15673859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
15683859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
15693859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
15703859Sml29623 
15714977Sraghus 		if (portn == 0) {
15724977Sraghus 			/* 0x8 */
15734977Sraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15744977Sraghus 		}
15753859Sml29623 
15766835Syc148097 		/* Initialize PLL for 1G */
15773859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
15783859Sml29623 		pll_cfg_l.bits.enpll = 1;
15794977Sraghus 		pll_sts_l.bits.enpll = 1;
15803859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15816929Smisaki 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
15823859Sml29623 			goto fail;
15834977Sraghus 
15844977Sraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15854977Sraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15864977Sraghus 			goto fail;
15874977Sraghus 
15884977Sraghus #ifdef  NXGE_DEBUG
15894977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15904977Sraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15914977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15924977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15934977Sraghus 		    portn, pll_cfg_l.value, cfg.value));
15944977Sraghus 
15954977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15964977Sraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15974977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15984977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
15994977Sraghus 		    portn, pll_sts_l.value, cfg.value));
16004977Sraghus #endif
16014977Sraghus 
16024977Sraghus 		/* Set loopback mode if necessary */
16034977Sraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
16044977Sraghus 			tx_cfg_l.bits.entest = 1;
16054977Sraghus 			rx_cfg_l.bits.entest = 1;
16064977Sraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
16074977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16084977Sraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
16094977Sraghus 			    portn, test_cfg.value));
16104977Sraghus 			if ((status = nxge_mdio_write(nxgep, portn,
16114977Sraghus 			    ESR_N2_DEV_ADDR,
16124977Sraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
16134977Sraghus 				goto fail;
16144977Sraghus 			}
16154977Sraghus 		}
16163859Sml29623 	} else {
16173859Sml29623 		goto fail;
16183859Sml29623 	}
16193859Sml29623 
16203859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
16213859Sml29623 
16223859Sml29623 	NXGE_DELAY(20);
16233859Sml29623 
16243859Sml29623 	/* init TX channels */
16253859Sml29623 	for (chan = 0; chan < 4; chan++) {
16263859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16276929Smisaki 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
16283859Sml29623 			goto fail;
16293859Sml29623 
16303859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16316929Smisaki 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
16323859Sml29623 			goto fail;
16334977Sraghus 
16344977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16354977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16364977Sraghus 		    portn, chan, tx_cfg_l.value));
16374977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16384977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16394977Sraghus 		    portn, chan, tx_cfg_h.value));
16403859Sml29623 	}
16413859Sml29623 
16423859Sml29623 	/* init RX channels */
16433859Sml29623 	for (chan = 0; chan < 4; chan++) {
16443859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16456929Smisaki 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
16463859Sml29623 			goto fail;
16473859Sml29623 
16483859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16496929Smisaki 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
16503859Sml29623 			goto fail;
16514977Sraghus 
16524977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16534977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16544977Sraghus 		    portn, chan, rx_cfg_l.value));
16556835Syc148097 
16564977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16574977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16584977Sraghus 		    portn, chan, rx_cfg_h.value));
16593859Sml29623 	}
16603859Sml29623 
16613859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
16626929Smisaki 	    portn));
16633859Sml29623 
16643859Sml29623 	return (NXGE_OK);
16653859Sml29623 fail:
16665572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16675572Ssbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16685572Ssbehera 	    portn));
16693859Sml29623 
16703859Sml29623 	return (status);
16713859Sml29623 }
16723859Sml29623 
16734732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
16744732Sdavemq 
16754732Sdavemq static nxge_status_t
16764732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
16773859Sml29623 {
16783859Sml29623 	npi_handle_t		handle;
16793859Sml29623 	uint8_t			portn;
16806075Ssbehera 	int			chan, i;
16813859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
16823859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
16833859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
16843859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
16853859Sml29623 	uint64_t		val;
16863859Sml29623 	uint16_t		val16l;
16873859Sml29623 	uint16_t		val16h;
16883859Sml29623 	nxge_status_t		status = NXGE_OK;
16893859Sml29623 
16903859Sml29623 	portn = nxgep->mac.portnum;
16913859Sml29623 
16923859Sml29623 	if ((portn != 0) && (portn != 1))
16933859Sml29623 		return (NXGE_OK);
16943859Sml29623 
16954732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16964732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
16973859Sml29623 	handle = nxgep->npi_handle;
16984732Sdavemq 	switch (portn) {
16994732Sdavemq 	case 0:
17006028Ssbehera 		/* Reset Serdes */
17016028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
17026028Ssbehera 		NXGE_DELAY(20);
17036028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17046028Ssbehera 		NXGE_DELAY(2000);
17056028Ssbehera 
17066028Ssbehera 		/* Configure Serdes to 10G mode */
17076028Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
17086028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
17096028Ssbehera 
17104732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
17114732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
17124732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
17134732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
17144732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
17154732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
17164732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17174732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17184732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
17194732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
17204732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
17214732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
17224732Sdavemq 
17234732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
17244732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
17254732Sdavemq 			ESR_REG_WR(handle,
17264732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
17274732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
17284732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
17294732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
17304732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
17314732Sdavemq 		} else {
17324732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
17333859Sml29623 		}
17344732Sdavemq 		break;
17354732Sdavemq 	case 1:
17366028Ssbehera 		/* Reset Serdes */
17376028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
17386028Ssbehera 		NXGE_DELAY(20);
17396028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17406028Ssbehera 		NXGE_DELAY(2000);
17416028Ssbehera 
17426028Ssbehera 		/* Configure Serdes to 10G mode */
17436028Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
17446028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
17456028Ssbehera 
17464732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
17474732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
17484732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
17494732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
17504732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
17514732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
17524732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17534732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17544732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
17554732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
17564732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
17574732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
17584732Sdavemq 
17594732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
17604732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
17614732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
17624732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
17634732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
17644732Sdavemq 		} else {
17654732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
17663859Sml29623 		}
17674732Sdavemq 		break;
17684732Sdavemq 	default:
17694732Sdavemq 		/* Nothing to do here */
17704732Sdavemq 		goto done;
17714732Sdavemq 	}
17724732Sdavemq 
17734732Sdavemq 	/* init TX RX channels */
17744732Sdavemq 	for (chan = 0; chan < 4; chan++) {
17754732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
17764732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17774732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
17783859Sml29623 			goto fail;
17794732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
17804732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17814732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
17823859Sml29623 			goto fail;
17833859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
17844732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17854732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
17863859Sml29623 			goto fail;
17873859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
17884732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17894732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
17904732Sdavemq 			goto fail;
17914732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
17924732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
17934732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
17944732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
17954732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
17964732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
17974732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
17984732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
17994732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
18004732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
18014732Sdavemq 			goto fail;
18024732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
18034732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
18044732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
18054732Sdavemq 			goto fail;
18064732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
18074732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
18084732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
18094732Sdavemq 			goto fail;
18104732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
18114732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
18124732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
18133859Sml29623 			goto fail;
18143859Sml29623 		}
18153859Sml29623 
18164732Sdavemq 	/* Apply Tx core reset */
18174732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
18184732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
18194732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
18204732Sdavemq 		goto fail;
18214732Sdavemq 
18224732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18234732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
18244732Sdavemq 	    NXGE_OK)
18254732Sdavemq 		goto fail;
18264732Sdavemq 
18274732Sdavemq 	NXGE_DELAY(200);
18284732Sdavemq 
18294732Sdavemq 	/* Apply Rx core reset */
18304732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18314732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
18324732Sdavemq 	    NXGE_OK)
18334732Sdavemq 		goto fail;
18344732Sdavemq 
18354732Sdavemq 	NXGE_DELAY(200);
18364732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18374732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
18384732Sdavemq 		goto fail;
18394732Sdavemq 
18404732Sdavemq 	NXGE_DELAY(200);
18414732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
18424732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
18434732Sdavemq 	    &val16l)) != NXGE_OK)
18444732Sdavemq 		goto fail;
18454732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18464732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
18474732Sdavemq 		goto fail;
18484732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
18494732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18505196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
18515196Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
18525196Ssbehera 		    portn, val16l, val16h));
18534732Sdavemq 	}
18544732Sdavemq 
18554732Sdavemq 	if (portn == 0) {
18566075Ssbehera 		/* Wait for serdes to be ready */
18576075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
18586075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
18596075Ssbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
18606075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
18616075Ssbehera 			    ESR_SIG_XSERDES_RDY_P0 |
18626075Ssbehera 			    ESR_SIG_XDETECT_P0_CH3 |
18636075Ssbehera 			    ESR_SIG_XDETECT_P0_CH2 |
18646075Ssbehera 			    ESR_SIG_XDETECT_P0_CH1 |
18656075Ssbehera 			    ESR_SIG_XDETECT_P0_CH0))
18666075Ssbehera 
18676075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
18686075Ssbehera 			else
18696075Ssbehera 				break;
18706075Ssbehera 		}
18716075Ssbehera 
18726075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
18736650Sjoycey 			/*
18746650Sjoycey 			 * RDY signal stays low may due to the absent of the
18756650Sjoycey 			 * external PHY, it is not an error condition. But still
18766650Sjoycey 			 * print the message for the debugging purpose when link
18776650Sjoycey 			 * stays down
18786650Sjoycey 			 */
18796075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18806075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
18816075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
18826835Syc148097 				goto done;
18834732Sdavemq 		}
18844732Sdavemq 	} else if (portn == 1) {
18856075Ssbehera 		/* Wait for serdes to be ready */
18866075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
18876075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
18886075Ssbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
18896075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
18906075Ssbehera 			    ESR_SIG_XSERDES_RDY_P1 |
18916075Ssbehera 			    ESR_SIG_XDETECT_P1_CH3 |
18926075Ssbehera 			    ESR_SIG_XDETECT_P1_CH2 |
18936075Ssbehera 			    ESR_SIG_XDETECT_P1_CH1 |
18946075Ssbehera 			    ESR_SIG_XDETECT_P1_CH0))
18956075Ssbehera 
18966075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
18976075Ssbehera 			else
18986075Ssbehera 				break;
18996075Ssbehera 		}
19006075Ssbehera 
19016075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
19026650Sjoycey 			/*
19036650Sjoycey 			 * RDY signal stays low may due to the absent of the
19046650Sjoycey 			 * external PHY, it is not an error condition. But still
19056650Sjoycey 			 * print the message for the debugging purpose when link
19066650Sjoycey 			 * stays down
19076650Sjoycey 			 */
19086075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19096075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
19106075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
19116835Syc148097 				goto done;
19123859Sml29623 		}
19133859Sml29623 	}
19143859Sml29623 
19153859Sml29623 done:
19164732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19174732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
19184732Sdavemq 
19193859Sml29623 	return (NXGE_OK);
19203859Sml29623 fail:
19215572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19224732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
19234732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
19243859Sml29623 
19253859Sml29623 	return (status);
19263859Sml29623 }
19273859Sml29623 
19284732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
19294732Sdavemq 
19304732Sdavemq static nxge_status_t
19314732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
19323859Sml29623 {
19334732Sdavemq 	npi_handle_t		handle;
19344732Sdavemq 	uint8_t			portn;
19355196Ssbehera 	int			chan;
19365196Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
19375196Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
19385196Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
19395196Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
19404732Sdavemq 	uint64_t		val;
19415196Ssbehera 	uint16_t		val16l;
19425196Ssbehera 	uint16_t		val16h;
19435196Ssbehera 	nxge_status_t		status = NXGE_OK;
19443859Sml29623 
19453859Sml29623 	portn = nxgep->mac.portnum;
19464732Sdavemq 
19474732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19484732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
19494732Sdavemq 
19504732Sdavemq 	handle = nxgep->npi_handle;
19514732Sdavemq 
19524732Sdavemq 	switch (portn) {
19534732Sdavemq 	case 0:
19545196Ssbehera 		/* Assert the reset register */
19555196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
19565196Ssbehera 		val |= ESR_RESET_0;
19575196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
19585196Ssbehera 
19595196Ssbehera 		/* Set the PLL register to 0x79 */
19605196Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
19615196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
19625196Ssbehera 
19635196Ssbehera 		/* Set the control register to 0x249249f */
19645196Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
19655196Ssbehera 
19665196Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
19675196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
19685196Ssbehera 			/* Set pad loopback modes 0xaa */
19695196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
19705196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
19715196Ssbehera 		} else {
19725196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
19735196Ssbehera 		}
19745196Ssbehera 
19755196Ssbehera 		/* Deassert the reset register */
19765196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
19775196Ssbehera 		val &= ~ESR_RESET_0;
19785196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
19794732Sdavemq 		break;
19805196Ssbehera 
19814732Sdavemq 	case 1:
19825196Ssbehera 		/* Assert the reset register */
19835196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
19845196Ssbehera 		val |= ESR_RESET_1;
19855196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
19865196Ssbehera 
19875196Ssbehera 		/* Set PLL register to 0x79 */
19885196Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
19895196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
19905196Ssbehera 
19915196Ssbehera 		/* Set the control register to 0x249249f */
19925196Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
19935196Ssbehera 
19945196Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
19955196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
19965196Ssbehera 			/* Set pad loopback mode 0xaa */
19975196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
19985196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
19995196Ssbehera 		} else {
20005196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
20015196Ssbehera 		}
20025196Ssbehera 
20035196Ssbehera 		/* Deassert the reset register */
20045196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
20055196Ssbehera 		val &= ~ESR_RESET_1;
20065196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
20074732Sdavemq 		break;
20085196Ssbehera 
20094732Sdavemq 	default:
20105196Ssbehera 		/* Nothing to do here */
20115196Ssbehera 		goto done;
20125196Ssbehera 	}
20135196Ssbehera 
20145196Ssbehera 	/* init TX RX channels */
20155196Ssbehera 	for (chan = 0; chan < 4; chan++) {
20165196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20175196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
20185196Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
20195196Ssbehera 			goto fail;
20205196Ssbehera 		}
20215196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20225196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
20235196Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
20245196Ssbehera 			goto fail;
20255196Ssbehera 		}
20265196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20275196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
20285196Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
20295196Ssbehera 			goto fail;
20305196Ssbehera 		}
20315196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20325196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
20335196Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
20345196Ssbehera 			goto fail;
20355196Ssbehera 		}
20365196Ssbehera 
20375196Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
20385196Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
20395196Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
20405196Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
20415196Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
20425196Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
20435196Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
20445196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20455196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
20465196Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
20475196Ssbehera 			goto fail;
20485196Ssbehera 		}
20495196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20505196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
20515196Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
20525196Ssbehera 			goto fail;
20535196Ssbehera 		}
20545196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20555196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
20565196Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
20575196Ssbehera 			goto fail;
20585196Ssbehera 		}
20595196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20605196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
20615196Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
20625196Ssbehera 			goto fail;
20635196Ssbehera 		}
20645196Ssbehera 	}
20655196Ssbehera 
20665196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20675196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
20684732Sdavemq 		goto fail;
20693859Sml29623 	}
20705196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20715196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
20725196Ssbehera 		goto fail;
20735196Ssbehera 	}
20745196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20755196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
20765196Ssbehera 		goto fail;
20775196Ssbehera 	}
20785196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20795196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
20805196Ssbehera 		goto fail;
20815196Ssbehera 	}
20825196Ssbehera 
20835196Ssbehera 	/* Apply Tx core reset */
20845196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20855196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
20865196Ssbehera 		goto fail;
20875196Ssbehera 	}
20885196Ssbehera 
20895196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20905196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
20915196Ssbehera 	    NXGE_OK) {
20925196Ssbehera 		goto fail;
20935196Ssbehera 	}
20945196Ssbehera 
20955196Ssbehera 	NXGE_DELAY(200);
20965196Ssbehera 
20975196Ssbehera 	/* Apply Rx core reset */
20985196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20995196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
21005196Ssbehera 	    NXGE_OK) {
21015196Ssbehera 		goto fail;
21025196Ssbehera 	}
21035196Ssbehera 
21045196Ssbehera 	NXGE_DELAY(200);
21055196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
21065196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
21075196Ssbehera 		goto fail;
21085196Ssbehera 	}
21095196Ssbehera 
21105196Ssbehera 	NXGE_DELAY(200);
21115196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
21125196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
21135196Ssbehera 		goto fail;
21145196Ssbehera 	}
21155196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
21165196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
21175196Ssbehera 		goto fail;
21185196Ssbehera 	}
21195196Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
21205196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21215196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
21225196Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
21235196Ssbehera 		status = NXGE_ERROR;
21245196Ssbehera 		goto fail;
21255196Ssbehera 	}
21265196Ssbehera 
21275196Ssbehera 	NXGE_DELAY(200);
21285196Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
21295196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21305196Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
21315196Ssbehera 	    "val 0x%x", portn, val));
21325196Ssbehera 	if (portn == 0) {
21335196Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
21345196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
21356650Sjoycey 			/*
21366650Sjoycey 			 * RDY signal stays low may due to the absent of the
21376650Sjoycey 			 * external PHY, it is not an error condition. But still
21386650Sjoycey 			 * print the message for the debugging purpose when link
21396650Sjoycey 			 * stays down
21406650Sjoycey 			 */
21415196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21426650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
21436650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
21446835Syc148097 				goto done;
21455196Ssbehera 		}
21465196Ssbehera 	} else if (portn == 1) {
21475196Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
21485196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
21496650Sjoycey 			/*
21506650Sjoycey 			 * RDY signal stays low may due to the absent of the
21516650Sjoycey 			 * external PHY, it is not an error condition. But still
21526650Sjoycey 			 * print the message for the debugging purpose when link
21536650Sjoycey 			 * stays down
21546650Sjoycey 			 */
21555196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21566650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
21576650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
21586835Syc148097 				goto done;
21596835Syc148097 
21605196Ssbehera 		}
21615196Ssbehera 	}
21625196Ssbehera done:
21634732Sdavemq 
21644732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21654732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
21663859Sml29623 	return (NXGE_OK);
21674732Sdavemq fail:
21685196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21694732Sdavemq 	    "nxge_1G_serdes_init: "
21704732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
21714732Sdavemq 	    portn));
21724732Sdavemq 
21735196Ssbehera 	return (status);
21743859Sml29623 }
21753859Sml29623 
21765572Ssbehera /* Initialize the BCM 8704 xcvr */
21774732Sdavemq 
21784732Sdavemq static nxge_status_t
21795572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
21803859Sml29623 {
21813859Sml29623 	uint16_t		val;
21823859Sml29623 #ifdef	NXGE_DEBUG
21833859Sml29623 	uint8_t			portn;
21843859Sml29623 	uint16_t		val1;
21853859Sml29623 #endif
21863859Sml29623 	uint8_t			phy_port_addr;
21873859Sml29623 	pmd_tx_control_t	tx_ctl;
21883859Sml29623 	control_t		ctl;
21893859Sml29623 	phyxs_control_t		phyxs_ctl;
21903859Sml29623 	pcs_control_t		pcs_ctl;
21913859Sml29623 	uint32_t		delay = 0;
21923859Sml29623 	optics_dcntr_t		op_ctr;
21933859Sml29623 	nxge_status_t		status = NXGE_OK;
21943859Sml29623 #ifdef	NXGE_DEBUG
21953859Sml29623 	portn = nxgep->mac.portnum;
21963859Sml29623 #endif
21975572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
21984732Sdavemq 	    portn));
21994732Sdavemq 
22004732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
22014732Sdavemq 
22024732Sdavemq 	/* Reset the transceiver */
22034732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
22044732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
22054732Sdavemq 		goto fail;
22064732Sdavemq 
22074732Sdavemq 	phyxs_ctl.bits.reset = 1;
22084732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
22094732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
22104732Sdavemq 		goto fail;
22114732Sdavemq 
22124732Sdavemq 	do {
22134732Sdavemq 		drv_usecwait(500);
22144732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22154732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
22164732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
22174732Sdavemq 			goto fail;
22184732Sdavemq 		delay++;
22194732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
22204732Sdavemq 	if (delay == 100) {
22214732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
22224732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
22234732Sdavemq 		status = NXGE_ERROR;
22244732Sdavemq 		goto fail;
22254732Sdavemq 	}
22264732Sdavemq 
22274732Sdavemq 	/* Set to 0x7FBF */
22284732Sdavemq 	ctl.value = 0;
22294732Sdavemq 	ctl.bits.res1 = 0x3F;
22304732Sdavemq 	ctl.bits.optxon_lvl = 1;
22314732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
22324732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
22334732Sdavemq 	ctl.bits.optxflt_lvl = 1;
22344732Sdavemq 	ctl.bits.opprflt_lvl = 1;
22354732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
22364732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
22374732Sdavemq 	ctl.bits.optxrst_lvl = 1;
22384732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22394732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
22404732Sdavemq 	    != NXGE_OK)
22414732Sdavemq 		goto fail;
22424732Sdavemq 
22434732Sdavemq 	/* Set to 0x164 */
22444732Sdavemq 	tx_ctl.value = 0;
22454732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
22464732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
22474732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
22484732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
22494732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22504732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
22514732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
22524732Sdavemq 		goto fail;
22534732Sdavemq 	/*
22544732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
22554732Sdavemq 	 * back these registers twice after written.
22564732Sdavemq 	 */
22574732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22584732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
22594732Sdavemq 	    != NXGE_OK)
22604732Sdavemq 		goto fail;
22614732Sdavemq 
22624732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22634732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
22644732Sdavemq 	    != NXGE_OK)
22654732Sdavemq 		goto fail;
22664732Sdavemq 
22674732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22684732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
22694732Sdavemq 	    != NXGE_OK)
22704732Sdavemq 		goto fail;
22714732Sdavemq 
22724732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22734732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
22744732Sdavemq 	    != NXGE_OK)
22754732Sdavemq 		goto fail;
22764732Sdavemq 
22774732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
22784732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22794732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
22804732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
22814732Sdavemq 		goto fail;
22825553Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
22835553Smisaki 		op_ctr.bits.gpio_sel = 0x1;
22845553Smisaki 	} else {
22855553Smisaki 		op_ctr.bits.gpio_sel = 0x3;
22865553Smisaki 	}
22874732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22884732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
22894732Sdavemq 	    op_ctr.value)) != NXGE_OK)
22904732Sdavemq 		goto fail;
22914732Sdavemq 
22924732Sdavemq 	NXGE_DELAY(1000000);
22934732Sdavemq 
22944732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
22954732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22964732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
22974732Sdavemq 	    != NXGE_OK)
22984732Sdavemq 		goto fail;
22994732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
23004732Sdavemq 		pcs_ctl.bits.loopback = 1;
23014732Sdavemq 	else
23024732Sdavemq 		pcs_ctl.bits.loopback = 0;
23034732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
23044732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
23054732Sdavemq 	    != NXGE_OK)
23064732Sdavemq 		goto fail;
23074732Sdavemq 
23084732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
23094732Sdavemq 	if (status != NXGE_OK)
23104732Sdavemq 		goto fail;
23114732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23124732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
23134732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
23144732Sdavemq 	if (status != NXGE_OK)
23154732Sdavemq 		goto fail;
23164732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23174732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
23184732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
23194732Sdavemq 	if (status != NXGE_OK)
23204732Sdavemq 		goto fail;
23214732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23224732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
23234732Sdavemq 
23244732Sdavemq #ifdef	NXGE_DEBUG
23254732Sdavemq 	/* Diagnose link issue if link is not up */
23264732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
23274732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
23284732Sdavemq 	    &val);
23294732Sdavemq 	if (status != NXGE_OK)
23304732Sdavemq 		goto fail;
23314732Sdavemq 
23324732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23336929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
23344732Sdavemq 	if (status != NXGE_OK)
23354732Sdavemq 		goto fail;
23364732Sdavemq 
23374732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23386929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
23394732Sdavemq 	if (status != NXGE_OK)
23404732Sdavemq 		goto fail;
23414732Sdavemq 
23424732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23436929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
23444732Sdavemq 	if (status != NXGE_OK)
23454732Sdavemq 		goto fail;
23464732Sdavemq 
23474732Sdavemq 	if (val != 0x3FC) {
23484732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
23494732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23504732Sdavemq 			    "Cable not connected to peer or bad"
23514732Sdavemq 			    " cable on port<%d>\n", portn));
23524732Sdavemq 		} else if (val == 0x639C) {
23534732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23544732Sdavemq 			    "Optical module (XFP) is bad or absent"
23554732Sdavemq 			    " on port<%d>\n", portn));
23564732Sdavemq 		}
23574732Sdavemq 	}
23584732Sdavemq #endif
23594732Sdavemq 
23605572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
23615572Ssbehera 	    portn));
23625572Ssbehera 	return (NXGE_OK);
23635572Ssbehera 
23645572Ssbehera fail:
23655572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23665572Ssbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
23675572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
23685572Ssbehera 	return (NXGE_ERROR);
23695572Ssbehera }
23705572Ssbehera 
23715572Ssbehera /* Initialize the BCM 8706 Transceiver */
23725572Ssbehera 
23735572Ssbehera static nxge_status_t
23745572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
23755572Ssbehera {
23765572Ssbehera 	uint8_t			phy_port_addr;
23775572Ssbehera 	phyxs_control_t		phyxs_ctl;
23785572Ssbehera 	pcs_control_t		pcs_ctl;
23795572Ssbehera 	uint32_t		delay = 0;
23805572Ssbehera 	optics_dcntr_t		op_ctr;
23815572Ssbehera 	nxge_status_t		status = NXGE_OK;
23825572Ssbehera #ifdef	NXGE_DEBUG
23835572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
23845572Ssbehera #endif
23855572Ssbehera 
23865572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
23875572Ssbehera 	    portn));
23885572Ssbehera 
23895572Ssbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
23905572Ssbehera 
23915572Ssbehera 	/* Reset the transceiver */
23925572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23935572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
23945572Ssbehera 		goto fail;
23955572Ssbehera 
23965572Ssbehera 	phyxs_ctl.bits.reset = 1;
23975572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23985572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
23995572Ssbehera 		goto fail;
24005572Ssbehera 	do {
24015572Ssbehera 		drv_usecwait(500);
24025572Ssbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24035572Ssbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
24045572Ssbehera 		    &phyxs_ctl.value)) != NXGE_OK)
24055572Ssbehera 			goto fail;
24065572Ssbehera 		delay++;
24075572Ssbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
24085572Ssbehera 
24095572Ssbehera 	if (delay == 100) {
24105572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
24115572Ssbehera 		    "failed to reset Transceiver on port<%d>", portn));
24125572Ssbehera 		status = NXGE_ERROR;
24135572Ssbehera 		goto fail;
24145572Ssbehera 	}
24155572Ssbehera 
24165572Ssbehera 	NXGE_DELAY(1000000);
24175572Ssbehera 
24185572Ssbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
24195572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24205572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
24215572Ssbehera 	    != NXGE_OK)
24225572Ssbehera 		goto fail;
24235572Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24245572Ssbehera 		pcs_ctl.bits.loopback = 1;
24255572Ssbehera 	else
24265572Ssbehera 		pcs_ctl.bits.loopback = 0;
24275572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24285572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
24295572Ssbehera 	    != NXGE_OK)
24305572Ssbehera 		goto fail;
24315572Ssbehera 
24325572Ssbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
24335572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24345572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24355572Ssbehera 	    &op_ctr.value)) != NXGE_OK)
24365572Ssbehera 		goto fail;
24375572Ssbehera 	op_ctr.bits.gpio_sel = 0x3;
24385572Ssbehera 	op_ctr.bits.res2 = 0x1;
24395572Ssbehera 
24405572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24415572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24425572Ssbehera 	    op_ctr.value)) != NXGE_OK)
24435572Ssbehera 		goto fail;
24445572Ssbehera 
24455572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
24465572Ssbehera 	    portn));
24475572Ssbehera 	return (NXGE_OK);
24485572Ssbehera 
24495572Ssbehera fail:
24505572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24515572Ssbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
24525572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
24535572Ssbehera 	return (status);
24545572Ssbehera }
24555572Ssbehera 
24566604Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
24576604Ssbehera 
24586604Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
24596604Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
24606604Ssbehera 
24616604Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
24626604Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
24636604Ssbehera 
24646604Ssbehera 
24656604Ssbehera static void
24666604Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
24676604Ssbehera {
24686604Ssbehera 	uint16_t	value;
24696604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
24706604Ssbehera 
24716604Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
24726604Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
24736604Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
24746604Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
24756604Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
24766604Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
24776604Ssbehera 		    value);
24786604Ssbehera 	}
24796604Ssbehera }
24806604Ssbehera 
24816604Ssbehera static nxge_status_t
24826604Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
24836604Ssbehera {
24846604Ssbehera 	nxge_status_t	status;
24856604Ssbehera 	pcs_control_t	pcs_ctl;
24866604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
24876604Ssbehera 
24886604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
24896604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
24906604Ssbehera 
24916604Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24926604Ssbehera 		pcs_ctl.bits.loopback = 1;
24936604Ssbehera 	else
24946604Ssbehera 		pcs_ctl.bits.loopback = 0;
24956604Ssbehera 
24966604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
24976604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
24986604Ssbehera 
24996604Ssbehera fail:
25006604Ssbehera 	return (status);
25016604Ssbehera }
25026604Ssbehera 
25036604Ssbehera 
25046604Ssbehera static void
25056604Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
25066604Ssbehera {
25076604Ssbehera 	uint16_t	val2;
25086604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
25096604Ssbehera 
25106604Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
25116604Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
25126604Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
25136604Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
25146604Ssbehera 
25156604Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
25166604Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
25176604Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
25186604Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
25196604Ssbehera 	}
25206604Ssbehera }
25216604Ssbehera 
25226604Ssbehera 
25236604Ssbehera static nxge_status_t
25246604Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
25256604Ssbehera {
25266604Ssbehera 	uint8_t		phy;
25276604Ssbehera 	nxge_status_t	status;
25286604Ssbehera 	uint16_t	clk;
25296604Ssbehera 
25306604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
25316604Ssbehera 
25326604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
25336604Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
25346604Ssbehera 	    nxgep->mac.portnum, phy));
25356604Ssbehera 
25366604Ssbehera 	/* Set LED functions	*/
25376604Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
25386604Ssbehera 	/* PCS activity */
25396604Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
25406604Ssbehera 
25416604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
25426604Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
25436604Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
25446604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
25456604Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
25466604Ssbehera 
25476604Ssbehera 	/* Set internal loopback mode if necessary */
25486604Ssbehera 
25496604Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
25506604Ssbehera 
25516604Ssbehera 	/* Enable PMD */
25526604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
25536604Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
25546604Ssbehera 
25556604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
25566604Ssbehera 
25576604Ssbehera fail:
25586604Ssbehera 	return (status);
25596604Ssbehera }
25606604Ssbehera 
25616604Ssbehera 
25626604Ssbehera 
25635572Ssbehera /* Initialize the 10G Transceiver */
25645572Ssbehera 
25655572Ssbehera static nxge_status_t
25665572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
25675572Ssbehera {
25685572Ssbehera 	p_nxge_stats_t		statsp;
25696439Sml29623 	p_nxge_param_t		param_arr = nxgep->param_arr;
25705572Ssbehera 	nxge_status_t		status = NXGE_OK;
25715572Ssbehera #ifdef	NXGE_DEBUG
25725572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
25735572Ssbehera #endif
25745572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
25755572Ssbehera 	    portn));
25765572Ssbehera 
25775572Ssbehera 	statsp = nxgep->statsp;
25785572Ssbehera 
2579*9599Stc99174@train 	/* Disable Link LEDs, with or without PHY */
2580*9599Stc99174@train 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
25815572Ssbehera 		goto done;
2582*9599Stc99174@train 
2583*9599Stc99174@train 	/* Skip MDIO, if PHY absent */
2584*9599Stc99174@train 	if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
2585*9599Stc99174@train 		goto done;
2586*9599Stc99174@train 	}
25875572Ssbehera 
25885572Ssbehera 	/* Set Clause 45 */
25895572Ssbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
25905572Ssbehera 
25915572Ssbehera 	switch (nxgep->chip_id) {
25925572Ssbehera 	case BCM8704_CHIP_ID:
25936835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25945572Ssbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
25955572Ssbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
25965572Ssbehera 		break;
25975572Ssbehera 	case BCM8706_CHIP_ID:
25986835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25995572Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
26005572Ssbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
26015572Ssbehera 		break;
26026604Ssbehera 	case MRVL88X201X_CHIP_ID:
26036835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
26046604Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
26056604Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
26066604Ssbehera 		break;
26075572Ssbehera 	default:
26085572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
26095572Ssbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
26105572Ssbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
26115572Ssbehera 		goto fail;
26125572Ssbehera 	}
26135572Ssbehera 
26145572Ssbehera 	if (status != NXGE_OK) {
26155572Ssbehera 		goto fail;
26165572Ssbehera 	}
26174977Sraghus done:
26184732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
26194732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
26206439Sml29623 	statsp->mac_stats.adv_cap_asmpause =
26216439Sml29623 	    param_arr[param_anar_asmpause].value;
26226439Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
26234732Sdavemq 
26244732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
26254732Sdavemq 	    portn));
26264732Sdavemq 	return (NXGE_OK);
26274732Sdavemq 
26284732Sdavemq fail:
26295572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26304732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
26315572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
26325572Ssbehera 	return (NXGE_ERROR);
26334732Sdavemq }
26344732Sdavemq 
26354732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
26364732Sdavemq 
26374732Sdavemq static nxge_status_t
26384732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
26394732Sdavemq {
26404732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
26414732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
26424732Sdavemq 	nxge_status_t		status = NXGE_OK;
26434732Sdavemq 
26444977Sraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
26454977Sraghus 		statsp->mac_stats.cap_1000fdx =
26464977Sraghus 		    param_arr[param_anar_1000fdx].value;
26474977Sraghus 		goto done;
26484977Sraghus 	}
26494977Sraghus 
26504732Sdavemq 	/* Set Clause 22 */
26514732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
26524732Sdavemq 
26534732Sdavemq 	/* Set capability flags */
26544732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
26554977Sraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
26564977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
26574977Sraghus 		statsp->mac_stats.cap_100fdx =
26584977Sraghus 		    param_arr[param_anar_100fdx].value;
26594977Sraghus 		statsp->mac_stats.cap_10fdx =
26604977Sraghus 		    param_arr[param_anar_10fdx].value;
26614977Sraghus 	}
26624732Sdavemq 
26634732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
26644977Sraghus done:
26654732Sdavemq 	return (status);
26664732Sdavemq }
26674732Sdavemq 
26686835Syc148097 /*
26696835Syc148097  * Although the Teranetics copper transceiver (TN1010) does not need
26706835Syc148097  * to be initialized by the driver for passing packets, this funtion
26716835Syc148097  * initializes the members of nxgep->statsp->mac_stats struct for
26726835Syc148097  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
26736835Syc148097  * It also configures the TN1010 for PHY loopback to support SunVTS.
26746835Syc148097  *
26756835Syc148097  * TN1010 only has the option to disable advertisement for the 10G
26766835Syc148097  * mode. So we can set it to either Dual Mode or 1G Only mode but
26776835Syc148097  * can't set it to 10G Only mode.
26786835Syc148097  *
26796835Syc148097  * ndd -set command can set the following 6 speed/duplex related parameters.
26806835Syc148097  *
26816835Syc148097  * ----------------------------------------------------------------
26826835Syc148097  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
26836835Syc148097  * ----------------------------------------------------------------
26846835Syc148097  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
26856835Syc148097  * adv_10gfdx_cap
26866835Syc148097  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
26876835Syc148097  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
26886835Syc148097  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
26896835Syc148097  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
26906835Syc148097  * ----------------------------------------------------------------
26916835Syc148097  */
26926835Syc148097 static nxge_status_t
26936835Syc148097 nxge_tn1010_xcvr_init(p_nxge_t nxgep)
26946835Syc148097 {
26956835Syc148097 	p_nxge_param_t		param_arr;
26966835Syc148097 	p_nxge_stats_t		statsp;
26976835Syc148097 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
26986835Syc148097 	uint16_t		speed;
26996835Syc148097 	uint8_t			phy_port_addr;
27006835Syc148097 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
27016835Syc148097 	int			status = NXGE_OK;
27026835Syc148097 
27036835Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
27046835Syc148097 
27056835Syc148097 	param_arr	= nxgep->param_arr;
27066835Syc148097 	statsp		= nxgep->statsp;
27076835Syc148097 
27086835Syc148097 	/*
27096835Syc148097 	 * Initialize the xcvr statistics which are NOT controlled by ndd
27106835Syc148097 	 */
27116835Syc148097 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
27126835Syc148097 	statsp->mac_stats.cap_100T4    = 0;
27136835Syc148097 
27146835Syc148097 	/*
27156835Syc148097 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
27166835Syc148097 	 * that function nxge_check_tn1010_link repeatedly invoked by the
27176835Syc148097 	 * timer will update link_speed real time.
27186835Syc148097 	 */
27196835Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
27206835Syc148097 		goto fail;
27216835Syc148097 	}
27226835Syc148097 	if (speed == TN1010_SPEED_1G) {
27236835Syc148097 		statsp->mac_stats.cap_10gfdx = 0;
27246835Syc148097 	} else {
27256835Syc148097 		statsp->mac_stats.cap_10gfdx = 1;
27266835Syc148097 	}
27276835Syc148097 
27286835Syc148097 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
27296835Syc148097 	statsp->mac_stats.cap_1000fdx  = 1;
27306835Syc148097 
27316835Syc148097 	/* TN1010 is not able to operate in the following states */
27326835Syc148097 	statsp->mac_stats.cap_1000hdx  = 0;
27336835Syc148097 	statsp->mac_stats.cap_100fdx   = 0;
27346835Syc148097 	statsp->mac_stats.cap_100hdx   = 0;
27356835Syc148097 	statsp->mac_stats.cap_10fdx    = 0;
27366835Syc148097 	statsp->mac_stats.cap_10hdx    = 0;
27376835Syc148097 
27386835Syc148097 	/* param_anar_pause can be modified by ndd -set */
27396835Syc148097 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
27406835Syc148097 
27416835Syc148097 	/*
27426835Syc148097 	 * The following 4 lines actually overwrites what ever the ndd command
27436835Syc148097 	 * has set. For example, by command
27446835Syc148097 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
27456835Syc148097 	 * we could set param_arr[param_autoneg].value to n.  However, because
27466835Syc148097 	 * here we assign constants to these parameters, whatever we set with
27476835Syc148097 	 * the "ndd -set" command will be replaced. So command
27486835Syc148097 	 *	kstat nxge:X | grep param
27496835Syc148097 	 * will always show those constant values.  In other words, the
27506835Syc148097 	 * "ndd -set" command can NOT change the values of these 4 parameters
27516835Syc148097 	 * even though the command appears to be successful.
27526835Syc148097 	 *
27536835Syc148097 	 * Note: TN1010 auto negotiation is always enabled.
27546835Syc148097 	 */
27556835Syc148097 	statsp->mac_stats.adv_cap_autoneg
27566835Syc148097 	    = param_arr[param_autoneg].value = 1;
27576835Syc148097 	statsp->mac_stats.adv_cap_1000fdx
27586835Syc148097 	    = param_arr[param_anar_1000fdx].value = 1;
27596835Syc148097 	statsp->mac_stats.adv_cap_100fdx
27606835Syc148097 	    = param_arr[param_anar_100fdx].value = 0;
27616835Syc148097 	statsp->mac_stats.adv_cap_10fdx
27626835Syc148097 	    = param_arr[param_anar_10fdx].value = 0;
27636835Syc148097 
27646835Syc148097 	/*
27656835Syc148097 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
27666835Syc148097 	 * defined in nxge_param_arr[], therefore they are not seen by the
27676835Syc148097 	 * "ndd -get" command and can not be changed by ndd.  We just set
27686835Syc148097 	 * them (both ndd param and kstat values) to constant 0 because TN1010
27696835Syc148097 	 * does not support those speeds.
27706835Syc148097 	 */
27716835Syc148097 	statsp->mac_stats.adv_cap_100T4
27726835Syc148097 	    = param_arr[param_anar_100T4].value = 0;
27736835Syc148097 	statsp->mac_stats.adv_cap_1000hdx
27746835Syc148097 	    = param_arr[param_anar_1000hdx].value = 0;
27756835Syc148097 	statsp->mac_stats.adv_cap_100hdx
27766835Syc148097 	    = param_arr[param_anar_100hdx].value = 0;
27776835Syc148097 	statsp->mac_stats.adv_cap_10hdx
27786835Syc148097 	    = param_arr[param_anar_10hdx].value = 0;
27796835Syc148097 
27806835Syc148097 	/*
27816835Syc148097 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
27826835Syc148097 	 * by ndd
27836835Syc148097 	 */
27846835Syc148097 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
27856835Syc148097 
27866835Syc148097 	/*
27876835Syc148097 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
27886835Syc148097 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
27896835Syc148097 	 * "ndd -get" command and can not be changed by ndd. Here we do not
27906835Syc148097 	 * assign a constant to it so the default value defined in
27916835Syc148097 	 * nxge_param_arr[] will be used to set the parameter and
27926835Syc148097 	 * will be shown by the kstat.
27936835Syc148097 	 */
27946835Syc148097 	statsp->mac_stats.adv_cap_asmpause
27956835Syc148097 	    = param_arr[param_anar_asmpause].value;
27966835Syc148097 
27976835Syc148097 	/*
27986835Syc148097 	 * Initialize the link statistics.
27996835Syc148097 	 */
28006835Syc148097 	statsp->mac_stats.link_T4 = 0;
28016835Syc148097 	statsp->mac_stats.link_asmpause = 0;
28026835Syc148097 	statsp->mac_stats.link_pause = 0;
28036835Syc148097 	if (speed == TN1010_SPEED_1G) {
28046835Syc148097 		statsp->mac_stats.link_speed = 1000;
28056835Syc148097 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
28066835Syc148097 		statsp->mac_stats.link_up = 1;
28076835Syc148097 	} else {
28086835Syc148097 		statsp->mac_stats.link_speed = 10000;
28096835Syc148097 		statsp->mac_stats.link_duplex = 2;
28106835Syc148097 		statsp->mac_stats.link_up = 1;
28116835Syc148097 	}
28126835Syc148097 
28136835Syc148097 	/*
28146835Syc148097 	 * Because TN1010 does not have a link partner register, to
28156835Syc148097 	 * figure out the link partner's capabilities is tricky. Here we
28166835Syc148097 	 * just set the kstat based on our knowledge about the partner
28176835Syc148097 	 * (The partner must support auto-neg because auto-negotiation
28186835Syc148097 	 * has completed, it must support 1G or 10G because that is the
28196835Syc148097 	 * negotiated speed we are using.)
28206835Syc148097 	 *
28216835Syc148097 	 * Note: Current kstat does not show lp_cap_10gfdx and
28226835Syc148097 	 *	lp_cap_10ghdx.
28236835Syc148097 	 */
28246835Syc148097 	if (speed == TN1010_SPEED_1G) {
28256835Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 1;
28266835Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 0;
28276835Syc148097 	} else {
28286835Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 0;
28296835Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 1;
28306835Syc148097 	}
28316835Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
28326835Syc148097 	statsp->mac_stats.lp_cap_1000hdx  = 0;
28336835Syc148097 	statsp->mac_stats.lp_cap_100fdx   = 0;
28346835Syc148097 	statsp->mac_stats.lp_cap_100hdx   = 0;
28356835Syc148097 	statsp->mac_stats.lp_cap_10fdx    = 0;
28366835Syc148097 	statsp->mac_stats.lp_cap_10hdx    = 0;
28376835Syc148097 	statsp->mac_stats.lp_cap_10gfdx   = 0;
28386835Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
28396835Syc148097 	statsp->mac_stats.lp_cap_100T4    = 0;
28406835Syc148097 	statsp->mac_stats.lp_cap_autoneg  = 1;
28416835Syc148097 	statsp->mac_stats.lp_cap_asmpause = 0;
28426835Syc148097 	statsp->mac_stats.lp_cap_pause    = 0;
28436835Syc148097 
28446835Syc148097 	/* Handle PHY loopback for SunVTS loopback test */
28456835Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
28466835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
28476835Syc148097 
28486835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
28496835Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
28506835Syc148097 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
28516835Syc148097 		goto fail;
28526835Syc148097 	}
28536835Syc148097 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
28546835Syc148097 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
28556835Syc148097 		tn1010_pcs_ctrl.bits.loopback = 1;
28566835Syc148097 	} else {
28576835Syc148097 		tn1010_pcs_ctrl.bits.loopback = 0;
28586835Syc148097 	}
28596835Syc148097 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
28606835Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
28616835Syc148097 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
28626835Syc148097 		goto fail;
28636835Syc148097 	}
28646835Syc148097 
28656835Syc148097 	statsp->mac_stats.xcvr_inits++;
28666835Syc148097 
28676835Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
28686835Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
28696835Syc148097 	return (status);
28706835Syc148097 fail:
28716835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
28726835Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
28736835Syc148097 	return (status);
28746835Syc148097 }
28756835Syc148097 
28764732Sdavemq /* Initialize transceiver */
28774732Sdavemq 
28784732Sdavemq nxge_status_t
28794732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
28804732Sdavemq {
28814732Sdavemq 	p_nxge_stats_t		statsp;
28824732Sdavemq #ifdef	NXGE_DEBUG
28834732Sdavemq 	uint8_t			portn;
28844732Sdavemq #endif
28854732Sdavemq 
28864732Sdavemq 	nxge_status_t		status = NXGE_OK;
28874732Sdavemq #ifdef	NXGE_DEBUG
28884732Sdavemq 	portn = nxgep->mac.portnum;
28894732Sdavemq #endif
28903859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
28913859Sml29623 	statsp = nxgep->statsp;
28923859Sml29623 
28933859Sml29623 	/*
28946835Syc148097 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
28956835Syc148097 	 * modify mac_stats.
28963859Sml29623 	 */
28973859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
28983859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
28993859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
29003859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
29013859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
29023859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
29033859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
29043859Sml29623 	statsp->mac_stats.cap_pause = 0;
29053859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
29063859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
29073859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
29083859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
29093859Sml29623 
29103859Sml29623 	/*
29113859Sml29623 	 * Initialize the link statistics.
29123859Sml29623 	 */
29133859Sml29623 	statsp->mac_stats.link_T4 = 0;
29143859Sml29623 	statsp->mac_stats.link_asmpause = 0;
29153859Sml29623 	statsp->mac_stats.link_pause = 0;
29163859Sml29623 
29174732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
29184732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
29193859Sml29623 		if (status != NXGE_OK)
29203859Sml29623 			goto fail;
29214732Sdavemq 		statsp->mac_stats.xcvr_inits++;
29223859Sml29623 	}
29233859Sml29623 
29244732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
29254732Sdavemq 	    portn));
29263859Sml29623 	return (NXGE_OK);
29273859Sml29623 
29283859Sml29623 fail:
29293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29304732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
29314732Sdavemq 	    portn));
29323859Sml29623 	return (status);
29333859Sml29623 }
29343859Sml29623 
29354977Sraghus /* Look for transceiver type */
29364977Sraghus 
29374977Sraghus nxge_status_t
29384977Sraghus nxge_xcvr_find(p_nxge_t nxgep)
29394977Sraghus {
29405196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
29415196Ssbehera 	    nxgep->mac.portnum));
29424977Sraghus 
29434977Sraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
29444977Sraghus 		return (NXGE_ERROR);
29454977Sraghus 
29464977Sraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
29474977Sraghus 		return (NXGE_ERROR);
29484977Sraghus 
29494977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
29504977Sraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
29514977Sraghus 	return (NXGE_OK);
29524977Sraghus }
29533859Sml29623 
29543859Sml29623 /* Initialize the TxMAC sub-block */
29553859Sml29623 
29563859Sml29623 nxge_status_t
29573859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
29583859Sml29623 {
29593859Sml29623 	npi_attr_t		ap;
29603859Sml29623 	uint8_t			portn;
29613859Sml29623 	nxge_port_mode_t	portmode;
29623859Sml29623 	nxge_port_t		portt;
29633859Sml29623 	npi_handle_t		handle;
29643859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
29653859Sml29623 
29663859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
29673859Sml29623 	portt    = nxgep->mac.porttype;
29683859Sml29623 	handle   = nxgep->npi_handle;
29693859Sml29623 	portmode = nxgep->mac.portmode;
29703859Sml29623 
29713859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
29726929Smisaki 	    portn));
29733859Sml29623 	/* Set Max and Min Frame Size */
29746439Sml29623 	/*
29756439Sml29623 	 * Use maxframesize to configure the hardware maxframe size
29766835Syc148097 	 * and minframesize to configure the hardware minframe size.
29776439Sml29623 	 */
29786439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29796439Sml29623 	    "==> nxge_tx_mac_init: port<%d> "
29806439Sml29623 	    "min framesize %d max framesize %d ",
29816439Sml29623 	    nxgep->mac.minframesize,
29826439Sml29623 	    nxgep->mac.maxframesize,
29836439Sml29623 	    portn));
29846439Sml29623 
29856439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
29866439Sml29623 	    MAC_PORT_FRAME_SIZE,
29876439Sml29623 	    nxgep->mac.minframesize,
29886439Sml29623 	    nxgep->mac.maxframesize,
29896439Sml29623 	    rs);
29903859Sml29623 	if (rs != NPI_SUCCESS)
29913859Sml29623 		goto fail;
29923859Sml29623 
29933859Sml29623 	if (portt == PORT_TYPE_XMAC) {
29943859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
29956929Smisaki 		    0)) != NPI_SUCCESS)
29963859Sml29623 			goto fail;
29973859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
29983859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
29994977Sraghus 		    (portmode == PORT_10G_COPPER) ||
30006835Syc148097 		    (portmode == PORT_10G_TN1010) ||
3001*9599Stc99174@train 		    (portmode == PORT_HSP_MODE) ||
30024977Sraghus 		    (portmode == PORT_10G_SERDES)) {
30033859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
30046929Smisaki 			    XGMII_IPG_12_15, rs);
30053859Sml29623 			if (rs != NPI_SUCCESS)
30063859Sml29623 				goto fail;
30073859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
30083859Sml29623 		} else {
30093859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
30106929Smisaki 			    MII_GMII_IPG_12, rs);
30113859Sml29623 			if (rs != NPI_SUCCESS)
30123859Sml29623 				goto fail;
30133859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
30143859Sml29623 		}
30153859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
30166929Smisaki 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
30173859Sml29623 			goto fail;
30183859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
30193859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
30203859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
30213859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
30223859Sml29623 
30233859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
30246929Smisaki 		    != NPI_SUCCESS)
30253859Sml29623 			goto fail;
30263859Sml29623 
30273859Sml29623 	} else {
30283859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
30296929Smisaki 		    0)) != NPI_SUCCESS)
30303859Sml29623 			goto fail;
30313859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
30323859Sml29623 
30333859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
30346929Smisaki 		    rs);
30353859Sml29623 		if (rs != NPI_SUCCESS)
30363859Sml29623 			goto fail;
30373859Sml29623 		nxgep->mac.ctrltype = 0x8808;
30383859Sml29623 
30393859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
30403859Sml29623 		if (rs != NPI_SUCCESS)
30413859Sml29623 			goto fail;
30423859Sml29623 		nxgep->mac.pa_size = 0x7;
30433859Sml29623 
30443859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
30456929Smisaki 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
30463859Sml29623 			goto fail;
30473859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
30483859Sml29623 	}
30493859Sml29623 
30503859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
30516929Smisaki 	    portn));
30523859Sml29623 
30533859Sml29623 	return (NXGE_OK);
30543859Sml29623 fail:
30553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30566929Smisaki 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
30573859Sml29623 
30583859Sml29623 	return (NXGE_ERROR | rs);
30593859Sml29623 }
30603859Sml29623 
30616495Sspeer 
30623859Sml29623 /* Initialize the RxMAC sub-block */
30633859Sml29623 
30643859Sml29623 nxge_status_t
30653859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
30663859Sml29623 {
30673859Sml29623 	npi_attr_t		ap;
30683859Sml29623 	uint32_t		i;
30693859Sml29623 	uint16_t		hashtab_e;
30703859Sml29623 	p_hash_filter_t		hash_filter;
30713859Sml29623 	nxge_port_t		portt;
30723859Sml29623 	uint8_t			portn;
30733859Sml29623 	npi_handle_t		handle;
30743859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
30753859Sml29623 	uint16_t 		*addr16p;
30763859Sml29623 	uint16_t 		addr0, addr1, addr2;
30773859Sml29623 	xmac_rx_config_t	xconfig;
30783859Sml29623 	bmac_rx_config_t	bconfig;
30793859Sml29623 
30803859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
30813859Sml29623 
30823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
30836929Smisaki 	    portn));
30843859Sml29623 	handle = nxgep->npi_handle;
30853859Sml29623 	portt = nxgep->mac.porttype;
30863859Sml29623 
30873859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
30883859Sml29623 	addr0 = ntohs(addr16p[2]);
30893859Sml29623 	addr1 = ntohs(addr16p[1]);
30903859Sml29623 	addr2 = ntohs(addr16p[0]);
30913859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
30926929Smisaki 	    rs);
30933859Sml29623 
30943859Sml29623 	if (rs != NPI_SUCCESS)
30953859Sml29623 		goto fail;
30963859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
30973859Sml29623 	if (rs != NPI_SUCCESS)
30983859Sml29623 		goto fail;
30993859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
31003859Sml29623 	if (rs != NPI_SUCCESS)
31013859Sml29623 		goto fail;
31023859Sml29623 
31033859Sml29623 	/*
31043859Sml29623 	 * Load the multicast hash filter bits.
31053859Sml29623 	 */
31063859Sml29623 	hash_filter = nxgep->hash_filter;
31073859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
31083859Sml29623 		if (hash_filter != NULL) {
31093859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
31106929Smisaki 			    (NMCFILTER_REGS - 1) - i];
31113859Sml29623 		} else {
31123859Sml29623 			hashtab_e = 0;
31133859Sml29623 		}
31143859Sml29623 
31153859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
31166929Smisaki 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
31173859Sml29623 			goto fail;
31183859Sml29623 	}
31193859Sml29623 
31203859Sml29623 	if (portt == PORT_TYPE_XMAC) {
31213859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
31226929Smisaki 		    0)) != NPI_SUCCESS)
31233859Sml29623 			goto fail;
31243859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
31253859Sml29623 
31263859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
31273859Sml29623 
31283859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
31296929Smisaki 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
31306929Smisaki 		    ~CFG_XMAC_RX_STRIP_CRC;
31313859Sml29623 
31323859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
31333859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
31343859Sml29623 
31353859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
31363859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
31373859Sml29623 
31383859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
31393859Sml29623 
31403859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
31416929Smisaki 		    xconfig)) != NPI_SUCCESS)
31423859Sml29623 			goto fail;
31433859Sml29623 		nxgep->mac.rx_config = xconfig;
31443859Sml29623 
31453859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
31463859Sml29623 
31473859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
31486929Smisaki 		    != NPI_SUCCESS)
31493859Sml29623 			goto fail;
31503859Sml29623 	} else {
31513859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
31523859Sml29623 
31533859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
31546929Smisaki 		    0) != NPI_SUCCESS)
31553859Sml29623 			goto fail;
31563859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
31573859Sml29623 
31583859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
31596929Smisaki 		    ~CFG_BMAC_RX_STRIP_CRC;
31603859Sml29623 
31613859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
31623859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
31633859Sml29623 
31643859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
31653859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
31663859Sml29623 
31673859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
31683859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
31696929Smisaki 		    bconfig)) != NPI_SUCCESS)
31703859Sml29623 			goto fail;
31713859Sml29623 		nxgep->mac.rx_config = bconfig;
31723859Sml29623 
31733859Sml29623 		/* Always enable comparison of mac unique address */
31743859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
31756929Smisaki 		    != NPI_SUCCESS)
31763859Sml29623 			goto fail;
31773859Sml29623 	}
31783859Sml29623 
31793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
31806929Smisaki 	    portn));
31813859Sml29623 
31823859Sml29623 	return (NXGE_OK);
31833859Sml29623 
31843859Sml29623 fail:
31853859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
31866929Smisaki 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
31873859Sml29623 
31883859Sml29623 	return (NXGE_ERROR | rs);
31893859Sml29623 }
31903859Sml29623 
31913859Sml29623 /* Enable TXMAC */
31923859Sml29623 
31933859Sml29623 nxge_status_t
31943859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
31953859Sml29623 {
31963859Sml29623 	npi_handle_t	handle;
31973859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
31983859Sml29623 	nxge_status_t	status = NXGE_OK;
31993859Sml29623 
32003859Sml29623 	handle = nxgep->npi_handle;
32013859Sml29623 
32023859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
32036929Smisaki 	    nxgep->mac.portnum));
32043859Sml29623 
32053859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
32063859Sml29623 		goto fail;
32073859Sml29623 
32083859Sml29623 	/* based on speed */
32093859Sml29623 	nxgep->msg_min = ETHERMIN;
32103859Sml29623 
32113859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
32123859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
32136929Smisaki 		    CFG_XMAC_TX)) != NPI_SUCCESS)
32143859Sml29623 			goto fail;
32153859Sml29623 	} else {
32163859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
32176929Smisaki 		    CFG_BMAC_TX)) != NPI_SUCCESS)
32183859Sml29623 			goto fail;
32193859Sml29623 	}
32203859Sml29623 
32213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
32226929Smisaki 	    nxgep->mac.portnum));
32233859Sml29623 
32243859Sml29623 	return (NXGE_OK);
32253859Sml29623 fail:
32263859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32276929Smisaki 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
32286929Smisaki 	    nxgep->mac.portnum));
32293859Sml29623 	if (rs != NPI_SUCCESS)
32303859Sml29623 		return (NXGE_ERROR | rs);
32313859Sml29623 	else
32323859Sml29623 		return (status);
32333859Sml29623 }
32343859Sml29623 
32353859Sml29623 /* Disable TXMAC */
32363859Sml29623 
32373859Sml29623 nxge_status_t
32383859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
32393859Sml29623 {
32403859Sml29623 	npi_handle_t	handle;
32413859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
32423859Sml29623 
32436495Sspeer 	if (isLDOMguest(nxgep))
32446495Sspeer 		return (NXGE_OK);
32456495Sspeer 
32463859Sml29623 	handle = nxgep->npi_handle;
32473859Sml29623 
32483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
32496929Smisaki 	    nxgep->mac.portnum));
32503859Sml29623 
32513859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
32523859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
32536929Smisaki 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
32543859Sml29623 			goto fail;
32553859Sml29623 	} else {
32563859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
32576929Smisaki 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
32583859Sml29623 			goto fail;
32593859Sml29623 	}
32603859Sml29623 
32613859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
32626929Smisaki 	    nxgep->mac.portnum));
32633859Sml29623 	return (NXGE_OK);
32643859Sml29623 fail:
32653859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32666929Smisaki 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
32676929Smisaki 	    nxgep->mac.portnum));
32683859Sml29623 	return (NXGE_ERROR | rs);
32693859Sml29623 }
32703859Sml29623 
32713859Sml29623 /* Enable RXMAC */
32723859Sml29623 
32733859Sml29623 nxge_status_t
32743859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
32753859Sml29623 {
32763859Sml29623 	npi_handle_t	handle;
32773859Sml29623 	uint8_t 	portn;
32783859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
32793859Sml29623 	nxge_status_t	status = NXGE_OK;
32803859Sml29623 
32816495Sspeer 	/* This is a service-domain-only activity. */
32826495Sspeer 	if (isLDOMguest(nxgep))
32836495Sspeer 		return (status);
32846495Sspeer 
32853859Sml29623 	handle = nxgep->npi_handle;
32863859Sml29623 	portn = nxgep->mac.portnum;
32873859Sml29623 
32883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
32896929Smisaki 	    portn));
32903859Sml29623 
32913859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
32923859Sml29623 		goto fail;
32933859Sml29623 
32943859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
32953859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
32966495Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
32973859Sml29623 			goto fail;
32983859Sml29623 	} else {
32993859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
33006495Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
33013859Sml29623 			goto fail;
33023859Sml29623 	}
33033859Sml29623 
33046495Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
33056495Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
33063859Sml29623 
33073859Sml29623 	return (NXGE_OK);
33083859Sml29623 fail:
33093859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33106495Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
33113859Sml29623 
33123859Sml29623 	if (rs != NPI_SUCCESS)
33133859Sml29623 		return (NXGE_ERROR | rs);
33143859Sml29623 	else
33153859Sml29623 		return (status);
33163859Sml29623 }
33173859Sml29623 
33183859Sml29623 /* Disable RXMAC */
33193859Sml29623 
33203859Sml29623 nxge_status_t
33213859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
33223859Sml29623 {
33233859Sml29623 	npi_handle_t	handle;
33243859Sml29623 	uint8_t		portn;
33253859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
33263859Sml29623 
33276495Sspeer 	/* If we are a guest domain driver, don't bother. */
33286495Sspeer 	if (isLDOMguest(nxgep))
33296495Sspeer 		return (NXGE_OK);
33306495Sspeer 
33313859Sml29623 	handle = nxgep->npi_handle;
33323859Sml29623 	portn = nxgep->mac.portnum;
33333859Sml29623 
33343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
33356929Smisaki 	    portn));
33363859Sml29623 
33373859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
33383859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
33396929Smisaki 		    CFG_XMAC_RX)) != NPI_SUCCESS)
33403859Sml29623 			goto fail;
33413859Sml29623 	} else {
33423859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
33436929Smisaki 		    CFG_BMAC_RX)) != NPI_SUCCESS)
33443859Sml29623 			goto fail;
33453859Sml29623 	}
33463859Sml29623 
33473859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
33486929Smisaki 	    portn));
33493859Sml29623 	return (NXGE_OK);
33503859Sml29623 fail:
33513859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33526929Smisaki 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
33533859Sml29623 
33543859Sml29623 	return (NXGE_ERROR | rs);
33553859Sml29623 }
33563859Sml29623 
33573859Sml29623 /* Reset TXMAC */
33583859Sml29623 
33593859Sml29623 nxge_status_t
33603859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
33613859Sml29623 {
33623859Sml29623 	npi_handle_t	handle;
33633859Sml29623 	uint8_t		portn;
33643859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
33653859Sml29623 
33663859Sml29623 	handle = nxgep->npi_handle;
33673859Sml29623 	portn = nxgep->mac.portnum;
33683859Sml29623 
33693859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
33706929Smisaki 	    portn));
33713859Sml29623 
33723859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
33733859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
33743859Sml29623 		    != NPI_SUCCESS)
33753859Sml29623 			goto fail;
33763859Sml29623 	} else {
33773859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
33786929Smisaki 		    != NPI_SUCCESS)
33793859Sml29623 			goto fail;
33803859Sml29623 	}
33813859Sml29623 
33823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
33836929Smisaki 	    portn));
33843859Sml29623 
33853859Sml29623 	return (NXGE_OK);
33863859Sml29623 fail:
33873859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33886929Smisaki 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
33893859Sml29623 
33903859Sml29623 	return (NXGE_ERROR | rs);
33913859Sml29623 }
33923859Sml29623 
33933859Sml29623 /* Reset RXMAC */
33943859Sml29623 
33953859Sml29623 nxge_status_t
33963859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
33973859Sml29623 {
33983859Sml29623 	npi_handle_t	handle;
33993859Sml29623 	uint8_t		portn;
34003859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
34013859Sml29623 
34023859Sml29623 	handle = nxgep->npi_handle;
34033859Sml29623 	portn = nxgep->mac.portnum;
34043859Sml29623 
34053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
34066929Smisaki 	    portn));
34073859Sml29623 
34083859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
34093859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
34103859Sml29623 		    != NPI_SUCCESS)
34113859Sml29623 		goto fail;
34123859Sml29623 	} else {
34133859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
34146929Smisaki 		    != NPI_SUCCESS)
34153859Sml29623 		goto fail;
34163859Sml29623 	}
34173859Sml29623 
34183859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
34196929Smisaki 	    portn));
34203859Sml29623 
34213859Sml29623 	return (NXGE_OK);
34223859Sml29623 fail:
34233859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
34246929Smisaki 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
34253859Sml29623 	return (NXGE_ERROR | rs);
34263859Sml29623 }
34273859Sml29623 
34284732Sdavemq /* 10G fiber link interrupt start routine */
34294732Sdavemq 
34304732Sdavemq static nxge_status_t
34314732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
34324732Sdavemq {
34334732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34344732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34354732Sdavemq 
34364732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
34374732Sdavemq 
34384732Sdavemq 	if (rs != NPI_SUCCESS)
34394732Sdavemq 		return (NXGE_ERROR | rs);
34404732Sdavemq 	else
34414732Sdavemq 		return (NXGE_OK);
34424732Sdavemq }
34434732Sdavemq 
34444732Sdavemq /* 10G fiber link interrupt stop routine */
34454732Sdavemq 
34464732Sdavemq static nxge_status_t
34474732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
34484732Sdavemq {
34494732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34504732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34514732Sdavemq 
34524732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
34534732Sdavemq 
34544732Sdavemq 	if (rs != NPI_SUCCESS)
34554732Sdavemq 		return (NXGE_ERROR | rs);
34564732Sdavemq 	else
34574732Sdavemq 		return (NXGE_OK);
34584732Sdavemq }
34594732Sdavemq 
34604732Sdavemq /* 1G fiber link interrupt start routine */
34614732Sdavemq 
34624732Sdavemq static nxge_status_t
34634732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
34644732Sdavemq {
34654732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34664732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34674732Sdavemq 
34684732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
34694732Sdavemq 	if (rs != NPI_SUCCESS)
34704732Sdavemq 		return (NXGE_ERROR | rs);
34714732Sdavemq 	else
34724732Sdavemq 		return (NXGE_OK);
34734732Sdavemq }
34744732Sdavemq 
34754732Sdavemq /* 1G fiber link interrupt stop routine */
34764732Sdavemq 
34774732Sdavemq static nxge_status_t
34784732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
34794732Sdavemq {
34804732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34814732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34824732Sdavemq 
34834732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
34844732Sdavemq 
34854732Sdavemq 	if (rs != NPI_SUCCESS)
34864732Sdavemq 		return (NXGE_ERROR | rs);
34874732Sdavemq 	else
34884732Sdavemq 		return (NXGE_OK);
34894732Sdavemq }
34904732Sdavemq 
34914732Sdavemq /* 1G copper link interrupt start routine */
34924732Sdavemq 
34934732Sdavemq static nxge_status_t
34944732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
34954732Sdavemq {
34964732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34974732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34984732Sdavemq 
34994732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
35005203Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
35014732Sdavemq 
35024732Sdavemq 	if (rs != NPI_SUCCESS)
35034732Sdavemq 		return (NXGE_ERROR | rs);
35044732Sdavemq 	else
35054732Sdavemq 		return (NXGE_OK);
35064732Sdavemq }
35074732Sdavemq 
35084732Sdavemq /* 1G copper link interrupt stop routine */
35094732Sdavemq 
35104732Sdavemq static nxge_status_t
35114732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
35124732Sdavemq {
35134732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
35144732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
35154732Sdavemq 
35164732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
35174732Sdavemq 
35184732Sdavemq 	if (rs != NPI_SUCCESS)
35194732Sdavemq 		return (NXGE_ERROR | rs);
35204732Sdavemq 	else
35214732Sdavemq 		return (NXGE_OK);
35224732Sdavemq }
35234732Sdavemq 
35244732Sdavemq /* Enable/Disable Link Status change interrupt */
35253859Sml29623 
35263859Sml29623 nxge_status_t
35273859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
35283859Sml29623 {
35294732Sdavemq 	uint8_t		portn;
35304732Sdavemq 	nxge_status_t	status = NXGE_OK;
35313859Sml29623 
35323859Sml29623 	portn = nxgep->mac.portnum;
35333859Sml29623 
35343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
35354732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
35364732Sdavemq 		return (NXGE_OK);
35374732Sdavemq 
35384732Sdavemq 	if (enable == LINK_INTR_START)
35394732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
35404732Sdavemq 	else if (enable == LINK_INTR_STOP)
35414732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
35424732Sdavemq 	if (status != NXGE_OK)
35434732Sdavemq 		goto fail;
35443859Sml29623 
35453859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
35463859Sml29623 
35473859Sml29623 	return (NXGE_OK);
35483859Sml29623 fail:
35493859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
35506929Smisaki 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
35513859Sml29623 
35524732Sdavemq 	return (status);
35533859Sml29623 }
35543859Sml29623 
35553859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
35563859Sml29623 
35573859Sml29623 nxge_status_t
35583859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
35593859Sml29623 {
35603859Sml29623 	p_nxge_param_t	param_arr;
35613859Sml29623 	p_nxge_stats_t	statsp;
35623859Sml29623 	uint8_t		xcvr_portn;
35633859Sml29623 	p_mii_regs_t	mii_regs;
35643859Sml29623 	mii_bmcr_t	bmcr;
35653859Sml29623 	mii_bmsr_t	bmsr;
35663859Sml29623 	mii_anar_t	anar;
35673859Sml29623 	mii_gcr_t	gcr;
35683859Sml29623 	mii_esr_t	esr;
35693859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
35703859Sml29623 	int		status = NXGE_OK;
35713859Sml29623 
35723859Sml29623 	uint_t delay;
35733859Sml29623 
35743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
35753859Sml29623 
35763859Sml29623 	param_arr = nxgep->param_arr;
35773859Sml29623 	statsp = nxgep->statsp;
35783859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
35793859Sml29623 
35803859Sml29623 	mii_regs = NULL;
35813859Sml29623 
35823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35836929Smisaki 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
35843859Sml29623 
35853859Sml29623 	/*
35865196Ssbehera 	 * The mif phy mode may be connected to either a copper link
35875196Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
35885196Ssbehera 	 * configuration if it is hard-wired to fiber link.
35895196Ssbehera 	 */
35905196Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
35915196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
35925196Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
35935196Ssbehera 	}
35945196Ssbehera 
35955196Ssbehera 	/*
35963859Sml29623 	 * Reset the transceiver.
35973859Sml29623 	 */
35983859Sml29623 	delay = 0;
35993859Sml29623 	bmcr.value = 0;
36003859Sml29623 	bmcr.bits.reset = 1;
36013859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
36025125Sjoycey #if defined(__i386)
36036929Smisaki 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
36045125Sjoycey #else
36056929Smisaki 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
36065125Sjoycey #endif
36076929Smisaki 	    bmcr.value)) != NXGE_OK)
36083859Sml29623 		goto fail;
36093859Sml29623 	do {
36103859Sml29623 		drv_usecwait(500);
36113859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
36125125Sjoycey #if defined(__i386)
36136929Smisaki 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
36145125Sjoycey #else
36156929Smisaki 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
36165125Sjoycey #endif
36176929Smisaki 		    &bmcr.value)) != NXGE_OK)
36183859Sml29623 			goto fail;
36193859Sml29623 		delay++;
36203859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
36213859Sml29623 	if (delay == 1000) {
36223859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
36233859Sml29623 		goto fail;
36243859Sml29623 	}
36253859Sml29623 
36263859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
36275125Sjoycey #if defined(__i386)
36286929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
36295125Sjoycey #else
36306929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
36315125Sjoycey #endif
36326929Smisaki 	    &bmsr.value)) != NXGE_OK)
36333859Sml29623 		goto fail;
36343859Sml29623 
36353859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
36363859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
36373859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
36383859Sml29623 	param_arr[param_anar_100hdx].value = 0;
36393859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
36403859Sml29623 	param_arr[param_anar_10hdx].value = 0;
36413859Sml29623 
36423859Sml29623 	/*
36433859Sml29623 	 * Initialize the xcvr statistics.
36443859Sml29623 	 */
36453859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
36463859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
36473859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
36483859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
36493859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
36503859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
36513859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
36523859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
36533859Sml29623 
36543859Sml29623 	/*
36556835Syc148097 	 * Initialize the xcvr advertised capability statistics.
36563859Sml29623 	 */
36573859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
36583859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
36593859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
36603859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
36613859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
36623859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
36633859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
36643859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
36653859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
36666929Smisaki 	    param_arr[param_anar_asmpause].value;
36673859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
36683859Sml29623 
36693859Sml29623 
36703859Sml29623 	/*
36713859Sml29623 	 * Check for extended status just in case we're
36723859Sml29623 	 * running a Gigibit phy.
36733859Sml29623 	 */
36743859Sml29623 	if (bmsr.bits.extend_status) {
36753859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
36765125Sjoycey #if defined(__i386)
36776929Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->esr),
36785125Sjoycey #else
36796929Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->esr),
36805125Sjoycey #endif
36816929Smisaki 		    &esr.value)) != NXGE_OK)
36823859Sml29623 			goto fail;
36836929Smisaki 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
36843859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
36853859Sml29623 
36863859Sml29623 		statsp->mac_stats.cap_1000fdx =
36876929Smisaki 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
36883859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
36893859Sml29623 	} else {
36903859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
36913859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
36923859Sml29623 	}
36933859Sml29623 
36943859Sml29623 	/*
36953859Sml29623 	 * Initialize 1G Statistics once the capability is established.
36963859Sml29623 	 */
36973859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
36983859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
36993859Sml29623 
37003859Sml29623 	/*
37016835Syc148097 	 * Initialize the link statistics.
37023859Sml29623 	 */
37033859Sml29623 	statsp->mac_stats.link_T4 = 0;
37043859Sml29623 	statsp->mac_stats.link_asmpause = 0;
37053859Sml29623 	statsp->mac_stats.link_pause = 0;
37063859Sml29623 	statsp->mac_stats.link_speed = 0;
37073859Sml29623 	statsp->mac_stats.link_duplex = 0;
37083859Sml29623 	statsp->mac_stats.link_up = 0;
37093859Sml29623 
37103859Sml29623 	/*
37113859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
37123859Sml29623 	 */
37133859Sml29623 	bmcr.value = 0;
37143859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
37155125Sjoycey #if defined(__i386)
37166929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
37175125Sjoycey #else
37186929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
37195125Sjoycey #endif
37206929Smisaki 	    bmcr.value)) != NXGE_OK)
37213859Sml29623 		goto fail;
37223859Sml29623 
37233859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
37246929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
37253859Sml29623 		bmcr.bits.loopback = 1;
37263859Sml29623 		bmcr.bits.enable_autoneg = 0;
37273859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
37283859Sml29623 			bmcr.bits.speed_1000_sel = 1;
37293859Sml29623 		bmcr.bits.duplex_mode = 1;
37303859Sml29623 		param_arr[param_autoneg].value = 0;
37313859Sml29623 	} else {
37323859Sml29623 		bmcr.bits.loopback = 0;
37333859Sml29623 	}
37343859Sml29623 
37353859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
37366929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
37376929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
37383859Sml29623 		param_arr[param_autoneg].value = 0;
37393859Sml29623 		bcm5464r_aux.value = 0;
37403859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
37413859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
37423859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
37436929Smisaki 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
37443859Sml29623 			goto fail;
37453859Sml29623 	}
37463859Sml29623 
37476835Syc148097 	/* If auto-negotiation is desired */
37483859Sml29623 	if (param_arr[param_autoneg].value) {
37493859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37506929Smisaki 		    "Restarting Auto-negotiation."));
37513859Sml29623 		/*
37523859Sml29623 		 * Setup our Auto-negotiation advertisement register.
37533859Sml29623 		 */
37543859Sml29623 		anar.value = 0;
37553859Sml29623 		anar.bits.selector = 1;
37563859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
37573859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
37583859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
37593859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
37603859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
37613859Sml29623 		anar.bits.cap_asmpause = 0;
37623859Sml29623 		anar.bits.cap_pause = 0;
37633859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
37646929Smisaki 		    param_arr[param_anar_100fdx].value ||
37656929Smisaki 		    param_arr[param_anar_10fdx].value) {
37663859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
37673859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
37683859Sml29623 		}
37693859Sml29623 
37706835Syc148097 		/* Write to the auto-negotiation advertisement register */
37713859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
37725125Sjoycey #if defined(__i386)
37736929Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->anar),
37745125Sjoycey #else
37756929Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->anar),
37765125Sjoycey #endif
37776929Smisaki 		    anar.value)) != NXGE_OK)
37783859Sml29623 			goto fail;
37793859Sml29623 		if (bmsr.bits.extend_status) {
37803859Sml29623 			gcr.value = 0;
37813859Sml29623 			gcr.bits.ms_mode_en =
37826929Smisaki 			    param_arr[param_master_cfg_enable].value;
37833859Sml29623 			gcr.bits.master =
37846929Smisaki 			    param_arr[param_master_cfg_value].value;
37853859Sml29623 			gcr.bits.link_1000fdx =
37866929Smisaki 			    param_arr[param_anar_1000fdx].value;
37873859Sml29623 			gcr.bits.link_1000hdx =
37886929Smisaki 			    param_arr[param_anar_1000hdx].value;
37893859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
37905125Sjoycey #if defined(__i386)
37916929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
37925125Sjoycey #else
37936929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
37945125Sjoycey #endif
37956929Smisaki 			    gcr.value)) != NXGE_OK)
37963859Sml29623 				goto fail;
37973859Sml29623 		}
37983859Sml29623 
37993859Sml29623 		bmcr.bits.enable_autoneg = 1;
38003859Sml29623 		bmcr.bits.restart_autoneg = 1;
38013859Sml29623 
38023859Sml29623 	} else {
38033859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
38043859Sml29623 		bmcr.bits.speed_1000_sel =
38056929Smisaki 		    param_arr[param_anar_1000fdx].value |
38066929Smisaki 		    param_arr[param_anar_1000hdx].value;
38073859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
38086929Smisaki 		    (param_arr[param_anar_100fdx].value |
38096929Smisaki 		    param_arr[param_anar_100hdx].value);
38106835Syc148097 
38116835Syc148097 		/* Force to 1G */
38123859Sml29623 		if (bmcr.bits.speed_1000_sel) {
38133859Sml29623 			statsp->mac_stats.link_speed = 1000;
38143859Sml29623 			gcr.value = 0;
38153859Sml29623 			gcr.bits.ms_mode_en =
38166929Smisaki 			    param_arr[param_master_cfg_enable].value;
38173859Sml29623 			gcr.bits.master =
38186929Smisaki 			    param_arr[param_master_cfg_value].value;
38193859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
38205125Sjoycey #if defined(__i386)
38216929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
38225125Sjoycey #else
38236929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
38245125Sjoycey #endif
38256929Smisaki 			    gcr.value)) != NXGE_OK)
38263859Sml29623 				goto fail;
38273859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
38283859Sml29623 				bmcr.bits.duplex_mode = 1;
38293859Sml29623 				statsp->mac_stats.link_duplex = 2;
38303859Sml29623 			} else
38313859Sml29623 				statsp->mac_stats.link_duplex = 1;
38326835Syc148097 
38336835Syc148097 		/* Force to 100M */
38343859Sml29623 		} else if (bmcr.bits.speed_sel) {
38353859Sml29623 			statsp->mac_stats.link_speed = 100;
38363859Sml29623 			if (param_arr[param_anar_100fdx].value) {
38373859Sml29623 				bmcr.bits.duplex_mode = 1;
38383859Sml29623 				statsp->mac_stats.link_duplex = 2;
38393859Sml29623 			} else
38403859Sml29623 				statsp->mac_stats.link_duplex = 1;
38416835Syc148097 
38426835Syc148097 		/* Force to 10M */
38433859Sml29623 		} else {
38443859Sml29623 			statsp->mac_stats.link_speed = 10;
38453859Sml29623 			if (param_arr[param_anar_10fdx].value) {
38463859Sml29623 				bmcr.bits.duplex_mode = 1;
38473859Sml29623 				statsp->mac_stats.link_duplex = 2;
38483859Sml29623 			} else
38493859Sml29623 				statsp->mac_stats.link_duplex = 1;
38503859Sml29623 		}
38513859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
38523859Sml29623 			statsp->mac_stats.link_asmpause =
38536929Smisaki 			    statsp->mac_stats.cap_asmpause;
38543859Sml29623 			statsp->mac_stats.link_pause =
38556929Smisaki 			    statsp->mac_stats.cap_pause;
38563859Sml29623 		}
38573859Sml29623 
38583859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
38596929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
38606929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
38613859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
38623859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
38633859Sml29623 				gcr.value = 0;
38643859Sml29623 				gcr.bits.ms_mode_en = 1;
38653859Sml29623 				gcr.bits.master = 1;
38663859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
38675125Sjoycey #if defined(__i386)
38686929Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
38695125Sjoycey #else
38706929Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
38715125Sjoycey #endif
38726929Smisaki 				    gcr.value)) != NXGE_OK)
38733859Sml29623 					goto fail;
38743859Sml29623 				bmcr.value = 0;
38753859Sml29623 				bmcr.bits.speed_1000_sel = 1;
38763859Sml29623 				statsp->mac_stats.link_speed = 1000;
38773859Sml29623 			} else if (statsp->port_stats.lb_mode
38783859Sml29623 			    == nxge_lb_ext100) {
38793859Sml29623 				/* BCM5464R 100mbps external loopback mode */
38803859Sml29623 				bmcr.value = 0;
38813859Sml29623 				bmcr.bits.speed_sel = 1;
38823859Sml29623 				bmcr.bits.duplex_mode = 1;
38833859Sml29623 				statsp->mac_stats.link_speed = 100;
38843859Sml29623 			} else if (statsp->port_stats.lb_mode
38853859Sml29623 			    == nxge_lb_ext10) {
38863859Sml29623 				/* BCM5464R 10mbps external loopback mode */
38873859Sml29623 				bmcr.value = 0;
38883859Sml29623 				bmcr.bits.duplex_mode = 1;
38893859Sml29623 				statsp->mac_stats.link_speed = 10;
38903859Sml29623 			}
38913859Sml29623 		}
38923859Sml29623 	}
38933859Sml29623 
38943859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38955125Sjoycey #if defined(__i386)
38966929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
38975125Sjoycey #else
38986929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
38995125Sjoycey #endif
39006929Smisaki 	    bmcr.value)) != NXGE_OK)
39013859Sml29623 		goto fail;
39023859Sml29623 
39033859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39045125Sjoycey #if defined(__i386)
39056929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
39065125Sjoycey #else
39076929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
39085125Sjoycey #endif
39096929Smisaki 	    &bmcr.value)) != NXGE_OK)
39103859Sml29623 		goto fail;
39113859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
39123859Sml29623 
39133859Sml29623 	/*
39143859Sml29623 	 * Initialize the xcvr status kept in the context structure.
39153859Sml29623 	 */
39163859Sml29623 	nxgep->soft_bmsr.value = 0;
39173859Sml29623 
39183859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39195125Sjoycey #if defined(__i386)
39206929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
39215125Sjoycey #else
39226929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
39235125Sjoycey #endif
39246929Smisaki 	    &nxgep->bmsr.value)) != NXGE_OK)
39253859Sml29623 		goto fail;
39263859Sml29623 
39273859Sml29623 	statsp->mac_stats.xcvr_inits++;
39283859Sml29623 	nxgep->bmsr.value = 0;
39293859Sml29623 
39303859Sml29623 fail:
39313859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39326929Smisaki 	    "<== nxge_mii_xcvr_init status 0x%x", status));
39333859Sml29623 	return (status);
39343859Sml29623 }
39353859Sml29623 
39365196Ssbehera nxge_status_t
39375196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
39385196Ssbehera {
39395196Ssbehera 	p_nxge_param_t	param_arr;
39405196Ssbehera 	p_nxge_stats_t	statsp;
39415196Ssbehera 	uint8_t		xcvr_portn;
39425196Ssbehera 	p_mii_regs_t	mii_regs;
39435196Ssbehera 	mii_bmcr_t	bmcr;
39445196Ssbehera 	mii_bmsr_t	bmsr;
39455196Ssbehera 	mii_gcr_t	gcr;
39465196Ssbehera 	mii_esr_t	esr;
39475196Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
39485196Ssbehera 	int		status = NXGE_OK;
39495196Ssbehera 
39505196Ssbehera 	uint_t delay;
39515196Ssbehera 
39525196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
39535196Ssbehera 
39545196Ssbehera 	param_arr = nxgep->param_arr;
39555196Ssbehera 	statsp = nxgep->statsp;
39565196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
39575196Ssbehera 
39585196Ssbehera 	mii_regs = NULL;
39595196Ssbehera 
39605196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39615196Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
39625196Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
39635196Ssbehera 
39645196Ssbehera 	/*
39655196Ssbehera 	 * Reset the transceiver.
39665196Ssbehera 	 */
39675196Ssbehera 	delay = 0;
39685196Ssbehera 	bmcr.value = 0;
39695196Ssbehera 	bmcr.bits.reset = 1;
39705196Ssbehera 
39715196Ssbehera #if defined(__i386)
39725196Ssbehera 
39735196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
39745196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
39755196Ssbehera 		goto fail;
39765196Ssbehera #else
39775196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
39785196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
39795196Ssbehera 		goto fail;
39805196Ssbehera #endif
39815196Ssbehera 	do {
39825196Ssbehera 		drv_usecwait(500);
39835196Ssbehera #if defined(__i386)
39845196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
39855196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
39865196Ssbehera 		    != NXGE_OK)
39875196Ssbehera 			goto fail;
39885196Ssbehera #else
39895196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
39905196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
39915196Ssbehera 		    != NXGE_OK)
39925196Ssbehera 			goto fail;
39935196Ssbehera #endif
39945196Ssbehera 		delay++;
39955196Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
39965196Ssbehera 	if (delay == 1000) {
39975196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
39985196Ssbehera 		goto fail;
39995196Ssbehera 	}
40005196Ssbehera 
40015196Ssbehera #if defined(__i386)
40025196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
40035196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
40045196Ssbehera 		goto fail;
40055196Ssbehera #else
40065196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
40075196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
40085196Ssbehera 		goto fail;
40095196Ssbehera #endif
40105196Ssbehera 
40115196Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
40125196Ssbehera 	param_arr[param_anar_100T4].value = 0;
40135196Ssbehera 	param_arr[param_anar_100fdx].value = 0;
40145196Ssbehera 	param_arr[param_anar_100hdx].value = 0;
40155196Ssbehera 	param_arr[param_anar_10fdx].value = 0;
40165196Ssbehera 	param_arr[param_anar_10hdx].value = 0;
40175196Ssbehera 
40185196Ssbehera 	/*
40195196Ssbehera 	 * Initialize the xcvr statistics.
40205196Ssbehera 	 */
40215196Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
40225196Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
40235196Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
40245196Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
40255196Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
40265196Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
40275196Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
40285196Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
40295196Ssbehera 
40305196Ssbehera 	/*
40315196Ssbehera 	 * Initialize the xcvr advertised capability statistics.
40325196Ssbehera 	 */
40335196Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
40345196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
40355196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
40365196Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
40375196Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
40385196Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
40395196Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
40405196Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
40415196Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
40425196Ssbehera 	    param_arr[param_anar_asmpause].value;
40435196Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
40445196Ssbehera 
40455196Ssbehera 	/*
40465196Ssbehera 	 * Check for extended status just in case we're
40475196Ssbehera 	 * running a Gigibit phy.
40485196Ssbehera 	 */
40495196Ssbehera 	if (bmsr.bits.extend_status) {
40505196Ssbehera #if defined(__i386)
40515196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
40525196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
40535196Ssbehera 		    NXGE_OK)
40545196Ssbehera 			goto fail;
40555196Ssbehera #else
40565196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
40575196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
40585196Ssbehera 		    NXGE_OK)
40595196Ssbehera 			goto fail;
40605196Ssbehera #endif
40615196Ssbehera 		param_arr[param_anar_1000fdx].value &=
40625196Ssbehera 		    esr.bits.link_1000fdx;
40635196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
40645196Ssbehera 
40655196Ssbehera 		statsp->mac_stats.cap_1000fdx =
40665196Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
40675196Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
40685196Ssbehera 	} else {
40695196Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
40705196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
40715196Ssbehera 	}
40725196Ssbehera 
40735196Ssbehera 	/*
40745196Ssbehera 	 * Initialize 1G Statistics once the capability is established.
40755196Ssbehera 	 */
40765196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
40775196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
40785196Ssbehera 
40795196Ssbehera 	/*
40805196Ssbehera 	 * Initialize the link statistics.
40815196Ssbehera 	 */
40825196Ssbehera 	statsp->mac_stats.link_T4 = 0;
40835196Ssbehera 	statsp->mac_stats.link_asmpause = 0;
40845196Ssbehera 	statsp->mac_stats.link_pause = 0;
40855196Ssbehera 	statsp->mac_stats.link_speed = 0;
40865196Ssbehera 	statsp->mac_stats.link_duplex = 0;
40875196Ssbehera 	statsp->mac_stats.link_up = 0;
40885196Ssbehera 
40895196Ssbehera 	/*
40905196Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
40915196Ssbehera 	 */
40925196Ssbehera 	bmcr.value = 0;
40935196Ssbehera #if defined(__i386)
40945196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
40955196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
40965196Ssbehera 		goto fail;
40975196Ssbehera #else
40985196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
40995196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
41005196Ssbehera 		goto fail;
41015196Ssbehera #endif
41025196Ssbehera 
41035196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
41045196Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
41055196Ssbehera 		bmcr.bits.loopback = 1;
41065196Ssbehera 		bmcr.bits.enable_autoneg = 0;
41075196Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
41085196Ssbehera 			bmcr.bits.speed_1000_sel = 1;
41095196Ssbehera 		bmcr.bits.duplex_mode = 1;
41105196Ssbehera 		param_arr[param_autoneg].value = 0;
41115196Ssbehera 	} else {
41125196Ssbehera 		bmcr.bits.loopback = 0;
41135196Ssbehera 	}
41145196Ssbehera 
41155196Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
41165196Ssbehera 		param_arr[param_autoneg].value = 0;
41175196Ssbehera 		bcm5464r_aux.value = 0;
41185196Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
41195196Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
41205196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
41215196Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
41225196Ssbehera 			goto fail;
41235196Ssbehera 	}
41245196Ssbehera 
41255196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
41265196Ssbehera 	bmcr.bits.speed_1000_sel = 1;
41275196Ssbehera 	bmcr.bits.speed_sel = 0;
41285196Ssbehera 	bmcr.bits.duplex_mode = 1;
41295196Ssbehera 	statsp->mac_stats.link_speed = 1000;
41305196Ssbehera 	statsp->mac_stats.link_duplex = 2;
41315196Ssbehera 
41325196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
41335196Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
41345196Ssbehera 		gcr.value = 0;
41355196Ssbehera 		gcr.bits.ms_mode_en = 1;
41365196Ssbehera 		gcr.bits.master = 1;
41375196Ssbehera #if defined(__i386)
41385196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
41395196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
41405196Ssbehera 		    gcr.value)) != NXGE_OK)
41415196Ssbehera 			goto fail;
41425196Ssbehera #else
41435196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
41445196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
41455196Ssbehera 		    gcr.value)) != NXGE_OK)
41465196Ssbehera 			goto fail;
41475196Ssbehera #endif
41485196Ssbehera 		bmcr.value = 0;
41495196Ssbehera 		bmcr.bits.speed_1000_sel = 1;
41505196Ssbehera 		statsp->mac_stats.link_speed = 1000;
41515196Ssbehera 	}
41525196Ssbehera 
41535196Ssbehera #if defined(__i386)
41545196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
41555196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
41565196Ssbehera 	    bmcr.value)) != NXGE_OK)
41575196Ssbehera 		goto fail;
41585196Ssbehera #else
41595196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
41605196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
41615196Ssbehera 	    bmcr.value)) != NXGE_OK)
41625196Ssbehera 		goto fail;
41635196Ssbehera #endif
41645196Ssbehera 
41655196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41665196Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
41675196Ssbehera 	    bmcr.value));
41685196Ssbehera 
41695196Ssbehera #if defined(__i386)
41705196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41715196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
41725196Ssbehera 		goto fail;
41735196Ssbehera #else
41745196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41755196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
41765196Ssbehera 		goto fail;
41775196Ssbehera #endif
41785196Ssbehera 
41795196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41805196Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
41815196Ssbehera 
41825196Ssbehera 	/*
41835196Ssbehera 	 * Initialize the xcvr status kept in the context structure.
41845196Ssbehera 	 */
41855196Ssbehera 	nxgep->soft_bmsr.value = 0;
41865196Ssbehera #if defined(__i386)
41875196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41885196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
41895196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
41905196Ssbehera 		goto fail;
41915196Ssbehera #else
41925196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41935196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
41945196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
41955196Ssbehera 		goto fail;
41965196Ssbehera #endif
41975196Ssbehera 
41985196Ssbehera 	statsp->mac_stats.xcvr_inits++;
41995196Ssbehera 	nxgep->bmsr.value = 0;
42005196Ssbehera 
42015196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
42025196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
42035196Ssbehera 	return (status);
42045196Ssbehera 
42055196Ssbehera fail:
42065196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42075196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
42085196Ssbehera 	return (status);
42095196Ssbehera }
42105196Ssbehera 
42113859Sml29623 /* Read from a MII compliant register */
42123859Sml29623 
42133859Sml29623 nxge_status_t
42143859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
42153859Sml29623 		uint16_t *value)
42163859Sml29623 {
42173859Sml29623 	npi_status_t rs = NPI_SUCCESS;
42183859Sml29623 
42193859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
42206929Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
42213859Sml29623 
42226075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
42233859Sml29623 
42245196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
42255196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
42263859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
42276929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42283859Sml29623 			goto fail;
42294977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42304977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
42313859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
42326929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42333859Sml29623 			goto fail;
42343859Sml29623 	} else
42353859Sml29623 		goto fail;
42363859Sml29623 
42376075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42383859Sml29623 
42393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
42406929Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
42413859Sml29623 	return (NXGE_OK);
42423859Sml29623 fail:
42436075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42443859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42456929Smisaki 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
42463859Sml29623 
42473859Sml29623 	return (NXGE_ERROR | rs);
42483859Sml29623 }
42493859Sml29623 
42503859Sml29623 /* Write to a MII compliant Register */
42513859Sml29623 
42523859Sml29623 nxge_status_t
42533859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
42543859Sml29623 		uint16_t value)
42553859Sml29623 {
42563859Sml29623 	npi_status_t rs = NPI_SUCCESS;
42573859Sml29623 
42583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
42596929Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
42603859Sml29623 
42616075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
42623859Sml29623 
42635196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
42645196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
42653859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
42666929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42673859Sml29623 			goto fail;
42684977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42694977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
42703859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
42716929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42723859Sml29623 			goto fail;
42733859Sml29623 	} else
42743859Sml29623 		goto fail;
42753859Sml29623 
42766075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42773859Sml29623 
42783859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
42796929Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
42803859Sml29623 	return (NXGE_OK);
42813859Sml29623 fail:
42826075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42833859Sml29623 
42843859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42856929Smisaki 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
42863859Sml29623 
42873859Sml29623 	return (NXGE_ERROR | rs);
42883859Sml29623 }
42893859Sml29623 
42906835Syc148097 /*
42916835Syc148097  * Perform write to Clause45 serdes / transceiver device
42926835Syc148097  * Arguments:
42936835Syc148097  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
42946835Syc148097  *			number if nxge_mdio_write is used for accessing the
42956835Syc148097  *			internal LSIL serdes. Otherwise PHYAD is different
42966835Syc148097  * 			for different platforms.
42976835Syc148097  *	device:		With each PHYAD, the driver can use MDIO to control
42986835Syc148097  *			multiple devices inside the PHY, here "device" is an
42996835Syc148097  *			MMD (MDIO managable device).
43006835Syc148097  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
43016835Syc148097  *			the register which the driver will write value to.
43026835Syc148097  *	value:		The register value will be filled in.
43036835Syc148097  */
43043859Sml29623 nxge_status_t
43053859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
43063859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
43073859Sml29623 {
43083859Sml29623 	npi_status_t rs = NPI_SUCCESS;
43093859Sml29623 
43103859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
43116929Smisaki 	    xcvr_portn));
43123859Sml29623 
43135780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
43143859Sml29623 
43153859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
43166929Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
43173859Sml29623 		goto fail;
43183859Sml29623 
43195780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43203859Sml29623 
43213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
43226929Smisaki 	    xcvr_portn));
43233859Sml29623 	return (NXGE_OK);
43243859Sml29623 fail:
43255780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43263859Sml29623 
43273859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43286929Smisaki 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
43293859Sml29623 
43303859Sml29623 	return (NXGE_ERROR | rs);
43313859Sml29623 }
43323859Sml29623 
43333859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
43343859Sml29623 
43353859Sml29623 nxge_status_t
43363859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
43373859Sml29623 		uint16_t xcvr_reg, uint16_t value)
43383859Sml29623 {
43393859Sml29623 	npi_status_t rs = NPI_SUCCESS;
43403859Sml29623 
43413859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
43426929Smisaki 	    xcvr_portn));
43433859Sml29623 
43445780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
43453859Sml29623 
43463859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
43476929Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
43483859Sml29623 		goto fail;
43493859Sml29623 
43505780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43513859Sml29623 
43523859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
43536929Smisaki 	    xcvr_portn));
43543859Sml29623 	return (NXGE_OK);
43553859Sml29623 fail:
43565780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43573859Sml29623 
43583859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43596929Smisaki 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
43603859Sml29623 
43613859Sml29623 	return (NXGE_ERROR | rs);
43623859Sml29623 }
43633859Sml29623 
43643859Sml29623 
43653859Sml29623 /* Check MII to see if there is any link status change */
43663859Sml29623 
43673859Sml29623 nxge_status_t
43683859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
43693859Sml29623 		nxge_link_state_t *link_up)
43703859Sml29623 {
43713859Sml29623 	p_nxge_param_t	param_arr;
43723859Sml29623 	p_nxge_stats_t	statsp;
43733859Sml29623 	p_mii_regs_t	mii_regs;
43743859Sml29623 	p_mii_bmsr_t	soft_bmsr;
43753859Sml29623 	mii_anar_t	anar;
43763859Sml29623 	mii_anlpar_t	anlpar;
43773859Sml29623 	mii_anar_t	an_common;
43783859Sml29623 	mii_aner_t	aner;
43793859Sml29623 	mii_gsr_t	gsr;
43803859Sml29623 	nxge_status_t	status = NXGE_OK;
43813859Sml29623 
43823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
43833859Sml29623 
43843859Sml29623 	mii_regs = NULL;
43853859Sml29623 	param_arr = nxgep->param_arr;
43863859Sml29623 	statsp = nxgep->statsp;
43873859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
43883859Sml29623 	*link_up = LINK_NO_CHANGE;
43893859Sml29623 
43905196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43915196Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
43925196Ssbehera 	    bmsr.value, bmsr_ints.value));
43935196Ssbehera 
43943859Sml29623 	if (bmsr_ints.bits.link_status) {
43955196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43965196Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
43975196Ssbehera 		    bmsr.value, bmsr_ints.value));
43983859Sml29623 		if (bmsr.bits.link_status) {
43993859Sml29623 			soft_bmsr->bits.link_status = 1;
44005196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44015196Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
44025196Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
44033859Sml29623 		} else {
44043859Sml29623 			statsp->mac_stats.link_up = 0;
44053859Sml29623 			soft_bmsr->bits.link_status = 0;
44063859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44076929Smisaki 			    "Link down cable problem"));
44083859Sml29623 			*link_up = LINK_IS_DOWN;
44093859Sml29623 		}
44103859Sml29623 	}
44113859Sml29623 
44125196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
44135196Ssbehera 	    param_arr[param_autoneg].value) {
44143859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
44153859Sml29623 			if (bmsr.bits.auto_neg_complete)
44163859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
44173859Sml29623 			else
44183859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
44193859Sml29623 		}
44203859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
44213859Sml29623 			statsp->mac_stats.link_T4 = 0;
44223859Sml29623 			statsp->mac_stats.link_speed = 0;
44233859Sml29623 			statsp->mac_stats.link_duplex = 0;
44243859Sml29623 			statsp->mac_stats.link_asmpause = 0;
44253859Sml29623 			statsp->mac_stats.link_pause = 0;
44263859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
44273859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
44283859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
44293859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
44303859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
44313859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
44323859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
44333859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
44343859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
44353859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
44363859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
44373859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
44383859Sml29623 		}
44393859Sml29623 	} else
44403859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
44413859Sml29623 
44423859Sml29623 	if ((bmsr_ints.bits.link_status ||
44436929Smisaki 	    bmsr_ints.bits.auto_neg_complete) &&
44446929Smisaki 	    soft_bmsr->bits.link_status &&
44456929Smisaki 	    soft_bmsr->bits.auto_neg_complete) {
44463859Sml29623 		statsp->mac_stats.link_up = 1;
44475196Ssbehera 
44485196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44495196Ssbehera 		    "==> nxge_mii_check "
44505196Ssbehera 		    "(auto negotiation complete or link up) "
44515196Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
44525196Ssbehera 		    bmsr.value, bmsr_ints.value));
44535196Ssbehera 
44545196Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
44555196Ssbehera 		    param_arr[param_autoneg].value) {
44563859Sml29623 			if ((status = nxge_mii_read(nxgep,
44576929Smisaki 			    statsp->mac_stats.xcvr_portn,
44585125Sjoycey #if defined(__i386)
44596929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anar),
44605125Sjoycey #else
44616929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anar),
44625125Sjoycey #endif
44636929Smisaki 			    &anar.value)) != NXGE_OK)
44643859Sml29623 				goto fail;
44653859Sml29623 			if ((status = nxge_mii_read(nxgep,
44666929Smisaki 			    statsp->mac_stats.xcvr_portn,
44675125Sjoycey #if defined(__i386)
44686929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
44695125Sjoycey #else
44706929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
44715125Sjoycey #endif
44726929Smisaki 			    &anlpar.value)) != NXGE_OK)
44733859Sml29623 				goto fail;
44743859Sml29623 			if ((status = nxge_mii_read(nxgep,
44756929Smisaki 			    statsp->mac_stats.xcvr_portn,
44765125Sjoycey #if defined(__i386)
44776929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->aner),
44785125Sjoycey #else
44796929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->aner),
44805125Sjoycey #endif
44816929Smisaki 			    &aner.value)) != NXGE_OK)
44823859Sml29623 				goto fail;
44833859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
44843859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
44853859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
44866929Smisaki 			    anlpar.bits.cap_100fdx;
44873859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
44886929Smisaki 			    anlpar.bits.cap_100hdx;
44893859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
44903859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
44913859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
44926929Smisaki 			    anlpar.bits.cap_asmpause;
44933859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
44943859Sml29623 			an_common.value = anar.value & anlpar.value;
44953859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
44966929Smisaki 			    param_arr[param_anar_1000hdx].value) {
44973859Sml29623 				if ((status = nxge_mii_read(nxgep,
44986929Smisaki 				    statsp->mac_stats.xcvr_portn,
44995125Sjoycey #if defined(__i386)
45006929Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
45015125Sjoycey #else
45026929Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
45035125Sjoycey #endif
45046929Smisaki 				    &gsr.value)) != NXGE_OK)
45053859Sml29623 					goto fail;
45063859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
45076929Smisaki 				    gsr.bits.link_1000fdx;
45083859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
45096929Smisaki 				    gsr.bits.link_1000hdx;
45103859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
45116929Smisaki 				    gsr.bits.link_1000fdx) {
45123859Sml29623 					statsp->mac_stats.link_speed = 1000;
45133859Sml29623 					statsp->mac_stats.link_duplex = 2;
45143859Sml29623 				} else if (
45156929Smisaki 				    param_arr[param_anar_1000hdx].value &&
45166929Smisaki 				    gsr.bits.link_1000hdx) {
45173859Sml29623 					statsp->mac_stats.link_speed = 1000;
45183859Sml29623 					statsp->mac_stats.link_duplex = 1;
45193859Sml29623 				}
45203859Sml29623 			}
45213859Sml29623 			if ((an_common.value != 0) &&
45226929Smisaki 			    !(statsp->mac_stats.link_speed)) {
45233859Sml29623 				if (an_common.bits.cap_100T4) {
45243859Sml29623 					statsp->mac_stats.link_T4 = 1;
45253859Sml29623 					statsp->mac_stats.link_speed = 100;
45263859Sml29623 					statsp->mac_stats.link_duplex = 1;
45273859Sml29623 				} else if (an_common.bits.cap_100fdx) {
45283859Sml29623 					statsp->mac_stats.link_speed = 100;
45293859Sml29623 					statsp->mac_stats.link_duplex = 2;
45303859Sml29623 				} else if (an_common.bits.cap_100hdx) {
45313859Sml29623 					statsp->mac_stats.link_speed = 100;
45323859Sml29623 					statsp->mac_stats.link_duplex = 1;
45333859Sml29623 				} else if (an_common.bits.cap_10fdx) {
45343859Sml29623 					statsp->mac_stats.link_speed = 10;
45353859Sml29623 					statsp->mac_stats.link_duplex = 2;
45363859Sml29623 				} else if (an_common.bits.cap_10hdx) {
45373859Sml29623 					statsp->mac_stats.link_speed = 10;
45383859Sml29623 					statsp->mac_stats.link_duplex = 1;
45393859Sml29623 				} else {
45403859Sml29623 					goto fail;
45413859Sml29623 				}
45423859Sml29623 			}
45433859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
45446929Smisaki 				int	link_pause;
45456929Smisaki 				int	cp, lcp;
45466929Smisaki 
45473859Sml29623 				statsp->mac_stats.link_asmpause =
45486929Smisaki 				    an_common.bits.cap_asmpause;
45496929Smisaki 				cp = statsp->mac_stats.cap_pause;
45506929Smisaki 				lcp = statsp->mac_stats.lp_cap_pause;
45516929Smisaki 				if (statsp->mac_stats.link_asmpause) {
45526929Smisaki 					if ((cp == 0) && (lcp == 1)) {
45536929Smisaki 						link_pause = 0;
45546929Smisaki 					} else {
45556929Smisaki 						link_pause = 1;
45566929Smisaki 					}
45576929Smisaki 				} else {
45586929Smisaki 					link_pause = an_common.bits.cap_pause;
45596929Smisaki 				}
45606929Smisaki 				statsp->mac_stats.link_pause = link_pause;
45613859Sml29623 			}
45625196Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
45635196Ssbehera 			statsp->mac_stats.link_speed = 1000;
45645196Ssbehera 			statsp->mac_stats.link_duplex = 2;
45653859Sml29623 		}
45663859Sml29623 		*link_up = LINK_IS_UP;
45673859Sml29623 	}
45683859Sml29623 
45693859Sml29623 	if (nxgep->link_notify) {
45703859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
45716929Smisaki 		    LINK_IS_DOWN);
45723859Sml29623 		nxgep->link_notify = B_FALSE;
45733859Sml29623 	}
45743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
45753859Sml29623 	return (NXGE_OK);
45763859Sml29623 fail:
45773859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
45786929Smisaki 	    "nxge_mii_check: Unable to check MII"));
45793859Sml29623 	return (status);
45803859Sml29623 }
45813859Sml29623 
45826835Syc148097 /*
45836835Syc148097  * Check PCS to see if there is any link status change.
45846835Syc148097  * This function is called by PORT_1G_SERDES only.
45856835Syc148097  */
45866835Syc148097 void
45874977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
45884977Sraghus {
45894977Sraghus 	p_nxge_stats_t	statsp;
45904977Sraghus 	boolean_t	linkup;
45914977Sraghus 
45924977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
45934977Sraghus 
45944977Sraghus 	statsp = nxgep->statsp;
45954977Sraghus 	*link_up = LINK_NO_CHANGE;
45964977Sraghus 
45974977Sraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
45984977Sraghus 	if (linkup) {
45994977Sraghus 		if (nxgep->link_notify ||
46004977Sraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
46014977Sraghus 			statsp->mac_stats.link_up = 1;
46024977Sraghus 			statsp->mac_stats.link_speed = 1000;
46034977Sraghus 			statsp->mac_stats.link_duplex = 2;
46044977Sraghus 			*link_up = LINK_IS_UP;
46054977Sraghus 			nxgep->link_notify = B_FALSE;
46064977Sraghus 		}
46074977Sraghus 	} else {
46084977Sraghus 		if (nxgep->link_notify ||
46094977Sraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
46104977Sraghus 			statsp->mac_stats.link_up = 0;
46114977Sraghus 			statsp->mac_stats.link_speed = 0;
46124977Sraghus 			statsp->mac_stats.link_duplex = 0;
46134977Sraghus 			*link_up = LINK_IS_DOWN;
46144977Sraghus 			nxgep->link_notify = B_FALSE;
46154977Sraghus 		}
46164977Sraghus 	}
46174977Sraghus 
46184977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
46194977Sraghus }
46204977Sraghus 
46213859Sml29623 /* Add a multicast address entry into the HW hash table */
46223859Sml29623 
46233859Sml29623 nxge_status_t
46243859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
46253859Sml29623 {
46263859Sml29623 	uint32_t mchash;
46273859Sml29623 	p_hash_filter_t hash_filter;
46283859Sml29623 	uint16_t hash_bit;
46293859Sml29623 	boolean_t rx_init = B_FALSE;
46303859Sml29623 	uint_t j;
46313859Sml29623 	nxge_status_t status = NXGE_OK;
46323859Sml29623 
46333859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
46343859Sml29623 
46353859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
46363859Sml29623 	mchash = crc32_mchash(addrp);
46373859Sml29623 	if (nxgep->hash_filter == NULL) {
46383859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
46396929Smisaki 		    "Allocating hash filter storage."));
46403859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
46416929Smisaki 		    KM_SLEEP);
46423859Sml29623 	}
46433859Sml29623 	hash_filter = nxgep->hash_filter;
46443859Sml29623 	j = mchash / HASH_REG_WIDTH;
46453859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
46463859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
46473859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
46483859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
46493859Sml29623 		hash_filter->hash_ref_cnt++;
46503859Sml29623 		rx_init = B_TRUE;
46513859Sml29623 	}
46523859Sml29623 	if (rx_init) {
46533859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
46543859Sml29623 			goto fail;
46553859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
46563859Sml29623 			goto fail;
46573859Sml29623 	}
46583859Sml29623 
46593859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46603859Sml29623 
46613859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
46623859Sml29623 
46633859Sml29623 	return (NXGE_OK);
46643859Sml29623 fail:
46653859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46663859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
46676929Smisaki 	    "Unable to add multicast address"));
46683859Sml29623 	return (status);
46693859Sml29623 }
46703859Sml29623 
46713859Sml29623 /* Remove a multicast address entry from the HW hash table */
46723859Sml29623 
46733859Sml29623 nxge_status_t
46743859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
46753859Sml29623 {
46763859Sml29623 	uint32_t mchash;
46773859Sml29623 	p_hash_filter_t hash_filter;
46783859Sml29623 	uint16_t hash_bit;
46793859Sml29623 	boolean_t rx_init = B_FALSE;
46803859Sml29623 	uint_t j;
46813859Sml29623 	nxge_status_t status = NXGE_OK;
46823859Sml29623 
46833859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
46843859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
46853859Sml29623 	mchash = crc32_mchash(addrp);
46863859Sml29623 	if (nxgep->hash_filter == NULL) {
46873859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
46886929Smisaki 		    "Hash filter already de_allocated."));
46893859Sml29623 		RW_EXIT(&nxgep->filter_lock);
46903859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
46913859Sml29623 		return (NXGE_OK);
46923859Sml29623 	}
46933859Sml29623 	hash_filter = nxgep->hash_filter;
46943859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
46953859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
46963859Sml29623 		j = mchash / HASH_REG_WIDTH;
46973859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
46983859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
46993859Sml29623 		hash_filter->hash_ref_cnt--;
47003859Sml29623 		rx_init = B_TRUE;
47013859Sml29623 	}
47023859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
47033859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
47046929Smisaki 		    "De-allocating hash filter storage."));
47053859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
47063859Sml29623 		nxgep->hash_filter = NULL;
47073859Sml29623 	}
47083859Sml29623 
47093859Sml29623 	if (rx_init) {
47103859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
47113859Sml29623 			goto fail;
47123859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
47133859Sml29623 			goto fail;
47143859Sml29623 	}
47153859Sml29623 	RW_EXIT(&nxgep->filter_lock);
47163859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
47173859Sml29623 
47183859Sml29623 	return (NXGE_OK);
47193859Sml29623 fail:
47203859Sml29623 	RW_EXIT(&nxgep->filter_lock);
47213859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
47226929Smisaki 	    "Unable to remove multicast address"));
47233859Sml29623 
47243859Sml29623 	return (status);
47253859Sml29623 }
47263859Sml29623 
47273859Sml29623 /* Set MAC address into MAC address HW registers */
47283859Sml29623 
47293859Sml29623 nxge_status_t
47303859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
47313859Sml29623 {
47323859Sml29623 	nxge_status_t status = NXGE_OK;
47333859Sml29623 
47343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
47353859Sml29623 
47363859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
47373859Sml29623 	/*
47383859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
47393859Sml29623 	 */
47403859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
47416929Smisaki 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
47426929Smisaki 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
47433859Sml29623 		goto nxge_set_mac_addr_exit;
47443859Sml29623 	}
47453859Sml29623 	nxgep->ouraddr = *addrp;
47463859Sml29623 	/*
47473859Sml29623 	 * Set new interface local address and re-init device.
47483859Sml29623 	 * This is destructive to any other streams attached
47493859Sml29623 	 * to this device.
47503859Sml29623 	 */
47513859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
47523859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
47533859Sml29623 		goto fail;
47543859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
47553859Sml29623 		goto fail;
47563859Sml29623 
47573859Sml29623 	RW_EXIT(&nxgep->filter_lock);
47583859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47593859Sml29623 	goto nxge_set_mac_addr_end;
47603859Sml29623 nxge_set_mac_addr_exit:
47613859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47623859Sml29623 nxge_set_mac_addr_end:
47633859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
47643859Sml29623 
47653859Sml29623 	return (NXGE_OK);
47663859Sml29623 fail:
47673859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47683859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
47696929Smisaki 	    "Unable to set mac address"));
47703859Sml29623 	return (status);
47713859Sml29623 }
47723859Sml29623 
47734693Stm144005 static
47744693Stm144005 check_link_state_t
47756835Syc148097 nxge_check_link_stop(nxge_t *nxge)
47764693Stm144005 {
47774693Stm144005 	/* If the poll has been cancelled, return STOP. */
47784693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
47794693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
47804693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
47814693Stm144005 		nxge->nxge_link_poll_timerid = 0;
47824693Stm144005 		cv_broadcast(&nxge->poll_cv);
47834693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
47844693Stm144005 
47854693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
47864693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
47874693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
47884693Stm144005 		    nxge->mac.portnum));
47894693Stm144005 		return (CHECK_LINK_STOP);
47904693Stm144005 	}
47914693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
47924693Stm144005 
47934693Stm144005 	return (CHECK_LINK_RESCHEDULE);
47944693Stm144005 }
47954693Stm144005 
47966835Syc148097 /*
47976835Syc148097  * Check status of MII (MIF or PCS) link.
47986835Syc148097  * This function is called once per second, that is because this function
47996835Syc148097  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
48006835Syc148097  * call this function recursively.
48016835Syc148097  */
48024732Sdavemq static nxge_status_t
48033859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
48043859Sml29623 {
48053859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
48063859Sml29623 	mii_anlpar_t anlpar;
48073859Sml29623 	mii_gsr_t gsr;
48083859Sml29623 	p_mii_regs_t mii_regs;
48093859Sml29623 	nxge_status_t status = NXGE_OK;
48103859Sml29623 	uint8_t portn;
48113859Sml29623 	nxge_link_state_t link_up;
48123859Sml29623 
48134693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
48144693Stm144005 		return (NXGE_ERROR);
48154693Stm144005 
48164693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
48174693Stm144005 		return (NXGE_OK);
48184693Stm144005 
48193859Sml29623 	portn = nxgep->mac.portnum;
48203859Sml29623 
48213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
48224693Stm144005 	    portn));
48233859Sml29623 
48243859Sml29623 	mii_regs = NULL;
48253859Sml29623 
48263859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
48273859Sml29623 
48283859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
48293859Sml29623 		goto nxge_check_mii_link_exit;
48303859Sml29623 
48314977Sraghus 	switch (nxgep->mac.portmode) {
48324977Sraghus 	default:
48335196Ssbehera 		bmsr_data.value = 0;
48343859Sml29623 		if ((status = nxge_mii_read(nxgep,
48354977Sraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
48365125Sjoycey #if defined(__i386)
48375125Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
48385125Sjoycey #else
48394977Sraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
48405125Sjoycey #endif
48414977Sraghus 		    &bmsr_data.value)) != NXGE_OK) {
48423859Sml29623 			goto fail;
48433859Sml29623 		}
48444977Sraghus 
48455196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48465196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
48475196Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
48485572Ssbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
48495196Ssbehera 
48504977Sraghus 		if (nxgep->param_arr[param_autoneg].value) {
48514977Sraghus 			if ((status = nxge_mii_read(nxgep,
48526929Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
48535125Sjoycey #if defined(__i386)
48546929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
48555125Sjoycey #else
48566929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
48575125Sjoycey #endif
48586929Smisaki 			    &gsr.value)) != NXGE_OK)
48594977Sraghus 				goto fail;
48604977Sraghus 			if ((status = nxge_mii_read(nxgep,
48616929Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
48625125Sjoycey #if defined(__i386)
48636929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
48645125Sjoycey #else
48656929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
48665125Sjoycey #endif
48676929Smisaki 			    &anlpar.value)) != NXGE_OK)
48684977Sraghus 				goto fail;
48695196Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
48705196Ssbehera 
48715196Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
48725196Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
48735196Ssbehera 				    gsr.bits.link_1000fdx) ||
48745196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
48755196Ssbehera 				    gsr.bits.link_1000hdx) ||
48765196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
48775196Ssbehera 				    anlpar.bits.cap_100T4) ||
48785196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
48795196Ssbehera 				    anlpar.bits.cap_100fdx) ||
48805196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
48815196Ssbehera 				    anlpar.bits.cap_100hdx) ||
48825196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
48835196Ssbehera 				    anlpar.bits.cap_10fdx) ||
48845196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
48855196Ssbehera 				    anlpar.bits.cap_10hdx))) {
48865196Ssbehera 					bmsr_data.bits.link_status = 0;
48875196Ssbehera 				}
48884977Sraghus 			}
48894977Sraghus 		}
48904977Sraghus 
48914977Sraghus 		/* Workaround for link down issue */
48924977Sraghus 		if (bmsr_data.value == 0) {
48934977Sraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
48944977Sraghus 			goto nxge_check_mii_link_exit;
48954977Sraghus 		}
48964977Sraghus 
48975196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48985196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
48995196Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
49005572Ssbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
49015196Ssbehera 
49024977Sraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
49034977Sraghus 		nxgep->bmsr.value = bmsr_data.value;
49045196Ssbehera 
49055196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49065196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
49075196Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
49085572Ssbehera 		    portn, bmsr_data.value, bmsr_ints.value));
49095196Ssbehera 
49104977Sraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
49114977Sraghus 		    &link_up)) != NXGE_OK) {
49124977Sraghus 			goto fail;
49134977Sraghus 		}
49144977Sraghus 		break;
49154977Sraghus 
49164977Sraghus 	case PORT_1G_SERDES:
49176835Syc148097 		/*
49186835Syc148097 		 * Above default is for all cases except PORT_1G_SERDES.
49196835Syc148097 		 * The default case gets information from the PHY, but a
49206835Syc148097 		 * nxge whose portmode equals PORT_1G_SERDES does not
49216835Syc148097 		 * have a PHY.
49226835Syc148097 		 */
49234977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49244977Sraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
49256835Syc148097 		nxge_pcs_check(nxgep, portn, &link_up);
49264977Sraghus 		break;
49273859Sml29623 	}
49283859Sml29623 
49293859Sml29623 nxge_check_mii_link_exit:
49303859Sml29623 	RW_EXIT(&nxgep->filter_lock);
49313859Sml29623 	if (link_up == LINK_IS_UP) {
49323859Sml29623 		nxge_link_is_up(nxgep);
49333859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
49343859Sml29623 		nxge_link_is_down(nxgep);
49353859Sml29623 	}
49363859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
49373859Sml29623 
49383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
49396929Smisaki 	    portn));
49403859Sml29623 	return (NXGE_OK);
49413859Sml29623 
49423859Sml29623 fail:
49433859Sml29623 	RW_EXIT(&nxgep->filter_lock);
49443859Sml29623 
49453859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
49463859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
49476929Smisaki 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
49483859Sml29623 	return (status);
49493859Sml29623 }
49503859Sml29623 
49513859Sml29623 /*ARGSUSED*/
49524732Sdavemq static nxge_status_t
49533859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
49543859Sml29623 {
49553859Sml29623 	uint8_t		portn;
49563859Sml29623 	nxge_status_t	status = NXGE_OK;
49575422Ssbehera 	boolean_t	link_up;
49584977Sraghus 	uint32_t	val;
49594977Sraghus 	npi_status_t	rs;
49603859Sml29623 
49614693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
49624693Stm144005 		return (NXGE_ERROR);
49634693Stm144005 
49644693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
49654693Stm144005 		return (NXGE_OK);
49664693Stm144005 
49673859Sml29623 	portn = nxgep->mac.portnum;
49685196Ssbehera 	val = 0;
49695196Ssbehera 	rs = NPI_SUCCESS;
49703859Sml29623 
49713859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
49724693Stm144005 	    portn));
49733859Sml29623 
49744977Sraghus 	switch (nxgep->mac.portmode) {
49754977Sraghus 	default:
49765572Ssbehera 		/*
49775572Ssbehera 		 * Check if the phy is present in case of hot swappable phy
49785572Ssbehera 		 */
49795572Ssbehera 		if (nxgep->hot_swappable_phy) {
49805572Ssbehera 			boolean_t phy_present_now = B_FALSE;
49815572Ssbehera 
49825572Ssbehera 			/*
49835572Ssbehera 			 * If this is the 2nd Goa port, then check 2 addresses
49845572Ssbehera 			 * to take care of the Goa NEM card requirements.
49855572Ssbehera 			 */
49865572Ssbehera 			if (portn == 1) {
49875572Ssbehera 				if (nxge_is_phy_present(nxgep,
49886835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
49895572Ssbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
49905572Ssbehera 					phy_present_now = B_TRUE;
49915572Ssbehera 					nxgep->xcvr_addr =
49926835Syc148097 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
49935572Ssbehera 					goto phy_check_done;
49945572Ssbehera 				}
49955572Ssbehera 			}
49965572Ssbehera 			if (nxge_is_phy_present(nxgep,
49976835Syc148097 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
49985572Ssbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
49995572Ssbehera 				nxgep->xcvr_addr =
50006835Syc148097 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
50015572Ssbehera 				phy_present_now = B_TRUE;
50025572Ssbehera 			}
50035572Ssbehera 
50045572Ssbehera phy_check_done:
5005*9599Stc99174@train 			/* Check back-to-back XAUI connect to detect Opus NEM */
5006*9599Stc99174@train 			rs = npi_xmac_xpcs_read(nxgep->npi_handle,
5007*9599Stc99174@train 			    nxgep->mac.portnum, XPCS_REG_STATUS, &val);
5008*9599Stc99174@train 			if (rs != 0)
5009*9599Stc99174@train 				goto fail;
5010*9599Stc99174@train 
5011*9599Stc99174@train 			link_up = B_FALSE;
5012*9599Stc99174@train 			if (val & XPCS_STATUS_LANE_ALIGN) {
5013*9599Stc99174@train 				link_up = B_TRUE;
5014*9599Stc99174@train 			}
5015*9599Stc99174@train 
50165572Ssbehera 			if (nxgep->phy_absent) {
50175572Ssbehera 				if (phy_present_now) {
50185572Ssbehera 				/*
50195572Ssbehera 				 * Detect, Initialize phy and do link up
50205572Ssbehera 				 * set xcvr vals, link_init, nxge_init
50215572Ssbehera 				 */
50225572Ssbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50235572Ssbehera 					    "Hot swappable phy DETECTED!!"));
50245572Ssbehera 					nxgep->phy_absent = B_FALSE;
50255572Ssbehera 					(void) nxge_xcvr_find(nxgep);
50265572Ssbehera 					(void) nxge_link_init(nxgep);
50275572Ssbehera 					if (!(nxgep->drv_state &
50285572Ssbehera 					    STATE_HW_INITIALIZED)) {
50295572Ssbehera 						status = nxge_init(nxgep);
50305572Ssbehera 						if (status != NXGE_OK) {
50315572Ssbehera 							NXGE_ERROR_MSG((nxgep,
50325572Ssbehera 							    NXGE_ERR_CTL,
50335572Ssbehera 							    "Hot swappable "
50345572Ssbehera 							    "phy present, but"
50355572Ssbehera 							    " driver init"
50365572Ssbehera 							    "  failed..."));
50375572Ssbehera 							goto fail;
50385572Ssbehera 						}
50395572Ssbehera 					}
5040*9599Stc99174@train 				} else if (link_up) { /* XAUI linkup, no PHY */
5041*9599Stc99174@train 					/*
5042*9599Stc99174@train 					 * This is the back-to-back XAUI
5043*9599Stc99174@train 					 * connect case for Opus NEM.
5044*9599Stc99174@train 					 */
5045*9599Stc99174@train 					nxgep->statsp->mac_stats.xcvr_inuse =
5046*9599Stc99174@train 					    XPCS_XCVR;
5047*9599Stc99174@train 					nxgep->mac.portmode = PORT_10G_SERDES;
5048*9599Stc99174@train 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5049*9599Stc99174@train 					    "HSP 10G Serdes DETECTED!!"));
5050*9599Stc99174@train 					break;
50515572Ssbehera 				}
50525572Ssbehera 
50535572Ssbehera 				goto start_link_check;
50545572Ssbehera 
50555572Ssbehera 			} else if (!phy_present_now) {
50565572Ssbehera 				/*
50575572Ssbehera 				 * Phy gone, bring link down reset xcvr vals
50585572Ssbehera 				 */
50595572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50605572Ssbehera 				    "Hot swappable phy REMOVED!!"));
50615572Ssbehera 				nxgep->phy_absent = B_TRUE;
50625572Ssbehera 				nxgep->statsp->mac_stats.link_up = 0;
50635572Ssbehera 				nxgep->statsp->mac_stats.link_speed = 0;
50645572Ssbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
50655572Ssbehera 				nxge_link_is_down(nxgep);
50665572Ssbehera 				nxgep->link_notify = B_FALSE;
50675572Ssbehera 
50685572Ssbehera 				(void) nxge_xcvr_find(nxgep);
50695572Ssbehera 
50705572Ssbehera 				goto start_link_check;
50715572Ssbehera 
50725572Ssbehera 			}
50735572Ssbehera 		}
50746604Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
50756835Syc148097 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
50766604Ssbehera 		} else {
50776604Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
50786604Ssbehera 		}
50794977Sraghus 		if (status != NXGE_OK)
50804977Sraghus 			goto fail;
50814977Sraghus 		break;
50824977Sraghus 	case PORT_10G_SERDES:
50834977Sraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
50845422Ssbehera 		    XPCS_REG_STATUS, &val);
50854977Sraghus 		if (rs != 0)
50864977Sraghus 			goto fail;
50874977Sraghus 
50884977Sraghus 		link_up = B_FALSE;
50895422Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
50905422Ssbehera 			link_up = B_TRUE;
50914977Sraghus 		}
50924977Sraghus 
50934977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50944977Sraghus 		    "==> nxge_check_10g_link port<%d> "
50955422Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
50965422Ssbehera 		    portn, val, link_up));
50975422Ssbehera 
50984977Sraghus 		break;
50994977Sraghus 	}
51003859Sml29623 
51013859Sml29623 	if (link_up) {
51023859Sml29623 		if (nxgep->link_notify ||
51036929Smisaki 		    nxgep->statsp->mac_stats.link_up == 0) {
51043859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
51053859Sml29623 				goto fail;
51063859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
51073859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
51083859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
51093859Sml29623 
51103859Sml29623 			nxge_link_is_up(nxgep);
51113859Sml29623 			nxgep->link_notify = B_FALSE;
51123859Sml29623 		}
51133859Sml29623 	} else {
51143859Sml29623 		if (nxgep->link_notify ||
51156929Smisaki 		    nxgep->statsp->mac_stats.link_up == 1) {
51163859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
51173859Sml29623 				goto fail;
51183859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
51196929Smisaki 			    "Link down cable problem"));
51203859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
51213859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
51223859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
51233859Sml29623 
51243859Sml29623 			nxge_link_is_down(nxgep);
51253859Sml29623 			nxgep->link_notify = B_FALSE;
5126*9599Stc99174@train 
5127*9599Stc99174@train 			if (nxgep->mac.portmode == PORT_10G_SERDES) {
5128*9599Stc99174@train 				/*
5129*9599Stc99174@train 				 * NEM was unplugged, set up xcvr table
5130*9599Stc99174@train 				 * to find another xcvr in the future.
5131*9599Stc99174@train 				 */
5132*9599Stc99174@train 				(void) nxge_xcvr_find(nxgep);
5133*9599Stc99174@train 			}
51343859Sml29623 		}
51353859Sml29623 	}
51363859Sml29623 
51375572Ssbehera start_link_check:
51383859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
51393859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
51404693Stm144005 	    portn));
51413859Sml29623 	return (NXGE_OK);
51423859Sml29623 
51433859Sml29623 fail:
51444693Stm144005 	(void) nxge_check_link_stop(nxgep);
51454693Stm144005 
51463859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51474693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
51484693Stm144005 	    portn));
51493859Sml29623 	return (status);
51503859Sml29623 }
51513859Sml29623 
51523859Sml29623 
51533859Sml29623 /* Declare link down */
51543859Sml29623 
51553859Sml29623 void
51563859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
51573859Sml29623 {
51584732Sdavemq 	p_nxge_stats_t statsp;
51594732Sdavemq 	char link_stat_msg[64];
51604732Sdavemq 
51613859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
51623859Sml29623 
51634732Sdavemq 	statsp = nxgep->statsp;
51644732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
51654732Sdavemq 	    statsp->mac_stats.xcvr_portn);
51664732Sdavemq 
51674732Sdavemq 	if (nxge_no_msg == B_FALSE) {
51684732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
51694732Sdavemq 	}
51704732Sdavemq 
51713859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
51723859Sml29623 
51733859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
51743859Sml29623 }
51753859Sml29623 
51763859Sml29623 /* Declare link up */
51773859Sml29623 
51783859Sml29623 void
51793859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
51803859Sml29623 {
51814732Sdavemq 	p_nxge_stats_t statsp;
51824732Sdavemq 	char link_stat_msg[64];
51833859Sml29623 	uint32_t val;
51843859Sml29623 
51853859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
51863859Sml29623 
51874732Sdavemq 	statsp = nxgep->statsp;
51884732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
51894732Sdavemq 	    statsp->mac_stats.xcvr_portn,
51904732Sdavemq 	    statsp->mac_stats.link_speed);
51914732Sdavemq 
51924732Sdavemq 	if (statsp->mac_stats.link_T4)
51934732Sdavemq 		(void) strcat(link_stat_msg, "T4");
51944732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
51954732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
51964732Sdavemq 	else
51974732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
51984732Sdavemq 
51993859Sml29623 
52003859Sml29623 	/* Clean up symbol errors incurred during link transition */
52014977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
52024977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
52033859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
52046929Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
52053859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
52066929Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
52073859Sml29623 	}
52083859Sml29623 
52096835Syc148097 	/*
52106835Syc148097 	 * If the driver was plumbed without a link (therefore auto-negotiation
52116835Syc148097 	 * could not complete), the driver will detect a link up when a cable
52126835Syc148097 	 * conneting to a link partner is plugged into the port. By the time
52136835Syc148097 	 * link-up is detected, auto-negotiation should have completed (The
52146835Syc148097 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
52156835Syc148097 	 * configure the Neptune/NIU according to the newly negotiated speed.
52166835Syc148097 	 * This is necessary only for the TN1010 basad device because only the
52176835Syc148097 	 * TN1010 supports dual speeds.
52186835Syc148097 	 */
52196835Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
52206835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
52216835Syc148097 
52226835Syc148097 		(void) nxge_set_tn1010_param(nxgep);
52236835Syc148097 
52246835Syc148097 		/*
52256835Syc148097 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
52266835Syc148097 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
52276835Syc148097 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
52286835Syc148097 		 */
52296835Syc148097 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
52306835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
52316835Syc148097 			    "nxge_link_is_up: nxge_xcvr_find failed"));
52326835Syc148097 		}
52336835Syc148097 
52346835Syc148097 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
52356835Syc148097 		if (nxge_link_init(nxgep) != NXGE_OK) {
52366835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
52376835Syc148097 			    "nxge_link_is_up: nxge_link_init failed"));
52386835Syc148097 		}
52396835Syc148097 
52406835Syc148097 		/*
52416835Syc148097 		 * nxge_mac_init calls many subroutines including
52426835Syc148097 		 * nxge_xif_init which sets XGMII or GMII mode
52436835Syc148097 		 */
52446835Syc148097 		if (nxge_mac_init(nxgep) != NXGE_OK) {
52456835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
52466835Syc148097 			    "nxge_link_is_up: nxge_mac_init failed"));
52476835Syc148097 		}
52486835Syc148097 	} else {
52496835Syc148097 		(void) nxge_xif_init(nxgep);
52506835Syc148097 	}
52516835Syc148097 
52524732Sdavemq 	if (nxge_no_msg == B_FALSE) {
52534732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
52544732Sdavemq 	}
52554732Sdavemq 
52563859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
52573859Sml29623 
52583859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
52593859Sml29623 }
52603859Sml29623 
52616835Syc148097 #ifdef NXGE_DEBUG
52626835Syc148097 /* Dump all TN1010 Status registers */
52636835Syc148097 static void
52646835Syc148097 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
52656835Syc148097 {
52666835Syc148097 	uint16_t val;
52676835Syc148097 
52686835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52696835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
52706835Syc148097 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
52716835Syc148097 
52726835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52736835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
52746835Syc148097 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
52756835Syc148097 
52766835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52776835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
52786835Syc148097 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
52796835Syc148097 
52806835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52816835Syc148097 	    TN1010_PCS_DEV_ADDR, 1, &val);
52826835Syc148097 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
52836835Syc148097 
52846835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52856835Syc148097 	    TN1010_PCS_DEV_ADDR, 8, &val);
52866835Syc148097 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
52876835Syc148097 
52886835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52896835Syc148097 	    TN1010_PCS_DEV_ADDR, 32, &val);
52906835Syc148097 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
52916835Syc148097 
52926835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52936835Syc148097 	    TN1010_PCS_DEV_ADDR, 33, &val);
52946835Syc148097 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
52956835Syc148097 
52966835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52976835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
52986835Syc148097 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
52996835Syc148097 
53006835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53016835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
53026835Syc148097 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
53036835Syc148097 
53046835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53056835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
53066835Syc148097 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
53076835Syc148097 
53086835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53096835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
53106835Syc148097 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
53116835Syc148097 
53126835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53136835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
53146835Syc148097 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
53156835Syc148097 
53166835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53176835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
53186835Syc148097 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
53196835Syc148097 
53206835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53216835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
53226835Syc148097 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
53236835Syc148097 
53246835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53256835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
53266835Syc148097 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
53276835Syc148097 
53286835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53296835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
53306835Syc148097 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
53316835Syc148097 
53326835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
53336835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
53346835Syc148097 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
53356835Syc148097 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
53366835Syc148097 }
53376835Syc148097 #endif
53386835Syc148097 
53393859Sml29623 /*
53403859Sml29623  * Calculate the bit in the multicast address filter
53413859Sml29623  * that selects the given * address.
53423859Sml29623  * Note: For GEM, the last 8-bits are used.
53433859Sml29623  */
53443859Sml29623 uint32_t
53453859Sml29623 crc32_mchash(p_ether_addr_t addr)
53463859Sml29623 {
53473859Sml29623 	uint8_t *cp;
53483859Sml29623 	uint32_t crc;
53493859Sml29623 	uint32_t c;
53503859Sml29623 	int byte;
53513859Sml29623 	int bit;
53523859Sml29623 
53533859Sml29623 	cp = (uint8_t *)addr;
53543859Sml29623 	crc = (uint32_t)0xffffffff;
53553859Sml29623 	for (byte = 0; byte < 6; byte++) {
53563859Sml29623 		c = (uint32_t)cp[byte];
53573859Sml29623 		for (bit = 0; bit < 8; bit++) {
53583859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
53593859Sml29623 				crc = (crc >> 1)^0xedb88320;
53603859Sml29623 			else
53613859Sml29623 				crc = (crc >> 1);
53623859Sml29623 			c >>= 1;
53633859Sml29623 		}
53643859Sml29623 	}
53653859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
53663859Sml29623 }
53673859Sml29623 
53683859Sml29623 /* Reset serdes */
53693859Sml29623 
53703859Sml29623 nxge_status_t
53713859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
53723859Sml29623 {
53733859Sml29623 	npi_handle_t		handle;
53743859Sml29623 
53753859Sml29623 	handle = nxgep->npi_handle;
53763859Sml29623 
53773859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
53783859Sml29623 	drv_usecwait(500);
53793859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
53803859Sml29623 
53813859Sml29623 	return (NXGE_OK);
53823859Sml29623 }
53833859Sml29623 
53846835Syc148097 /*
53856835Syc148097  * This function monitors link status using interrupt or polling.
53866835Syc148097  * It calls nxgep->xcvr.check_link, a member function of
53876835Syc148097  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
53886835Syc148097  * function back, that is why the check_link routine is
53896835Syc148097  * executed periodically.
53906835Syc148097  */
53913859Sml29623 nxge_status_t
53923859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
53933859Sml29623 {
53943859Sml29623 	nxge_status_t status = NXGE_OK;
53953859Sml29623 
53966495Sspeer 	/* If we are a guest domain driver, don't bother. */
53976495Sspeer 	if (isLDOMguest(nxgep))
53986495Sspeer 		return (status);
53996495Sspeer 
54003859Sml29623 	/*
54014693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
54024693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
54033859Sml29623 	 */
54044977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
54054977Sraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
54064977Sraghus 	    (nxgep->mac.portnum > 1))
54073859Sml29623 		return (NXGE_OK);
54083859Sml29623 
54093859Sml29623 	if (nxgep->statsp == NULL) {
54103859Sml29623 		/* stats has not been allocated. */
54113859Sml29623 		return (NXGE_OK);
54123859Sml29623 	}
54136075Ssbehera 	/* Don't check link if we're in internal loopback mode */
54146075Ssbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
54153859Sml29623 		return (NXGE_OK);
54163859Sml29623 
54173859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54184693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
54194693Stm144005 	    nxgep->mac.portnum, enable));
54203859Sml29623 	if (enable == LINK_MONITOR_START) {
54213859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
54223859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
54234693Stm144005 			    != NXGE_OK)
54243859Sml29623 				goto fail;
54253859Sml29623 		} else {
54264693Stm144005 			timeout_id_t timerid;
54276835Syc148097 			/*
54286835Syc148097 			 * check_link_stop means "Stop the link check", so
54296835Syc148097 			 * we return without starting the timer.
54306835Syc148097 			 */
54314693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
54324693Stm144005 				return (NXGE_OK);
54334693Stm144005 
54346835Syc148097 			/*
54356835Syc148097 			 * Otherwise fire the timer for the nxge to check
54366835Syc148097 			 * the link using the check_link function
54376835Syc148097 			 * of the nxge_xcvr_table and pass "nxgep" as the
54386835Syc148097 			 * argument to the check_link function.
54396835Syc148097 			 */
54404732Sdavemq 			if (nxgep->xcvr.check_link) {
54414732Sdavemq 				timerid = timeout(
54424732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
54434693Stm144005 				    nxgep,
54444693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
54454732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
54464732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
54474732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
54484732Sdavemq 			} else {
54494693Stm144005 				return (NXGE_ERROR);
54503859Sml29623 			}
54513859Sml29623 		}
54523859Sml29623 	} else {
54533859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
54543859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
54554693Stm144005 			    != NXGE_OK)
54563859Sml29623 				goto fail;
54573859Sml29623 		} else {
54584693Stm144005 			clock_t rv;
54594693Stm144005 
54604693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
54614693Stm144005 
54624693Stm144005 			/* If <timerid> == 0, the link monitor has */
54634693Stm144005 			/* never been started, or just now stopped. */
54644693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
54654693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
54664693Stm144005 				return (NXGE_OK);
54674693Stm144005 			}
54684693Stm144005 
54694693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
54704693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
54714693Stm144005 			    &nxgep->poll_lock,
54724693Stm144005 			    ddi_get_lbolt() +
54734693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
54744693Stm144005 			    LINK_MONITOR_PERIOD));
54754693Stm144005 			if (rv == -1) {
54764693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54774693Stm144005 				    "==> stopping port %d: "
54784693Stm144005 				    "cv_timedwait(%d) timed out",
54794693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
54804693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
54813859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
54823859Sml29623 			}
54834693Stm144005 
54844693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
54853859Sml29623 		}
54863859Sml29623 	}
54873859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54884693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
54894693Stm144005 	    nxgep->mac.portnum, enable));
54906495Sspeer 
54913859Sml29623 	return (NXGE_OK);
54923859Sml29623 fail:
54933859Sml29623 	return (status);
54946835Syc148097 
54953859Sml29623 }
54963859Sml29623 
54976835Syc148097 nxge_status_t
54986835Syc148097 nxge_check_tn1010_link(p_nxge_t nxgep)
54996835Syc148097 {
55006835Syc148097 	nxge_status_t	status = NXGE_OK;
55016835Syc148097 	nxge_link_state_t link_up;
55026835Syc148097 
55036835Syc148097 	if (nxgep->nxge_magic != NXGE_MAGIC) {
55046835Syc148097 		/* magic is 0 if driver is not attached */
55056835Syc148097 		return (NXGE_ERROR);
55066835Syc148097 	}
55076835Syc148097 
55086835Syc148097 	/* Link has been stopped, no need to continue */
55096835Syc148097 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
55106835Syc148097 		return (NXGE_OK);
55116835Syc148097 	}
55126835Syc148097 
55136835Syc148097 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
55146835Syc148097 		goto nxge_check_tn1010_link_exit;
55156835Syc148097 
55166835Syc148097 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
55176835Syc148097 		goto fail;
55186835Syc148097 
55196835Syc148097 nxge_check_tn1010_link_exit:
55206835Syc148097 	if (link_up == LINK_IS_UP)
55216835Syc148097 		nxge_link_is_up(nxgep);
55226835Syc148097 	else if (link_up == LINK_IS_DOWN)
55236835Syc148097 		nxge_link_is_down(nxgep);
55246835Syc148097 
55256835Syc148097 	/*
55266835Syc148097 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
55276835Syc148097 	 * which could be THIS function.
55286835Syc148097 	 */
55296835Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
55306835Syc148097 
55316835Syc148097 	return (NXGE_OK);
55326835Syc148097 
55336835Syc148097 fail:
55346835Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
55356835Syc148097 
55366835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55376835Syc148097 	    "nxge_check_tn1010_link: Failed to check link"));
55386835Syc148097 	return (status);
55396835Syc148097 }
55406835Syc148097 
55416835Syc148097 
55426835Syc148097 /*
55436835Syc148097  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
55446835Syc148097  */
55456835Syc148097 static nxge_status_t
55466835Syc148097 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
55476835Syc148097 {
55486835Syc148097 	nxge_status_t	status = NXGE_OK;
55496835Syc148097 	p_nxge_stats_t	statsp;
55506835Syc148097 	uint8_t		phy_port_addr, portn;
55516835Syc148097 	uint16_t	val;
55526835Syc148097 
55536835Syc148097 	*link_up = LINK_NO_CHANGE;
55546835Syc148097 
55556835Syc148097 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
55566835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
55576835Syc148097 	statsp = nxgep->statsp;
55586835Syc148097 
55596835Syc148097 	/* Check if link is up */
55606835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
55616835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
55626835Syc148097 	    != NXGE_OK) {
55636835Syc148097 		goto fail;
55646835Syc148097 	}
55656835Syc148097 	/*
55666835Syc148097 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
55676835Syc148097 	 * portmode and link_speed
55686835Syc148097 	 */
55696835Syc148097 	if (val & TN1010_AN_LINK_STAT_BIT) {
55706835Syc148097 		if (nxgep->link_notify ||
55716835Syc148097 		    nxgep->statsp->mac_stats.link_up == 0) {
55726835Syc148097 			statsp->mac_stats.link_up = 1;
55736835Syc148097 			statsp->mac_stats.link_duplex = 2;
55746835Syc148097 			*link_up = LINK_IS_UP;
55756835Syc148097 			nxgep->link_notify = B_FALSE;
55766835Syc148097 		}
55776835Syc148097 	} else {
55786835Syc148097 		if (nxgep->link_notify ||
55796835Syc148097 		    nxgep->statsp->mac_stats.link_up == 1) {
55806835Syc148097 			statsp->mac_stats.link_up = 0;
55816835Syc148097 			statsp->mac_stats.link_speed = 0;
55826835Syc148097 			statsp->mac_stats.link_duplex = 0;
55836835Syc148097 			*link_up = LINK_IS_DOWN;
55846835Syc148097 			nxgep->link_notify = B_FALSE;
55856835Syc148097 		}
55866835Syc148097 	}
55876835Syc148097 	return (NXGE_OK);
55886835Syc148097 
55896835Syc148097 fail:
55906835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55916835Syc148097 	    "nxge_tn1010_check: Unable to check TN1010"));
55926835Syc148097 	return (status);
55936835Syc148097 }
55946835Syc148097 
55956835Syc148097 
55963859Sml29623 /* Set promiscous mode */
55973859Sml29623 
55983859Sml29623 nxge_status_t
55993859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
56003859Sml29623 {
56013859Sml29623 	nxge_status_t status = NXGE_OK;
56023859Sml29623 
56034732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
56043859Sml29623 
56053859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
56063859Sml29623 
56073859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
56083859Sml29623 
56093859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
56103859Sml29623 		goto fail;
56113859Sml29623 	}
56123859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
56133859Sml29623 		goto fail;
56143859Sml29623 	}
56153859Sml29623 
56163859Sml29623 	RW_EXIT(&nxgep->filter_lock);
56173859Sml29623 
56183859Sml29623 	if (on)
56193859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
56203859Sml29623 	else
56213859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
56223859Sml29623 
56233859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
56243859Sml29623 
56253859Sml29623 	return (NXGE_OK);
56263859Sml29623 fail:
56273859Sml29623 	RW_EXIT(&nxgep->filter_lock);
56283859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
56294732Sdavemq 	    "Unable to set promisc (%d)", on));
56303859Sml29623 
56313859Sml29623 	return (status);
56323859Sml29623 }
56333859Sml29623 
56343859Sml29623 /*ARGSUSED*/
56353859Sml29623 uint_t
56363859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
56373859Sml29623 {
56383859Sml29623 #ifdef	NXGE_DEBUG
56393859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
56403859Sml29623 #endif
56413859Sml29623 #if NXGE_MIF
56423859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
56433859Sml29623 	uint32_t		status;
56443859Sml29623 	npi_handle_t		handle;
56453859Sml29623 	uint8_t			portn;
56463859Sml29623 	p_nxge_stats_t		statsp;
56473859Sml29623 #endif
56483859Sml29623 
56493859Sml29623 #ifdef	NXGE_MIF
56503859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
56513859Sml29623 		nxgep = ldvp->nxgep;
56523859Sml29623 	}
56533859Sml29623 	nxgep = ldvp->nxgep;
56543859Sml29623 #endif
56553859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
56563859Sml29623 
56573859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
56583859Sml29623 	return (DDI_INTR_CLAIMED);
56593859Sml29623 
56603859Sml29623 mif_intr_fail:
56613859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
56623859Sml29623 	return (DDI_INTR_UNCLAIMED);
56633859Sml29623 }
56643859Sml29623 
56653859Sml29623 /*ARGSUSED*/
56663859Sml29623 uint_t
56673859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
56683859Sml29623 {
56693859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
56703859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
56713859Sml29623 	p_nxge_ldg_t		ldgp;
56723859Sml29623 	uint32_t		status;
56733859Sml29623 	npi_handle_t		handle;
56743859Sml29623 	uint8_t			portn;
56753859Sml29623 	p_nxge_stats_t		statsp;
56763859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
56773859Sml29623 
56783859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
56793859Sml29623 		nxgep = ldvp->nxgep;
56803859Sml29623 	}
56813859Sml29623 
56823859Sml29623 	ldgp = ldvp->ldgp;
56833859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
56844732Sdavemq 	    "group %d", ldgp->ldg));
56853859Sml29623 
56863859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
56873859Sml29623 	/*
56883859Sml29623 	 * This interrupt handler is for a specific
56893859Sml29623 	 * mac port.
56903859Sml29623 	 */
56913859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
56923859Sml29623 	portn = nxgep->mac.portnum;
56933859Sml29623 
56943859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
56954732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
56963859Sml29623 
56973859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
56983859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
56996929Smisaki 		    (xmac_tx_iconfig_t *)&status);
57003859Sml29623 		if (rs != NPI_SUCCESS)
57013859Sml29623 			goto npi_fail;
57023859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
57033859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
57043859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
57053859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57066929Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
57073859Sml29623 			}
57083859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
57093859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
57105523Syc148097 				/*
57115523Syc148097 				 * Do not send FMA ereport because this
57125523Syc148097 				 * error does not indicate HW failure.
57135523Syc148097 				 */
57143859Sml29623 			}
57153859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
57163859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
57173859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57186929Smisaki 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
57193859Sml29623 			}
57203859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
57213859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
57223859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57236929Smisaki 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
57243859Sml29623 			}
57253859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
57263859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
57276929Smisaki 				    XTXMAC_BYTE_CNT_MASK;
57283859Sml29623 			}
57293859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
57303859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
57316929Smisaki 				    XTXMAC_FRM_CNT_MASK;
57323859Sml29623 			}
57333859Sml29623 		}
57343859Sml29623 
57353859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
57366929Smisaki 		    (xmac_rx_iconfig_t *)&status);
57373859Sml29623 		if (rs != NPI_SUCCESS)
57383859Sml29623 			goto npi_fail;
57393859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
57403859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
57413859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
57423859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
57433859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
57443859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57456929Smisaki 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
57463859Sml29623 			}
57475523Syc148097 			/*
57485523Syc148097 			 * Do not send FMA ereport for the following 3 errors
57495523Syc148097 			 * because they do not indicate HW failures.
57505523Syc148097 			 */
57513859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
57523859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
57536929Smisaki 				    XRXMAC_CRC_ER_CNT_MASK;
57543859Sml29623 			}
57553859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
57563859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
57576929Smisaki 				    MAC_LEN_ER_CNT_MASK;
57583859Sml29623 			}
57593859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
57603859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
57616929Smisaki 				    XRXMAC_CD_VIO_CNT_MASK;
57623859Sml29623 			}
57633859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
57643859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
57656929Smisaki 				    XRXMAC_BT_CNT_MASK;
57663859Sml29623 			}
57673859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
57683859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
57696929Smisaki 				    XRXMAC_HIST_CNT1_MASK;
57703859Sml29623 			}
57713859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
57723859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
57736929Smisaki 				    XRXMAC_HIST_CNT2_MASK;
57743859Sml29623 			}
57753859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
57763859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
57776929Smisaki 				    XRXMAC_HIST_CNT3_MASK;
57783859Sml29623 			}
57793859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
57803859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
57816929Smisaki 				    XRXMAC_HIST_CNT4_MASK;
57823859Sml29623 			}
57833859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
57843859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
57856929Smisaki 				    XRXMAC_HIST_CNT5_MASK;
57863859Sml29623 			}
57873859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
57883859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
57896929Smisaki 				    XRXMAC_HIST_CNT6_MASK;
57903859Sml29623 			}
57913859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
57923859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
57936929Smisaki 				    XRXMAC_BC_FRM_CNT_MASK;
57943859Sml29623 			}
57953859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
57963859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
57976929Smisaki 				    XRXMAC_MC_FRM_CNT_MASK;
57983859Sml29623 			}
57995523Syc148097 			/*
58005523Syc148097 			 * Do not send FMA ereport for the following 3 errors
58015523Syc148097 			 * because they do not indicate HW failures.
58025523Syc148097 			 */
58033859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
58043859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
58056929Smisaki 				    XRXMAC_FRAG_CNT_MASK;
58063859Sml29623 			}
58073859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
58083859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
58096929Smisaki 				    XRXMAC_AL_ER_CNT_MASK;
58103859Sml29623 			}
58113859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
58123859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
58136929Smisaki 				    XMAC_LINK_FLT_CNT_MASK;
58143859Sml29623 			}
58153859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
58163859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
58173859Sml29623 			}
58183859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
58193859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
58203859Sml29623 			}
58213859Sml29623 		}
58223859Sml29623 
58233859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
58246929Smisaki 		    (xmac_ctl_iconfig_t *)&status);
58253859Sml29623 		if (rs != NPI_SUCCESS)
58263859Sml29623 			goto npi_fail;
58273859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
58283859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
58293859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
58303859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
58313859Sml29623 				statsp->xmac_stats.tx_pause_state++;
58323859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
58333859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
58343859Sml29623 		}
58353859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
58363859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
58376929Smisaki 		    (bmac_tx_iconfig_t *)&status);
58383859Sml29623 		if (rs != NPI_SUCCESS)
58393859Sml29623 			goto npi_fail;
58403859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
58413859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
58423859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
58433859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58446929Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
58453859Sml29623 			}
58463859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
58473859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
58483859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58496929Smisaki 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
58503859Sml29623 			}
58513859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
58523859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
58536929Smisaki 				    BTXMAC_BYTE_CNT_MASK;
58543859Sml29623 			}
58553859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
58563859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
58576929Smisaki 				    BTXMAC_FRM_CNT_MASK;
58583859Sml29623 			}
58593859Sml29623 		}
58603859Sml29623 
58613859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
58626929Smisaki 		    (bmac_rx_iconfig_t *)&status);
58633859Sml29623 		if (rs != NPI_SUCCESS)
58643859Sml29623 			goto npi_fail;
58653859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
58663859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
58673859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
58683859Sml29623 			}
58693859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
58703859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
58716929Smisaki 				    RXMAC_FRM_CNT_MASK;
58723859Sml29623 			}
58733859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
58743859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
58756929Smisaki 				    BMAC_CRC_ER_CNT_MASK;
58763859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58776929Smisaki 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
58783859Sml29623 			}
58793859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
58803859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
58816929Smisaki 				    MAC_LEN_ER_CNT_MASK;
58823859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58836929Smisaki 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
58843859Sml29623 			}
58853859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
58863859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
58876929Smisaki 				    BMAC_CD_VIO_CNT_MASK;
58883859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58896929Smisaki 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
58903859Sml29623 			}
58913859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
58923859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
58936929Smisaki 				    BRXMAC_BYTE_CNT_MASK;
58943859Sml29623 			}
58953859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
58963859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
58976929Smisaki 				    BMAC_AL_ER_CNT_MASK;
58983859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58996929Smisaki 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
59003859Sml29623 			}
59013859Sml29623 
59023859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
59036929Smisaki 			    (bmac_ctl_iconfig_t *)&status);
59043859Sml29623 			if (rs != NPI_SUCCESS)
59053859Sml29623 				goto npi_fail;
59063859Sml29623 
59073859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
59083859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
59093859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
59103859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
59113859Sml29623 					statsp->bmac_stats.tx_pause_state++;
59123859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
59133859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
59143859Sml29623 			}
59153859Sml29623 		}
59163859Sml29623 
59173859Sml29623 	if (ldgp->nldvs == 1) {
59183859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
59196929Smisaki 		    B_TRUE, ldgp->ldg_timer);
59203859Sml29623 	}
59213859Sml29623 
59223859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
59233859Sml29623 	return (DDI_INTR_CLAIMED);
59243859Sml29623 
59253859Sml29623 npi_fail:
59263859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
59273859Sml29623 	return (DDI_INTR_UNCLAIMED);
59283859Sml29623 }
59293859Sml29623 
59303859Sml29623 nxge_status_t
59313859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
59323859Sml29623 {
59333859Sml29623 	uint8_t		phy_port_addr;
59343859Sml29623 	nxge_status_t	status = NXGE_OK;
59353859Sml29623 	boolean_t	rx_sig_ok;
59363859Sml29623 	boolean_t	pcs_blk_lock;
59373859Sml29623 	boolean_t	link_align;
59383859Sml29623 	uint16_t	val1, val2, val3;
59393859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
59403859Sml29623 	uint16_t	val_debug;
59413859Sml29623 	uint16_t	val;
59423859Sml29623 #endif
59433859Sml29623 
59443859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
59453859Sml29623 
59463859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
59473859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
59483859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
59493859Sml29623 	if ((val_debug & ~0x200) != 0) {
59503859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
59516929Smisaki 		    nxgep->mac.portnum, val_debug);
59523859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
59536929Smisaki 		    &val_debug);
59543859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
59556929Smisaki 		    nxgep->mac.portnum, val_debug);
59563859Sml29623 	}
59573859Sml29623 
59583859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59596929Smisaki 	    XPCS_REG_DESCWERR_COUNTER, &val);
59603859Sml29623 	if (val != 0)
59613859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
59623859Sml29623 
59633859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59646929Smisaki 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
59653859Sml29623 	if (val != 0)
59663859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
59673859Sml29623 
59683859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59696929Smisaki 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
59703859Sml29623 	if (val != 0)
59713859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
59723859Sml29623 #endif
59733859Sml29623 
59743859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
59753859Sml29623 
59763859Sml29623 	/* Check Device 1 Register 0xA bit0 */
59776929Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
59786929Smisaki 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
59793859Sml29623 	if (status != NXGE_OK)
59803859Sml29623 		goto fail;
59813859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
59823859Sml29623 
59833859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
59846929Smisaki 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
59856929Smisaki 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
59863859Sml29623 		goto fail;
59873859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
59883859Sml29623 
59893859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
59906929Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
59916929Smisaki 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
59923859Sml29623 	if (status != NXGE_OK)
59933859Sml29623 		goto fail;
59945572Ssbehera 
59955572Ssbehera 	switch (nxgep->chip_id) {
59965572Ssbehera 	case BCM8704_CHIP_ID:
59975572Ssbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
59985572Ssbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
59995572Ssbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
60005572Ssbehera 		break;
60015572Ssbehera 	case BCM8706_CHIP_ID:
60025572Ssbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
60035572Ssbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
60045572Ssbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
60055572Ssbehera 		    B_TRUE : B_FALSE;
60065572Ssbehera 		break;
60075572Ssbehera 	default:
60085572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
60095572Ssbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
60105572Ssbehera 		goto fail;
60115572Ssbehera 	}
60125572Ssbehera 
60133859Sml29623 
60143859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
60153859Sml29623 	/* Temp workaround for link down issue */
60163859Sml29623 	if (pcs_blk_lock == B_FALSE) {
60173859Sml29623 		if (val2 != 0x4) {
60183859Sml29623 			pcs_blk_lock = B_TRUE;
60196929Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
60206929Smisaki 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
60213859Sml29623 		}
60223859Sml29623 	}
60233859Sml29623 
60243859Sml29623 	if (link_align == B_FALSE) {
60253859Sml29623 		if (val3 != 0x140f) {
60263859Sml29623 			link_align = B_TRUE;
60276929Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
60286929Smisaki 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
60293859Sml29623 		}
60303859Sml29623 	}
60313859Sml29623 
60323859Sml29623 	if (rx_sig_ok == B_FALSE) {
60333859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
60343859Sml29623 			rx_sig_ok = B_TRUE;
60353859Sml29623 			cmn_err(CE_NOTE,
60366929Smisaki 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
60376929Smisaki 			    nxgep->mac.portnum);
60383859Sml29623 		}
60393859Sml29623 	}
60403859Sml29623 #endif
60413859Sml29623 
60423859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
60436929Smisaki 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
60443859Sml29623 
60453859Sml29623 	return (NXGE_OK);
60463859Sml29623 fail:
60473859Sml29623 	return (status);
60483859Sml29623 }
60493859Sml29623 
60506604Ssbehera static nxge_status_t
60516835Syc148097 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
60526604Ssbehera {
60536604Ssbehera 	uint8_t		phy;
60546604Ssbehera 	nxge_status_t   status = NXGE_OK;
60556604Ssbehera 	boolean_t	pma_status;
60566604Ssbehera 	boolean_t	pcs_status;
60576604Ssbehera 	boolean_t	xgxs_status;
60586604Ssbehera 	uint16_t	val;
60596604Ssbehera 
60606604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
60616604Ssbehera 
60626604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
60636604Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
60646604Ssbehera 
60656604Ssbehera 	*link_up = B_FALSE;
60666604Ssbehera 
60676604Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
60686604Ssbehera 
60696604Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
60706604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
60716604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60726604Ssbehera 
60736604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60746604Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
60756604Ssbehera 
60766604Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
60776604Ssbehera 
60786604Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
60796604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
60806604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60816604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
60826604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60836604Ssbehera 
60846604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60856604Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
60866604Ssbehera 
60876604Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
60886604Ssbehera 
60896604Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
60906604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
60916604Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
60926604Ssbehera 
60936604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60946604Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
60956604Ssbehera 
60966604Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
60976604Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
60986604Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
60996604Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
61006604Ssbehera 
61016604Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
61026604Ssbehera 	    B_TRUE : B_FALSE;
61036604Ssbehera 
61046604Ssbehera fail:
61056604Ssbehera 
61066604Ssbehera 	if (*link_up == B_FALSE) {
61076604Ssbehera 		/* PCS OFF */
61086604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
61096604Ssbehera 	} else {
61106604Ssbehera 		/* PCS Activity */
61116604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
61126604Ssbehera 	}
61136604Ssbehera 
61146604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61156604Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
61166604Ssbehera 
61176604Ssbehera 	return (status);
61186604Ssbehera }
61196604Ssbehera 
61203859Sml29623 nxge_status_t
61213859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
61223859Sml29623 {
61233859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
61244732Sdavemq 	    != NPI_SUCCESS)
61253859Sml29623 		return (NXGE_ERROR);
61263859Sml29623 	else
61273859Sml29623 		return (NXGE_OK);
61283859Sml29623 }
61293859Sml29623 
61303859Sml29623 nxge_status_t
61313859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
61323859Sml29623 {
61333859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
61344732Sdavemq 	    != NPI_SUCCESS)
61353859Sml29623 		return (NXGE_ERROR);
61363859Sml29623 	else
61373859Sml29623 		return (NXGE_OK);
61383859Sml29623 }
61394185Sspeer 
61405572Ssbehera static boolean_t
61415572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
61425572Ssbehera {
61435572Ssbehera 	uint32_t pma_pmd_id = 0;
61445572Ssbehera 	uint32_t pcs_id = 0;
61455572Ssbehera 	uint32_t phy_id = 0;
61465572Ssbehera 
61475572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
61485572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61495572Ssbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
61505572Ssbehera 	if ((pma_pmd_id & mask) == (id & mask))
61515572Ssbehera 		goto found_phy;
61525572Ssbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
61535572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61545572Ssbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
61555572Ssbehera 	if ((pcs_id & mask) == (id & mask))
61565572Ssbehera 		goto found_phy;
61575572Ssbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
61585572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61595572Ssbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
61605572Ssbehera 	if ((phy_id & mask) == (id & mask))
61615572Ssbehera 		goto found_phy;
61625572Ssbehera 
61635572Ssbehera 	return (B_FALSE);
61645572Ssbehera 
61655572Ssbehera found_phy:
61665572Ssbehera 	return (B_TRUE);
61675572Ssbehera }
61685572Ssbehera 
61694732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
61704732Sdavemq 
61714732Sdavemq static boolean_t
61724732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
61734732Sdavemq {
61744732Sdavemq 	int		i;
61754732Sdavemq 	boolean_t	found = B_FALSE;
61764732Sdavemq 
61774732Sdavemq 	switch (type) {
61784732Sdavemq 	case CLAUSE_45_TYPE:
61796835Syc148097 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
61806835Syc148097 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
61816835Syc148097 			    (id & BCM_PHY_ID_MASK)) ||
61826835Syc148097 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
61834732Sdavemq 				found = B_TRUE;
61844732Sdavemq 				break;
61854732Sdavemq 			}
61864732Sdavemq 		}
61874732Sdavemq 		break;
61884732Sdavemq 	case CLAUSE_22_TYPE:
61896835Syc148097 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
61904782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
61914782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
61924732Sdavemq 				found = B_TRUE;
61934732Sdavemq 				break;
61944732Sdavemq 			}
61954732Sdavemq 		}
61964732Sdavemq 		break;
61974732Sdavemq 	default:
61984732Sdavemq 		break;
61994732Sdavemq 	}
62004732Sdavemq 
62014732Sdavemq 	return (found);
62024732Sdavemq }
62034732Sdavemq 
62044977Sraghus static uint32_t
62054977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
62064977Sraghus {
62074977Sraghus 	uint16_t	val1 = 0;
62084977Sraghus 	uint16_t	val2 = 0;
62094977Sraghus 	uint32_t	pma_pmd_dev_id = 0;
62104977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62114977Sraghus 
62125780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62134977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
62144977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
62154977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
62164977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
62175780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62184977Sraghus 
62196835Syc148097 	/* Concatenate the Device ID stored in two registers. */
62204977Sraghus 	pma_pmd_dev_id = val1;
62214977Sraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
62224977Sraghus 	pma_pmd_dev_id |= val2;
62234977Sraghus 
62244977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
62254977Sraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
62264977Sraghus 
62274977Sraghus 	return (pma_pmd_dev_id);
62284977Sraghus }
62294977Sraghus 
62304977Sraghus static uint32_t
62314977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
62324977Sraghus {
62334977Sraghus 	uint16_t	val1 = 0;
62344977Sraghus 	uint16_t	val2 = 0;
62354977Sraghus 	uint32_t	pcs_dev_id = 0;
62364977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62374977Sraghus 
62385780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62394977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
62404977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
62414977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
62424977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
62435780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62444977Sraghus 
62454977Sraghus 	pcs_dev_id = val1;
62464977Sraghus 	pcs_dev_id = (pcs_dev_id << 16);
62474977Sraghus 	pcs_dev_id |= val2;
62484977Sraghus 
62494977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
62504977Sraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
62514977Sraghus 
62524977Sraghus 	return (pcs_dev_id);
62534977Sraghus }
62544977Sraghus 
62554977Sraghus static uint32_t
62564977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
62574977Sraghus {
62584977Sraghus 	uint16_t	val1 = 0;
62594977Sraghus 	uint16_t	val2 = 0;
62604977Sraghus 	uint32_t	phy_id = 0;
62614977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62624977Sraghus 	npi_status_t	npi_status = NPI_SUCCESS;
62634977Sraghus 
62646075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62654977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
62664977Sraghus 	    &val1);
62674977Sraghus 	if (npi_status != NPI_SUCCESS) {
62684977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62694977Sraghus 		    "clause 22 read to reg 2 failed!!!"));
62704977Sraghus 		goto exit;
62714977Sraghus 	}
62724977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
62734977Sraghus 	    &val2);
62744977Sraghus 	if (npi_status != 0) {
62754977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62764977Sraghus 		    "clause 22 read to reg 3 failed!!!"));
62774977Sraghus 		goto exit;
62784977Sraghus 	}
62794977Sraghus 	phy_id = val1;
62804977Sraghus 	phy_id = (phy_id << 16);
62814977Sraghus 	phy_id |= val2;
62824977Sraghus 
62834977Sraghus exit:
62846075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62854977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
62864977Sraghus 	    phy_port, phy_id));
62874977Sraghus 
62884977Sraghus 	return (phy_id);
62894977Sraghus }
62904977Sraghus 
62914732Sdavemq /*
62924732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
62934732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
62944732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
62954732Sdavemq  * and the Neptune type.
62966835Syc148097  *
62976835Syc148097  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
62986835Syc148097  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
62996835Syc148097  * in case the portmode information is not available via OBP, nxge.conf,
63006835Syc148097  * VPD or SEEPROM.
63014732Sdavemq  */
63024732Sdavemq nxge_status_t
63034732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
63044732Sdavemq {
63056261Sjoycey 	int		i, j, l;
63064732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
63074732Sdavemq 	uint32_t	pcs_dev_id = 0;
63084732Sdavemq 	uint32_t	phy_id = 0;
63094782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
63104782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
63114782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
63124732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
63134732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
63145572Ssbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
63155572Ssbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
63164732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
63176835Syc148097 	uint8_t		num_xaui;
63184732Sdavemq 	nxge_status_t	status = NXGE_OK;
63194732Sdavemq 
63204732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
63214732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63224732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
63234732Sdavemq 	    nxgep->niu_type));
63244732Sdavemq 
63256495Sspeer 	if (isLDOMguest(nxgep)) {
63266495Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
63276495Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
63286495Sspeer 		return (NXGE_OK);
63296495Sspeer 	}
63306495Sspeer 
63316261Sjoycey 	j = l = 0;
63324732Sdavemq 	total_port_fd = total_phy_fd = 0;
63334732Sdavemq 	/*
63347801SSantwona.Behera@Sun.COM 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
63357801SSantwona.Behera@Sun.COM 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
63364732Sdavemq 	 */
63374732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
63384977Sraghus 
63394977Sraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
63404732Sdavemq 
63414732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
63424732Sdavemq 			pma_pmd_dev_fd[i] = 1;
63434732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
63446604Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
63454782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
63466835Syc148097 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
63476835Syc148097 				    == TN1010_DEV_ID) {
63486835Syc148097 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
63496835Syc148097 				} else {
63506835Syc148097 					port_pma_pmd_dev_id[j] =
63516929Smisaki 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
63526835Syc148097 				}
63535572Ssbehera 				port_fd_arr[j] = (uint8_t)i;
63544732Sdavemq 				j++;
63554732Sdavemq 			}
63564732Sdavemq 		} else {
63574732Sdavemq 			pma_pmd_dev_fd[i] = 0;
63584732Sdavemq 		}
63594732Sdavemq 
63604977Sraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
63614732Sdavemq 
63624732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
63634732Sdavemq 			pcs_dev_fd[i] = 1;
63644732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
63656604Ssbehera 			    "dev %x found", i, pcs_dev_id));
63666261Sjoycey 			if (pma_pmd_dev_fd[i] == 1) {
63676835Syc148097 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
63686835Syc148097 				    == TN1010_DEV_ID) {
63696835Syc148097 					port_pcs_dev_id[j - 1] =
63706835Syc148097 					    TN1010_DEV_ID;
63716835Syc148097 				} else {
63726835Syc148097 					port_pcs_dev_id[j - 1] =
63736835Syc148097 					    pcs_dev_id &
63746835Syc148097 					    BCM_PHY_ID_MASK;
63756835Syc148097 				}
63766261Sjoycey 			} else {
63776261Sjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
63786835Syc148097 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
63796929Smisaki 					    == TN1010_DEV_ID) {
63806835Syc148097 						port_pcs_dev_id[j] =
63816835Syc148097 						    TN1010_DEV_ID;
63826835Syc148097 					} else {
63836835Syc148097 						port_pcs_dev_id[j] =
63846835Syc148097 						    pcs_dev_id &
63856835Syc148097 						    BCM_PHY_ID_MASK;
63866835Syc148097 					}
63876261Sjoycey 					port_fd_arr[j] = (uint8_t)i;
63886261Sjoycey 					j++;
63896261Sjoycey 				}
63904732Sdavemq 			}
63914732Sdavemq 		} else {
63924732Sdavemq 			pcs_dev_fd[i] = 0;
63934732Sdavemq 		}
63944732Sdavemq 
63955572Ssbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
63965572Ssbehera 			total_port_fd ++;
63975572Ssbehera 		}
63984732Sdavemq 
63994977Sraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
64004732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
64015572Ssbehera 			total_phy_fd ++;
64024732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
64036604Ssbehera 			    "%x found", i, phy_id));
64044782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
64056835Syc148097 				if ((phy_id & TN1010_DEV_ID_MASK)
64066835Syc148097 				    == TN1010_DEV_ID) {
64076835Syc148097 					port_phy_id[l] = TN1010_DEV_ID;
64086835Syc148097 				} else {
64096835Syc148097 					port_phy_id[l]
64106835Syc148097 					    = phy_id & BCM_PHY_ID_MASK;
64116835Syc148097 				}
64125572Ssbehera 				phy_fd_arr[l] = (uint8_t)i;
64134732Sdavemq 				l++;
64144732Sdavemq 			}
64154732Sdavemq 		}
64164732Sdavemq 	}
64174732Sdavemq 
64184732Sdavemq 	switch (total_port_fd) {
64194732Sdavemq 	case 2:
64204732Sdavemq 		switch (total_phy_fd) {
64214732Sdavemq 		case 2:
64227801SSantwona.Behera@Sun.COM 			/* 2 10G, 2 1G RGMII Fiber / copper */
64236261Sjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
64246261Sjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
64256261Sjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
64266261Sjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
64276261Sjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
64286261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
64296261Sjoycey 
64307801SSantwona.Behera@Sun.COM 				switch (hw_p->platform_type) {
64317801SSantwona.Behera@Sun.COM 				case P_NEPTUNE_ROCK:
64327801SSantwona.Behera@Sun.COM 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
64337801SSantwona.Behera@Sun.COM 					/*
64347801SSantwona.Behera@Sun.COM 					 * ROCK platform has assigned a lower
64357801SSantwona.Behera@Sun.COM 					 * addr to port 1. (port 0 = 0x9 and
64367801SSantwona.Behera@Sun.COM 					 * port 1 = 0x8).
64377801SSantwona.Behera@Sun.COM 					 */
64387801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[1] = port_fd_arr[0];
64397801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[0] = port_fd_arr[1];
64407801SSantwona.Behera@Sun.COM 
64417801SSantwona.Behera@Sun.COM 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64427801SSantwona.Behera@Sun.COM 					    "Rock with 2 10G, 2 1GC"));
64437801SSantwona.Behera@Sun.COM 					break;
64447801SSantwona.Behera@Sun.COM 
64457801SSantwona.Behera@Sun.COM 				case P_NEPTUNE_NONE:
64467801SSantwona.Behera@Sun.COM 				default:
64477801SSantwona.Behera@Sun.COM 					hw_p->platform_type =
64487801SSantwona.Behera@Sun.COM 					    P_NEPTUNE_GENERIC;
64497801SSantwona.Behera@Sun.COM 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
64507801SSantwona.Behera@Sun.COM 
64517801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[0] = port_fd_arr[0];
64527801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[1] = port_fd_arr[1];
64537801SSantwona.Behera@Sun.COM 
64547801SSantwona.Behera@Sun.COM 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64557801SSantwona.Behera@Sun.COM 					    "ARTM card with 2 10G, 2 1GF"));
64567801SSantwona.Behera@Sun.COM 					break;
64577801SSantwona.Behera@Sun.COM 				}
64587801SSantwona.Behera@Sun.COM 
64596261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
64606261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
64616261Sjoycey 
64626261Sjoycey 			} else {
64636261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64646261Sjoycey 				    "Unsupported neptune type 1"));
64656261Sjoycey 				goto error_exit;
64666261Sjoycey 			}
64676261Sjoycey 			break;
64686261Sjoycey 
64694732Sdavemq 		case 1:
64704732Sdavemq 			/* TODO - 2 10G, 1 1G */
64714732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64724732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
64734732Sdavemq 			goto error_exit;
64744732Sdavemq 		case 0:
64756835Syc148097 			/*
64766835Syc148097 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
64776835Syc148097 			 * cards, etc.
64786835Syc148097 			 */
64794782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
64804782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
64814782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
64826604Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
64836604Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
64846604Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
64856604Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
64866604Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
64876604Ssbehera 			    (port_pma_pmd_dev_id[1] ==
64886604Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
64894977Sraghus 
64904977Sraghus 				/*
64914977Sraghus 				 * Check the first phy port address against
64924977Sraghus 				 * the known phy start addresses to determine
64934977Sraghus 				 * the platform type.
64944977Sraghus 				 */
64955572Ssbehera 
64965572Ssbehera 				switch (port_fd_arr[0]) {
64976835Syc148097 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
64986604Ssbehera 					/*
64996604Ssbehera 					 * The Marvell case also falls into
65006604Ssbehera 					 * this case as
65016604Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
65026835Syc148097 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
65036604Ssbehera 					 * This is OK for the 2 10G case.
65046604Ssbehera 					 */
65054977Sraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
65064977Sraghus 					hw_p->platform_type =
65074977Sraghus 					    P_NEPTUNE_ATLAS_2PORT;
65085572Ssbehera 					break;
65096835Syc148097 				case GOA_CLAUSE45_PORT_ADDR_BASE:
65105572Ssbehera 					if (hw_p->platform_type !=
65115572Ssbehera 					    P_NEPTUNE_NIU) {
65125572Ssbehera 						hw_p->platform_type =
65135572Ssbehera 						    P_NEPTUNE_GENERIC;
65145572Ssbehera 						hw_p->niu_type =
65155572Ssbehera 						    NEPTUNE_2_10GF;
65165572Ssbehera 					}
65175572Ssbehera 					break;
65185572Ssbehera 				default:
65195572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
65204977Sraghus 					    "Unsupported neptune type 2 - 1"));
65214977Sraghus 					goto error_exit;
65224977Sraghus 				}
65235572Ssbehera 
65245572Ssbehera 				for (i = 0; i < 2; i++) {
65255572Ssbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
65265572Ssbehera 				}
65276835Syc148097 
65286835Syc148097 			/* Both XAUI slots have copper XAUI cards */
65296835Syc148097 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
65306835Syc148097 			    == TN1010_DEV_ID) &&
65316835Syc148097 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
65326835Syc148097 			    == TN1010_DEV_ID)) ||
65336835Syc148097 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
65346835Syc148097 			    == TN1010_DEV_ID) &&
65356835Syc148097 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
65366835Syc148097 			    == TN1010_DEV_ID))) {
65376835Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010;
65386835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
65396835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
65406835Syc148097 
65416835Syc148097 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
65426835Syc148097 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
65436835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
65446835Syc148097 			    == TN1010_DEV_ID) ||
65456835Syc148097 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
65466835Syc148097 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
65476835Syc148097 			    TN1010_DEV_ID)) {
65486835Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
65496835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
65506835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
65516835Syc148097 
65526835Syc148097 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
65536835Syc148097 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
65546835Syc148097 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
65556835Syc148097 			    == TN1010_DEV_ID) ||
65566835Syc148097 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
65576835Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
65586835Syc148097 			    == TN1010_DEV_ID)) {
65596835Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
65606835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
65616835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
65626835Syc148097 
65634732Sdavemq 			} else {
65644732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
65654732Sdavemq 				    "Unsupported neptune type 2"));
65664732Sdavemq 				goto error_exit;
65674732Sdavemq 			}
65684732Sdavemq 			break;
65696835Syc148097 
65704732Sdavemq 		case 4:
65716835Syc148097 			if (nxge_get_num_of_xaui(
65726835Syc148097 			    port_pma_pmd_dev_id, port_pcs_dev_id,
65736835Syc148097 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
65746835Syc148097 				goto error_exit;
65756835Syc148097 			}
65766835Syc148097 			if (num_xaui != 2)
65776835Syc148097 				goto error_exit;
65786835Syc148097 
65796835Syc148097 			/*
65806835Syc148097 			 *  Maramba with 2 XAUIs (either fiber or copper)
65816835Syc148097 			 *
65826835Syc148097 			 * Check the first phy port address against
65836835Syc148097 			 * the known phy start addresses to determine
65846835Syc148097 			 * the platform type.
65856835Syc148097 			 */
65866835Syc148097 			switch (phy_fd_arr[0]) {
65876835Syc148097 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
65886835Syc148097 				hw_p->platform_type =
65896835Syc148097 				    P_NEPTUNE_MARAMBA_P0;
65906835Syc148097 				break;
65916835Syc148097 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
65926835Syc148097 				hw_p->platform_type =
65936835Syc148097 				    P_NEPTUNE_MARAMBA_P1;
65946835Syc148097 				break;
65956835Syc148097 			default:
65966835Syc148097 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
65976835Syc148097 				    "Unknown port %d...Cannot "
65986835Syc148097 				    "determine platform type", i));
65996835Syc148097 				goto error_exit;
66006835Syc148097 			}
66016835Syc148097 
66026835Syc148097 			hw_p->xcvr_addr[0] = port_fd_arr[0];
66036835Syc148097 			hw_p->xcvr_addr[1] = port_fd_arr[1];
66046835Syc148097 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
66056835Syc148097 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
66066835Syc148097 
66076835Syc148097 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
66086835Syc148097 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
66096835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
66106835Syc148097 			    == TN1010_DEV_ID) {
66116835Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
66126835Syc148097 
66136835Syc148097 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
66146835Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
66156835Syc148097 			    == TN1010_DEV_ID) &&
66166835Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
66176835Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
66186835Syc148097 
66196835Syc148097 			/* Both slots have fiber XAUI */
66206835Syc148097 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
66216835Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
66224977Sraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
66234977Sraghus 
66246835Syc148097 			/* Both slots have copper XAUI */
66256835Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
66266835Syc148097 			    == TN1010_DEV_ID) &&
66276835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
66286835Syc148097 			    == TN1010_DEV_ID) {
66296835Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
66306835Syc148097 
66314732Sdavemq 			} else {
66324732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66334732Sdavemq 				    "Unsupported neptune type 3"));
66344732Sdavemq 				goto error_exit;
66354732Sdavemq 			}
66364732Sdavemq 			break;
66374732Sdavemq 		default:
66384732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66394732Sdavemq 			    "Unsupported neptune type 5"));
66404732Sdavemq 			goto error_exit;
66414732Sdavemq 		}
66424782Ssbehera 		break;
66436835Syc148097 	case 1: 	/* Only one clause45 port */
66446835Syc148097 		switch (total_phy_fd) {	/* Number of clause22 ports */
66454732Sdavemq 		case 3:
66464977Sraghus 			/*
66474977Sraghus 			 * TODO 3 1G, 1 10G mode.
66484977Sraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
66494977Sraghus 			 * 1_10G_3_1G
66504977Sraghus 			 */
66514977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66524977Sraghus 			    "Unsupported neptune type 7"));
66534977Sraghus 			goto error_exit;
66544732Sdavemq 		case 2:
66554732Sdavemq 			/*
66564732Sdavemq 			 * TODO 2 1G, 1 10G mode.
66574732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
66584732Sdavemq 			 * 1_10G_2_1G
66594732Sdavemq 			 */
66604732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66614732Sdavemq 			    "Unsupported neptune type 8"));
66624732Sdavemq 			goto error_exit;
66634732Sdavemq 		case 1:
66644732Sdavemq 			/*
66654732Sdavemq 			 * TODO 1 1G, 1 10G mode.
66664732Sdavemq 			 * Differentiate between 1_1G_1_10G and
66674732Sdavemq 			 * 1_10G_1_1G
66684732Sdavemq 			 */
66694732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66704732Sdavemq 			    "Unsupported neptune type 9"));
66714732Sdavemq 			goto error_exit;
66726835Syc148097 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
66736835Syc148097 			/* Fiber XAUI */
66745572Ssbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
66755572Ssbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
66765572Ssbehera 
66775572Ssbehera 				/*
66785572Ssbehera 				 * Check the first phy port address against
66795572Ssbehera 				 * the known phy start addresses to determine
66805572Ssbehera 				 * the platform type.
66815572Ssbehera 				 */
66825572Ssbehera 
66835572Ssbehera 				switch (port_fd_arr[0]) {
66846835Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
66856835Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
66866835Syc148097 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
66876835Syc148097 					/*
66886835Syc148097 					 * If hw_p->platform_type ==
66896835Syc148097 					 * P_NEPTUNE_NIU, then portmode
66906835Syc148097 					 * is already known, so there is
66916835Syc148097 					 * no need to figure out hw_p->
66926835Syc148097 					 * platform_type because
66936835Syc148097 					 * platform_type is only for
66946835Syc148097 					 * figuring out portmode.
66956835Syc148097 					 */
66965572Ssbehera 					if (hw_p->platform_type !=
66975572Ssbehera 					    P_NEPTUNE_NIU) {
66985572Ssbehera 						hw_p->platform_type =
66995572Ssbehera 						    P_NEPTUNE_GENERIC;
67005572Ssbehera 						hw_p->niu_type =
67015572Ssbehera 						    NEPTUNE_2_10GF;
67025572Ssbehera 					}
67035572Ssbehera 					break;
67045572Ssbehera 				default:
67055572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67065572Ssbehera 					    "Unsupported neptune type 10"));
67075572Ssbehera 					goto error_exit;
67085572Ssbehera 				}
67096075Ssbehera 				/*
67106075Ssbehera 				 * For GOA, which is a hot swappable PHY, the
67116075Ssbehera 				 * phy address to function number mapping
67126075Ssbehera 				 * should be preserved, i.e., addr 16 is
67136075Ssbehera 				 * assigned to function 0 and 20 to function 1
67146075Ssbehera 				 * But for Huron XAUI, the assignment should
67156075Ssbehera 				 * be by function number, i.e., whichever
67166075Ssbehera 				 * function number attaches should be
67176075Ssbehera 				 * assigned the available PHY (this is required
67186075Ssbehera 				 * primarily to support pre-production Huron
67196075Ssbehera 				 * boards where function 0 is mapped to addr 17
67206075Ssbehera 				 */
67216075Ssbehera 				if (port_fd_arr[0] ==
67226835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
67236075Ssbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
67246075Ssbehera 				} else {
67256075Ssbehera 					hw_p->xcvr_addr[nxgep->function_num] =
67266075Ssbehera 					    port_fd_arr[0];
67276075Ssbehera 				}
67286835Syc148097 
67296835Syc148097 			/* A 10G copper XAUI in either slot0 or slot1 */
67306835Syc148097 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
67316835Syc148097 			    == TN1010_DEV_ID ||
67326835Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
67336835Syc148097 			    == TN1010_DEV_ID) {
67346835Syc148097 				switch (port_fd_arr[0]) {
67356835Syc148097 				/* The XAUI is in slot0 */
67366835Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
67376835Syc148097 					hw_p->niu_type = NEPTUNE_1_TN1010;
67386835Syc148097 					break;
67396835Syc148097 
67406835Syc148097 				/* The XAUI is in slot1 */
67416835Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
67426835Syc148097 					hw_p->niu_type
67436835Syc148097 					    = NEPTUNE_1_NONE_1_TN1010;
67446835Syc148097 					break;
67456835Syc148097 				default:
67466835Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67476835Syc148097 					    "Unsupported XAUI port address"));
67486835Syc148097 					goto error_exit;
67496835Syc148097 				}
67506835Syc148097 				hw_p->xcvr_addr[nxgep->function_num]
67516835Syc148097 				    = port_fd_arr[0];
67526835Syc148097 
67535572Ssbehera 			} else {
67545572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67556835Syc148097 				    "Unsupported PHY type"));
67565572Ssbehera 				goto error_exit;
67575572Ssbehera 			}
67585572Ssbehera 			break;
67596835Syc148097 		case 4: /* Maramba always have 4 clause 45 ports */
67606835Syc148097 
67614732Sdavemq 			/* Maramba with 1 XAUI */
67626929Smisaki 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
67636929Smisaki 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
67646835Syc148097 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
67656929Smisaki 			    != TN1010_DEV_ID) &&
67666835Syc148097 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
67676929Smisaki 			    != TN1010_DEV_ID)) {
67684732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67694732Sdavemq 				    "Unsupported neptune type 12"));
67704732Sdavemq 				goto error_exit;
67714732Sdavemq 			}
67726929Smisaki 
67736929Smisaki 			/*
67746929Smisaki 			 * Check the first phy port address against
67756929Smisaki 			 * the known phy start addresses to determine
67766929Smisaki 			 * the platform type.
67776929Smisaki 			 */
67786929Smisaki 			switch (phy_fd_arr[0]) {
67796929Smisaki 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
67806929Smisaki 				hw_p->platform_type =
67816929Smisaki 				    P_NEPTUNE_MARAMBA_P0;
67826929Smisaki 				break;
67836929Smisaki 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
67846929Smisaki 				hw_p->platform_type =
67856929Smisaki 				    P_NEPTUNE_MARAMBA_P1;
67866929Smisaki 				break;
67876929Smisaki 			default:
67886929Smisaki 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67896929Smisaki 				    "Unknown port %d...Cannot "
67906929Smisaki 				    "determine platform type 10 - 2",
67916929Smisaki 				    i));
67926929Smisaki 				goto error_exit;
67936929Smisaki 			}
67946929Smisaki 
67956929Smisaki 			/*
67966929Smisaki 			 * Check the clause45 address to determine
67976929Smisaki 			 * if XAUI is in port 0 or port 1.
67986929Smisaki 			 */
67996929Smisaki 			switch (port_fd_arr[0]) {
68006929Smisaki 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
68016929Smisaki 				if (port_pcs_dev_id[0]
68026929Smisaki 				    == PHY_BCM8704_FAMILY ||
68036929Smisaki 				    port_pma_pmd_dev_id[0]
68046929Smisaki 				    == PHY_BCM8704_FAMILY) {
68056929Smisaki 					hw_p->niu_type
68066929Smisaki 					    = NEPTUNE_1_10GF_3_1GC;
68076929Smisaki 				} else {
68086929Smisaki 					hw_p->niu_type
68096929Smisaki 					    = NEPTUNE_1_TN1010_3_1GC;
68106929Smisaki 				}
68116929Smisaki 				hw_p->xcvr_addr[0] = port_fd_arr[0];
68126929Smisaki 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
68136929Smisaki 					hw_p->xcvr_addr[i] =
68146929Smisaki 					    phy_fd_arr[i];
68156929Smisaki 				}
68166929Smisaki 				break;
68176929Smisaki 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
68186929Smisaki 				if (port_pcs_dev_id[0]
68196929Smisaki 				    == PHY_BCM8704_FAMILY ||
68206929Smisaki 				    port_pma_pmd_dev_id[0]
68216929Smisaki 				    == PHY_BCM8704_FAMILY) {
68226929Smisaki 					hw_p->niu_type =
68236929Smisaki 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
68246929Smisaki 				} else {
68256929Smisaki 					hw_p->niu_type =
68266929Smisaki 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
68276929Smisaki 				}
68286929Smisaki 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
68296929Smisaki 				hw_p->xcvr_addr[1] = port_fd_arr[0];
68306929Smisaki 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
68316929Smisaki 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
68326929Smisaki 				break;
68336929Smisaki 			default:
68346929Smisaki 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68356929Smisaki 				    "Unsupported neptune type 11"));
68366929Smisaki 				goto error_exit;
68376929Smisaki 			}
68386929Smisaki 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68396929Smisaki 			    "Maramba with 1 XAUI (fiber or copper)"));
68404732Sdavemq 			break;
68414732Sdavemq 		default:
68424732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68434732Sdavemq 			    "Unsupported neptune type 13"));
68444732Sdavemq 			goto error_exit;
68454732Sdavemq 		}
68464732Sdavemq 		break;
68476835Syc148097 	case 0: /* 4 ports Neptune based NIC */
68484732Sdavemq 		switch (total_phy_fd) {
68494732Sdavemq 		case 4:
68504782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
68514782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
68524782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
68534782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
68544732Sdavemq 
68554732Sdavemq 				/*
68564732Sdavemq 				 * Check the first phy port address against
68574732Sdavemq 				 * the known phy start addresses to determine
68584732Sdavemq 				 * the platform type.
68594732Sdavemq 				 */
68605572Ssbehera 				switch (phy_fd_arr[0]) {
68616835Syc148097 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
68624732Sdavemq 					hw_p->platform_type =
68634732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
68645572Ssbehera 					break;
68656835Syc148097 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
68664977Sraghus 					hw_p->platform_type =
68674977Sraghus 					    P_NEPTUNE_ATLAS_4PORT;
68685572Ssbehera 					break;
68695572Ssbehera 				default:
68704977Sraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68714977Sraghus 					    "Unknown port %d...Cannot "
68724977Sraghus 					    "determine platform type", i));
68734977Sraghus 					goto error_exit;
68744732Sdavemq 				}
68754977Sraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
68765572Ssbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
68775572Ssbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
68785572Ssbehera 				}
68794732Sdavemq 			} else {
68804732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68814732Sdavemq 				    "Unsupported neptune type 14"));
68824732Sdavemq 				goto error_exit;
68834732Sdavemq 			}
68844732Sdavemq 			break;
68854732Sdavemq 		case 3:
68864732Sdavemq 			/* TODO 3 1G mode */
68874732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68884732Sdavemq 			    "Unsupported neptune type 15"));
68894732Sdavemq 			goto error_exit;
68904732Sdavemq 		case 2:
68914732Sdavemq 			/* TODO 2 1G mode */
68926261Sjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
68936261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
68946261Sjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
68956261Sjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
68966261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
68976261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
68986261Sjoycey 			} else {
68996261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69006261Sjoycey 				    "Unsupported neptune type 16"));
69016261Sjoycey 				goto error_exit;
69026261Sjoycey 			}
69034732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69046261Sjoycey 			    "2 RGMII Fiber ports - RTM"));
69056261Sjoycey 			break;
69066261Sjoycey 
69074732Sdavemq 		case 1:
69084732Sdavemq 			/* TODO 1 1G mode */
69094732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69104732Sdavemq 			    "Unsupported neptune type 17"));
69114732Sdavemq 			goto error_exit;
69124732Sdavemq 		default:
69134732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69144732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
69154732Sdavemq 			    total_phy_fd));
69164732Sdavemq 			goto error_exit;
69174732Sdavemq 		}
69184732Sdavemq 		break;
69194732Sdavemq 	default:
69204732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69214732Sdavemq 		    "Unsupported neptune type 19"));
69224732Sdavemq 		goto error_exit;
69234732Sdavemq 	}
69244732Sdavemq 
69254732Sdavemq scan_exit:
69264732Sdavemq 
69274732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
69284732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
69294732Sdavemq 	return (status);
69304732Sdavemq 
69314732Sdavemq error_exit:
69324732Sdavemq 	return (NXGE_ERROR);
69334732Sdavemq }
69344732Sdavemq 
69354185Sspeer boolean_t
69364185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
69374185Sspeer {
69384185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
69394185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
69404185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
69414185Sspeer 		return (B_FALSE);
69424185Sspeer 	else
69434185Sspeer 		return (B_TRUE);
69444185Sspeer }
69454732Sdavemq 
69464732Sdavemq static void
69474732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
69484732Sdavemq 
69494732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
69504732Sdavemq 	uint8_t xcvr_portn;
69514732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
69524732Sdavemq 
69534732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
69544732Sdavemq 
69554732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
69566835Syc148097 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
69574732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
69586835Syc148097 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
69594732Sdavemq 	}
69604732Sdavemq 	/*
69614732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
69624732Sdavemq 	 * swapped with ethernet port number. This is
69634732Sdavemq 	 * designed for better signal integrity in routing.
69644732Sdavemq 	 */
69654732Sdavemq 	switch (portn) {
69664732Sdavemq 	case 0:
69674732Sdavemq 		xcvr_portn += 3;
69684732Sdavemq 		break;
69694732Sdavemq 	case 1:
69704732Sdavemq 		xcvr_portn += 2;
69714732Sdavemq 		break;
69724732Sdavemq 	case 2:
69734732Sdavemq 		xcvr_portn += 1;
69744732Sdavemq 		break;
69754732Sdavemq 	case 3:
69764732Sdavemq 	default:
69774732Sdavemq 		break;
69784732Sdavemq 	}
69794732Sdavemq 
69806075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
69814732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
69824732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
69834732Sdavemq 	if (rs != NPI_SUCCESS) {
69844732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69854732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
69864732Sdavemq 		    "returned error 0x[%x]", rs));
69876075Ssbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
69884732Sdavemq 		return;
69894732Sdavemq 	}
69904732Sdavemq 
69914732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
69924732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
69934732Sdavemq 	if (rs != NPI_SUCCESS) {
69944732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69954732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
69964732Sdavemq 		    "returned error 0x[%x]", rs));
69974732Sdavemq 	}
69984732Sdavemq 
69996075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
70004732Sdavemq }
70015196Ssbehera 
70025196Ssbehera static nxge_status_t
70035196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
70045196Ssbehera {
70055196Ssbehera 	p_nxge_stats_t	statsp;
70065196Ssbehera 	uint8_t		xcvr_portn;
70075196Ssbehera 	p_mii_regs_t	mii_regs;
70085196Ssbehera 	mii_mode_control_stat_t	mode;
70095196Ssbehera 	int		status = NXGE_OK;
70105196Ssbehera 
70115196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
70125196Ssbehera 
70135196Ssbehera 	statsp = nxgep->statsp;
70145196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
70155196Ssbehera 	mii_regs = NULL;
70165196Ssbehera 	mode.value = 0;
70175203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
70185196Ssbehera #if defined(__i386)
70195196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
70205196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
70215196Ssbehera 	    mode.value)) != NXGE_OK) {
70225196Ssbehera 		goto fail;
70235196Ssbehera #else
70245196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
70255196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
70265196Ssbehera 	    mode.value)) != NXGE_OK) {
70275196Ssbehera 		goto fail;
70285196Ssbehera #endif
70295196Ssbehera 	}
70305196Ssbehera #if defined(__i386)
70315196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
70325196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
70335196Ssbehera 	    &mode.value)) != NXGE_OK) {
70345196Ssbehera 		goto fail;
70355196Ssbehera 	}
70365196Ssbehera #else
70375196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
70385196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
70395196Ssbehera 	    &mode.value)) != NXGE_OK) {
70405196Ssbehera 		goto fail;
70415196Ssbehera 	}
70425196Ssbehera #endif
70435196Ssbehera 
70445196Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
70455196Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
70465196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70475196Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
70485196Ssbehera 	}
70495196Ssbehera 
70505196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70515196Ssbehera 	    "nxge_mii_get_link_mode: "
70525196Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
70535203Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
70545196Ssbehera 	    mode.value, nxgep->mac.portmode));
70555196Ssbehera 
70565196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70575196Ssbehera 	    "<== nxge_mii_get_link_mode"));
70585196Ssbehera 	return (status);
70595196Ssbehera fail:
70605196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
70615196Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
70625196Ssbehera 	return (NXGE_ERROR);
70635196Ssbehera }
70645196Ssbehera 
70656439Sml29623 nxge_status_t
70666439Sml29623 nxge_mac_set_framesize(p_nxge_t nxgep)
70676439Sml29623 {
70686439Sml29623 	npi_attr_t		ap;
70696439Sml29623 	uint8_t			portn;
70706439Sml29623 	npi_handle_t		handle;
70716439Sml29623 	npi_status_t		rs = NPI_SUCCESS;
70726439Sml29623 
70736439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
70746439Sml29623 
70756439Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
70766439Sml29623 	handle = nxgep->npi_handle;
70776439Sml29623 
70786439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70796439Sml29623 	    "==> nxge_mac_sec_framesize: port<%d> "
70806439Sml29623 	    "min framesize %d max framesize %d ",
70816439Sml29623 	    portn,
70826439Sml29623 	    nxgep->mac.minframesize,
70836439Sml29623 	    nxgep->mac.maxframesize));
70846439Sml29623 
70856439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
70866439Sml29623 	    MAC_PORT_FRAME_SIZE,
70876439Sml29623 	    nxgep->mac.minframesize,
70886439Sml29623 	    nxgep->mac.maxframesize,
70896439Sml29623 	    rs);
70906439Sml29623 	if (rs != NPI_SUCCESS) {
70916439Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70926439Sml29623 		    "<== nxge_mac_set_framesize: failed to configure "
70936439Sml29623 		    "max/min frame size port %d", portn));
70946439Sml29623 
70956439Sml29623 		return (NXGE_ERROR | rs);
70966439Sml29623 	}
70976439Sml29623 
70986439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70996439Sml29623 	    "<== nxge_mac_set_framesize: port<%d>", portn));
71006439Sml29623 
71016439Sml29623 	return (NXGE_OK);
71026439Sml29623 }
71036439Sml29623 
71046835Syc148097 static nxge_status_t
71056835Syc148097 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
71066835Syc148097     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
71076835Syc148097 {
71086835Syc148097 	uint8_t i;
71096835Syc148097 
71106835Syc148097 	for (i = 0; i < 4; i++) {
71116835Syc148097 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
71126835Syc148097 			return (NXGE_ERROR);
71136835Syc148097 	}
71146835Syc148097 
71156835Syc148097 	*num_xaui = 0;
71166835Syc148097 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
71176835Syc148097 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
71186835Syc148097 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
71196835Syc148097 	    == TN1010_DEV_ID) &&
71206835Syc148097 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
71216835Syc148097 	    == TN1010_DEV_ID))) {
71226835Syc148097 		(*num_xaui) ++;
71236835Syc148097 	}
71246835Syc148097 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
71256835Syc148097 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
71266835Syc148097 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
71276835Syc148097 	    == TN1010_DEV_ID) &&
71286835Syc148097 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
71296835Syc148097 	    == TN1010_DEV_ID))) {
71306835Syc148097 		(*num_xaui) ++;
71316835Syc148097 	}
71326835Syc148097 	return (NXGE_OK);
71336835Syc148097 }
71346835Syc148097 
71356835Syc148097 /*
71366835Syc148097  * Instruction from Teranetics:  Once you detect link is up, go
71376835Syc148097  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
71386835Syc148097  * may want to qualify it by first checking Register 30.1.7:6 and
71396835Syc148097  * making sure it reads "01" (Auto-Neg Complete).
71406835Syc148097  *
71416835Syc148097  * If this function is called when the link is down or before auto-
71426835Syc148097  * negotiation has completed, then the speed of the PHY is not certain.
71436835Syc148097  * In such cases, this function returns 1G as the default speed with
71446835Syc148097  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
71456835Syc148097  * driver based on a default speed because this function will be called
71466835Syc148097  * again when the link comes up.  Returning NXGE_ERROR, which may
71476835Syc148097  * cause brutal chain reaction in caller functions, is not necessary.
71486835Syc148097  */
71496835Syc148097 static nxge_status_t
71506835Syc148097 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
71516835Syc148097 {
71526835Syc148097 	uint8_t		phy_port_addr, autoneg_stat, link_up;
71536835Syc148097 	nxge_status_t	status = NXGE_OK;
71546835Syc148097 	uint16_t	val;
71556835Syc148097 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
71566835Syc148097 
71576835Syc148097 	/* Set default speed to 10G */
71586835Syc148097 	*speed = TN1010_SPEED_10G;
71596835Syc148097 
71606835Syc148097 	/* Set Clause 45 */
71616835Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
71626835Syc148097 
71636835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
71646835Syc148097 
71656835Syc148097 	/* Check Device 1 Register 0xA bit0 for link up status */
71666835Syc148097 	status = nxge_mdio_read(nxgep, phy_port_addr,
71676835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
71686835Syc148097 	if (status != NXGE_OK)
71696835Syc148097 		goto fail;
71706835Syc148097 
71716835Syc148097 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
71726835Syc148097 	    ? B_TRUE : B_FALSE);
71736835Syc148097 	if (link_up == B_FALSE) {
71746835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71756835Syc148097 		    "nxge_get_tn1010_speed: link is down"));
71766835Syc148097 		goto nxge_get_tn1010_speed_exit;
71776835Syc148097 	}
71786835Syc148097 
71796835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
71806835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
71816835Syc148097 	    &val)) != NXGE_OK) {
71826835Syc148097 		goto fail;
71836835Syc148097 	}
71846835Syc148097 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
71856835Syc148097 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
71866835Syc148097 
71876835Syc148097 	/*
71886835Syc148097 	 * Return NXGE_OK even when we can not get a settled speed. In
71896835Syc148097 	 * such case, the speed reported should not be trusted but that
71906835Syc148097 	 * is OK, we will call this function periodically and will get
71916835Syc148097 	 * the correct speed after the link is up.
71926835Syc148097 	 */
71936835Syc148097 	switch (autoneg_stat) {
71946835Syc148097 	case TN1010_AN_IN_PROG:
71956835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71966835Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
71976835Syc148097 		break;
71986835Syc148097 	case TN1010_AN_COMPLETE:
71996835Syc148097 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
72006835Syc148097 		    TN1010_VENDOR_MMD1_DEV_ADDR,
72016835Syc148097 		    TN1010_VENDOR_MMD1_STATUS_REG,
72026835Syc148097 		    &val)) != NXGE_OK) {
72036835Syc148097 			goto fail;
72046835Syc148097 		}
72056835Syc148097 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
72066835Syc148097 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
72076835Syc148097 		break;
72086835Syc148097 	case TN1010_AN_RSVD:
72096835Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72106835Syc148097 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
72116835Syc148097 		break;
72126835Syc148097 	case TN1010_AN_FAILED:
72136835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
72146835Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
72156835Syc148097 		break;
72166835Syc148097 	default:
72176835Syc148097 		break;
72186835Syc148097 	}
72196835Syc148097 nxge_get_tn1010_speed_exit:
72206835Syc148097 	return (NXGE_OK);
72216835Syc148097 fail:
72226835Syc148097 	return (status);
72236835Syc148097 }
72246835Syc148097 
72256835Syc148097 
72266835Syc148097 /*
72276835Syc148097  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
72286835Syc148097  * figures out the speed of the PHY determined by the autonegotiation
72296835Syc148097  * process and sets the following 3 parameters,
72306835Syc148097  * 	nxgep->mac.portmode
72316835Syc148097  *     	nxgep->statsp->mac_stats.link_speed
72326835Syc148097  *	nxgep->statsp->mac_stats.xcvr_inuse
72336835Syc148097  */
72346835Syc148097 static nxge_status_t
72356835Syc148097 nxge_set_tn1010_param(p_nxge_t nxgep)
72366835Syc148097 {
72376835Syc148097 	uint16_t speed;
72386835Syc148097 
72396835Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
72406835Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72416835Syc148097 		    "nxge_set_tn1010_param: "
72426835Syc148097 		    "Failed to get TN1010 speed"));
72436835Syc148097 		return (NXGE_ERROR);
72446835Syc148097 	}
72456835Syc148097 	if (speed == TN1010_SPEED_1G) {
72466835Syc148097 		nxgep->mac.portmode = PORT_1G_TN1010;
72476835Syc148097 		nxgep->statsp->mac_stats.link_speed = 1000;
72486835Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
72496835Syc148097 	} else {
72506835Syc148097 		nxgep->mac.portmode = PORT_10G_TN1010;
72516835Syc148097 		nxgep->statsp->mac_stats.link_speed = 10000;
72526835Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
72536835Syc148097 	}
72546835Syc148097 	return (NXGE_OK);
72556835Syc148097 }
72566835Syc148097 
72575196Ssbehera #ifdef NXGE_DEBUG
72585196Ssbehera static void
72595196Ssbehera nxge_mii_dump(p_nxge_t nxgep)
72605196Ssbehera {
72615196Ssbehera 	p_nxge_stats_t	statsp;
72625196Ssbehera 	uint8_t		xcvr_portn;
72635196Ssbehera 	p_mii_regs_t	mii_regs;
72645196Ssbehera 	mii_bmcr_t	bmcr;
72655196Ssbehera 	mii_bmsr_t	bmsr;
72665196Ssbehera 	mii_idr1_t	idr1;
72675196Ssbehera 	mii_idr2_t	idr2;
72685196Ssbehera 	mii_mode_control_stat_t	mode;
72696495Sspeer 	p_nxge_param_t	param_arr;
72705196Ssbehera 
72715196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
72725196Ssbehera 
72735196Ssbehera 	statsp = nxgep->statsp;
72745196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
72755196Ssbehera 
72765196Ssbehera 	mii_regs = NULL;
72775196Ssbehera 
72785196Ssbehera #if defined(__i386)
72795196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
72805196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
72815196Ssbehera #else
72825196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
72835196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
72845196Ssbehera #endif
72855196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72865196Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
72875196Ssbehera 	    xcvr_portn, bmcr.value));
72885196Ssbehera 
72895196Ssbehera #if defined(__i386)
72905196Ssbehera 	(void) nxge_mii_read(nxgep,
72915196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72925196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
72935196Ssbehera #else
72945196Ssbehera 	(void) nxge_mii_read(nxgep,
72955196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72965196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
72975196Ssbehera #endif
72985196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72995196Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
73005196Ssbehera 	    xcvr_portn, bmsr.value));
73015196Ssbehera 
73025196Ssbehera #if defined(__i386)
73035196Ssbehera 	(void) nxge_mii_read(nxgep,
73045196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
73055196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
73065196Ssbehera #else
73075196Ssbehera 	(void) nxge_mii_read(nxgep,
73085196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
73095196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
73105196Ssbehera #endif
73115196Ssbehera 
73125196Ssbehera 
73135196Ssbehera #if defined(__i386)
73145196Ssbehera 	(void) nxge_mii_read(nxgep,
73155196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
73165196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
73175196Ssbehera #else
73185196Ssbehera 	(void) nxge_mii_read(nxgep,
73195196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
73205196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
73215196Ssbehera #endif
73225196Ssbehera 
73235196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
73245196Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
73255196Ssbehera 	    xcvr_portn, idr1.value));
73265196Ssbehera 
73275196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
73285196Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
73295196Ssbehera 	    xcvr_portn, idr2.value));
73305196Ssbehera 
73315196Ssbehera 	mode.value = 0;
73325203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
73335196Ssbehera 
73345196Ssbehera #if defined(__i386)
73355196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
73365196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
73375196Ssbehera 
73385196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
73395196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
73405196Ssbehera #else
73415196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
73425196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
73435196Ssbehera 
73445196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
73455196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
73465196Ssbehera #endif
73475196Ssbehera 
73485196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
73495196Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
73505196Ssbehera 	    xcvr_portn, mode.value));
73515196Ssbehera }
73525196Ssbehera #endif
7353