xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_mac.c (revision 9232:36814323355d)
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 /*
22*9232SMichael.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);
2784977Sraghus 
2794977Sraghus 	nxgep->mac.portmode = 0;
2805572Ssbehera 	nxgep->xcvr_addr = 0;
2815572Ssbehera 
2825572Ssbehera 	/*
2835572Ssbehera 	 * First check for hot swappable phy property.
2845572Ssbehera 	 */
2855572Ssbehera 	if (nxgep->hot_swappable_phy == B_TRUE) {
2865572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2875572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2885572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
2895572Ssbehera 	} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
2905572Ssbehera 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2915572Ssbehera 	    "hot-swappable-phy") == 1) {
2925572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2935572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
2945572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
2955572Ssbehera 	} else if (nxgep->niu_type == N2_NIU &&
2965572Ssbehera 	    ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
2975572Ssbehera 	    "hot-swappable-phy") == 1) {
2985572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
2995572Ssbehera 		nxgep->mac.portmode = PORT_HSP_MODE;
3005572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
3015572Ssbehera 	}
3025572Ssbehera 
3035572Ssbehera 	/*
3045572Ssbehera 	 * MDIO polling support for Monza RTM card, Goa NEM card
3055572Ssbehera 	 */
3065572Ssbehera 	if (nxgep->mac.portmode == PORT_HSP_MODE) {
3075572Ssbehera 		nxgep->hot_swappable_phy = B_TRUE;
3085572Ssbehera 		/*
3095572Ssbehera 		 * If this is the 2nd NIU port, then check 2 addresses
3105572Ssbehera 		 * to take care of the Goa NEM card. Port 1 can have addr 17
3115572Ssbehera 		 * (in the eval board) or 20 (in the P0 board).
3125572Ssbehera 		 */
3135572Ssbehera 		if (portn == 1) {
3145572Ssbehera 			if (nxge_is_phy_present(nxgep,
3156835Syc148097 			    ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID,
3165572Ssbehera 			    BCM_PHY_ID_MASK)) {
3175572Ssbehera 				nxgep->xcvr_addr =
3186835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR;
3195572Ssbehera 				goto found_phy;
3205572Ssbehera 			}
3215572Ssbehera 		}
3225572Ssbehera 		if (nxge_is_phy_present(nxgep,
3236835Syc148097 		    GOA_CLAUSE45_PORT_ADDR_BASE + portn,
3245572Ssbehera 		    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
3256835Syc148097 			nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE +
3265572Ssbehera 			    portn;
3275572Ssbehera 			goto found_phy;
3285572Ssbehera 		}
3295572Ssbehera 
3305572Ssbehera 		nxgep->phy_absent = B_TRUE;
3315572Ssbehera 		goto check_phy_done;
3325572Ssbehera found_phy:
3335572Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3345572Ssbehera 		nxgep->mac.portmode = PORT_10G_FIBER;
3355572Ssbehera 		nxgep->phy_absent = B_FALSE;
3365572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
3375572Ssbehera 		    "found for hot swappable phy"));
3385572Ssbehera check_phy_done:
3395572Ssbehera 		return (status);
3405572Ssbehera 	}
3415572Ssbehera 
3426835Syc148097 	/* Get phy-type property (May have been set by nxge.conf) */
3434977Sraghus 	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
3444977Sraghus 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
3454977Sraghus 	    "phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
3464977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3474977Sraghus 		    "found  conf file: phy-type %s", prop_val));
3484977Sraghus 		if (strcmp("xgsd", prop_val) == 0) {
3494977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3504977Sraghus 			nxgep->mac.portmode = PORT_10G_SERDES;
3514977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3524977Sraghus 			    "found: 10G Serdes"));
3534977Sraghus 		} else if (strcmp("gsd", prop_val) == 0) {
3544977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3554977Sraghus 			nxgep->mac.portmode = PORT_1G_SERDES;
3564977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
3574977Sraghus 		} else if (strcmp("mif", prop_val) == 0) {
3584977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
3594977Sraghus 			nxgep->mac.portmode = PORT_1G_COPPER;
3604977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
3614977Sraghus 		} else if (strcmp("pcs", prop_val) == 0) {
3624977Sraghus 			nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
3634977Sraghus 			nxgep->mac.portmode = PORT_1G_FIBER;
3644977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
3656075Ssbehera 		} else if (strcmp("xgf", prop_val) == 0) {
3666835Syc148097 			/*
3676835Syc148097 			 * Before OBP supports new phy-type property
3686835Syc148097 			 * value "xgc", the 10G copper XAUI may carry
3696835Syc148097 			 * "xgf" instead of "xgc". If the OBP is
3706835Syc148097 			 * upgraded to a newer version which supports
3716835Syc148097 			 * "xgc", then the TN1010 related code in this
3726835Syc148097 			 * "xgf" case will not be used anymore.
3736835Syc148097 			 */
3746835Syc148097 			if (nxge_is_tn1010_phy(nxgep)) {
3756835Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
3766835Syc148097 				    != NXGE_OK) {
3776835Syc148097 					return (status);
3786835Syc148097 				}
3796835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
3806835Syc148097 			} else {  /* For Fiber XAUI */
3816835Syc148097 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
3826835Syc148097 				nxgep->mac.portmode = PORT_10G_FIBER;
3836835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
3846835Syc148097 				    "10G Fiber Xcvr"));
3856835Syc148097 			}
3866835Syc148097 		} else if (strcmp("xgc", prop_val) == 0) {
3876835Syc148097 			if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
3886835Syc148097 				return (status);
3896835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
3904977Sraghus 		}
3914977Sraghus 
3924977Sraghus 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
3934977Sraghus 		    "phy-type", prop_val);
3944977Sraghus 		ddi_prop_free(prop_val);
3954977Sraghus 
3964977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
3974977Sraghus 		    "Got phy type [0x%x] from conf file",
3984977Sraghus 		    nxgep->mac.portmode));
3994977Sraghus 
4004977Sraghus 		return (NXGE_OK);
4014977Sraghus 	}
4025572Ssbehera 
4035572Ssbehera 	/* Get phy-type property from OBP */
4044977Sraghus 	if (nxgep->niu_type == N2_NIU) {
4054977Sraghus 		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
4064977Sraghus 		    "phy-type", &prop_val) == DDI_PROP_SUCCESS) {
4074977Sraghus 			if (strcmp("xgf", prop_val) == 0) {
4086835Syc148097 				/*
4096835Syc148097 				 * Before OBP supports new phy-type property
4106835Syc148097 				 * value "xgc", the 10G copper XAUI may carry
4116835Syc148097 				 * "xgf" instead of "xgc". If the OBP is
4126835Syc148097 				 * upgraded to a newer version which supports
4136835Syc148097 				 * "xgc", then the TN1010 related code in this
4146835Syc148097 				 * "xgf" case will not be used anymore.
4156835Syc148097 				 */
4166835Syc148097 				if (nxge_is_tn1010_phy(nxgep)) {
4176835Syc148097 					if ((status =
4186835Syc148097 					    nxge_set_tn1010_param(nxgep))
4196835Syc148097 					    != NXGE_OK) {
4206835Syc148097 						return (status);
4216835Syc148097 					}
4226835Syc148097 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4236835Syc148097 					    "TN1010 Xcvr"));
4246835Syc148097 				} else {  /* For Fiber XAUI */
4256835Syc148097 					nxgep->statsp->mac_stats.xcvr_inuse
4266835Syc148097 					    = XPCS_XCVR;
4276835Syc148097 					nxgep->mac.portmode = PORT_10G_FIBER;
4286835Syc148097 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4296835Syc148097 					    "10G Fiber Xcvr"));
4306835Syc148097 				}
4314977Sraghus 			} else if (strcmp("mif", prop_val) == 0) {
4324977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse =
4334977Sraghus 				    INT_MII_XCVR;
4344977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
4354977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4364977Sraghus 				    "1G Copper Xcvr"));
4374977Sraghus 			} else if (strcmp("pcs", prop_val) == 0) {
4384977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4394977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
4404977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4414977Sraghus 				    "1G Fiber Xcvr"));
4424977Sraghus 			} else if (strcmp("xgc", prop_val) == 0) {
4436835Syc148097 				status = nxge_set_tn1010_param(nxgep);
4446835Syc148097 				if (status != NXGE_OK)
4456835Syc148097 					return (status);
4466835Syc148097 				NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
4474977Sraghus 			} else if (strcmp("xgsd", prop_val) == 0) {
4484977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
4494977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
4504977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4514977Sraghus 				    "OBP: 10G Serdes"));
4524977Sraghus 			} else if (strcmp("gsd", prop_val) == 0) {
4534977Sraghus 				nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
4544977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
4554977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4564977Sraghus 				    "OBP: 1G Serdes"));
4574977Sraghus 			} else {
4584977Sraghus 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4594977Sraghus 				    "Unknown phy-type: %s", prop_val));
4604977Sraghus 				ddi_prop_free(prop_val);
4614977Sraghus 				return (NXGE_ERROR);
4624977Sraghus 			}
4634977Sraghus 			status = NXGE_OK;
4644977Sraghus 			(void) ddi_prop_update_string(DDI_DEV_T_NONE,
4654977Sraghus 			    nxgep->dip, "phy-type", prop_val);
4664977Sraghus 			ddi_prop_free(prop_val);
4674977Sraghus 
4684977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
4694977Sraghus 			    "Got phy type [0x%x] from OBP",
4704977Sraghus 			    nxgep->mac.portmode));
4714977Sraghus 
4724977Sraghus 			return (status);
4734977Sraghus 		} else {
4744977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4754977Sraghus 			    "Exiting...phy-type property not found"));
4764977Sraghus 			return (NXGE_ERROR);
4774977Sraghus 		}
4784977Sraghus 	}
4794977Sraghus 
4804977Sraghus 
4814977Sraghus 	if (!nxgep->vpd_info.present) {
4824977Sraghus 		return (NXGE_OK);
4834977Sraghus 	}
4844977Sraghus 
4854977Sraghus 	if (!nxgep->vpd_info.ver_valid) {
4864977Sraghus 		goto read_seeprom;
4874977Sraghus 	}
4884977Sraghus 
4894977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
4904977Sraghus 	    "Reading phy type from expansion ROM"));
4914977Sraghus 	/*
4924977Sraghus 	 * Try to read the phy type from the vpd data read off the
4934977Sraghus 	 * expansion ROM.
4944977Sraghus 	 */
4954977Sraghus 	phy_type = nxgep->vpd_info.phy_type;
4964977Sraghus 
4975196Ssbehera 	if (strncmp(phy_type, "mif", 3) == 0) {
4984977Sraghus 		nxgep->mac.portmode = PORT_1G_COPPER;
4994977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
5005196Ssbehera 	} else if (strncmp(phy_type, "xgf", 3) == 0) {
5014977Sraghus 		nxgep->mac.portmode = PORT_10G_FIBER;
5024977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
5035196Ssbehera 	} else if (strncmp(phy_type, "pcs", 3) == 0) {
5044977Sraghus 		nxgep->mac.portmode = PORT_1G_FIBER;
5054977Sraghus 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5065196Ssbehera 	} else if (strncmp(phy_type, "xgc", 3) == 0) {
5076835Syc148097 		status = nxge_set_tn1010_param(nxgep);
5086835Syc148097 		if (status != NXGE_OK) {
5096835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5106835Syc148097 			    "nxge_get_xcvr_type: Failed to set TN1010 param"));
5116835Syc148097 			goto read_seeprom;
5126835Syc148097 		}
5135196Ssbehera 	} else if (strncmp(phy_type, "xgsd", 4) == 0) {
5145196Ssbehera 		nxgep->mac.portmode = PORT_10G_SERDES;
5155196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
5165196Ssbehera 	} else if (strncmp(phy_type, "gsd", 3) == 0) {
5175196Ssbehera 		nxgep->mac.portmode = PORT_1G_SERDES;
5185196Ssbehera 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
5194977Sraghus 	} else {
5205196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5214977Sraghus 		    "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
5224977Sraghus 		    phy_type[0], phy_type[1], phy_type[2]));
5234977Sraghus 		goto read_seeprom;
5244977Sraghus 	}
5254977Sraghus 
5264977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
5274977Sraghus 	    "Got phy type [0x%x] from VPD", nxgep->mac.portmode));
5284977Sraghus 
5294977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
5304977Sraghus 	return (status);
5314977Sraghus 
5324977Sraghus read_seeprom:
5334977Sraghus 	/*
5344977Sraghus 	 * read the phy type from the SEEPROM - NCR registers
5354977Sraghus 	 */
5364977Sraghus 	status = nxge_espc_phy_type_get(nxgep);
5374977Sraghus 	if (status != NXGE_OK) {
5384977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5394977Sraghus 		    "Failed to get phy type"));
5404977Sraghus 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
5414977Sraghus 		    "[%s] invalid...please update", nxgep->vpd_info.ver));
5424977Sraghus 	}
5434977Sraghus 
5444977Sraghus 	return (status);
5454977Sraghus 
5464977Sraghus }
5474977Sraghus 
5484732Sdavemq /* Set up the PHY specific values. */
5494732Sdavemq 
5504732Sdavemq nxge_status_t
5514732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep)
5524732Sdavemq {
5534732Sdavemq 	nxge_status_t	status = NXGE_OK;
5544732Sdavemq 	uint32_t	port_type;
5554732Sdavemq 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
5564977Sraghus 	uint32_t	pcs_id = 0;
5574977Sraghus 	uint32_t	pma_pmd_id = 0;
5584977Sraghus 	uint32_t	phy_id = 0;
5595572Ssbehera 	uint16_t	chip_id = 0;
5604732Sdavemq 
5614732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
5624732Sdavemq 	    portn));
5634732Sdavemq 
5644977Sraghus 	switch (nxgep->niu_type) {
5654977Sraghus 	case N2_NIU:
5664977Sraghus 		switch (nxgep->mac.portmode) {
5674977Sraghus 		case PORT_1G_FIBER:
5684977Sraghus 		case PORT_1G_SERDES:
5694977Sraghus 			nxgep->xcvr = nxge_n2_1G_table;
5705572Ssbehera 			nxgep->xcvr_addr = portn;
5714977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
5724977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
5734977Sraghus 			    "Serdes"));
5744977Sraghus 			break;
5754977Sraghus 		case PORT_10G_FIBER:
5764977Sraghus 		case PORT_10G_SERDES:
5774977Sraghus 			nxgep->xcvr = nxge_n2_10G_table;
5785572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
5795572Ssbehera 				nxgep->xcvr_addr =
5805572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
5815572Ssbehera 			}
5824977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
5834977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
5844977Sraghus 			    "Serdes"));
5854977Sraghus 			break;
5866835Syc148097 		case PORT_1G_TN1010:
5876835Syc148097 			nxgep->xcvr = nxge_n2_1G_tn1010_table;
5886835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
5896835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5906835Syc148097 			    "TN1010 Copper Xcvr in 1G"));
5916835Syc148097 			break;
5926835Syc148097 		case PORT_10G_TN1010:
5936835Syc148097 			nxgep->xcvr = nxge_n2_10G_tn1010_table;
5946835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
5956835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
5966835Syc148097 			    "TN1010 Copper Xcvr in 10G"));
5976835Syc148097 			break;
5985572Ssbehera 		case PORT_HSP_MODE:
5995572Ssbehera 			nxgep->xcvr = nxge_n2_10G_table;
6005572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
6015572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
6025572Ssbehera 			    "Swappable Xcvr (not present)"));
6035572Ssbehera 			break;
6044977Sraghus 		default:
6054977Sraghus 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6064977Sraghus 			    "<== nxge_setup_xcvr_table: "
6074977Sraghus 			    "Unable to determine NIU portmode"));
6084977Sraghus 			return (NXGE_ERROR);
6094977Sraghus 		}
6104977Sraghus 		break;
6114977Sraghus 	default:
6124977Sraghus 		if (nxgep->mac.portmode == 0) {
6134977Sraghus 			/*
6144977Sraghus 			 * Would be the case for platforms like Maramba
6154977Sraghus 			 * in which the phy type could not be got from conf
6164977Sraghus 			 * file, OBP, VPD or Serial PROM.
6174977Sraghus 			 */
6184977Sraghus 			if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
6194977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6204977Sraghus 				    "<== nxge_setup_xcvr_table:"
6214977Sraghus 				    " Invalid Neptune type [0x%x]",
6224977Sraghus 				    nxgep->niu_type));
6234977Sraghus 				return (NXGE_ERROR);
6244977Sraghus 			}
6254977Sraghus 
6264977Sraghus 			port_type = nxgep->niu_type >>
6274977Sraghus 			    (NXGE_PORT_TYPE_SHIFT * portn);
6284977Sraghus 			port_type = port_type & (NXGE_PORT_TYPE_MASK);
6294977Sraghus 
6304977Sraghus 			switch (port_type) {
6314977Sraghus 
6324977Sraghus 			case NXGE_PORT_1G_COPPER:
6334977Sraghus 				nxgep->mac.portmode = PORT_1G_COPPER;
6344977Sraghus 				break;
6354977Sraghus 			case NXGE_PORT_10G_COPPER:
6364977Sraghus 				nxgep->mac.portmode = PORT_10G_COPPER;
6374977Sraghus 				break;
6384977Sraghus 			case NXGE_PORT_1G_FIBRE:
6394977Sraghus 				nxgep->mac.portmode = PORT_1G_FIBER;
6404977Sraghus 				break;
6414977Sraghus 			case NXGE_PORT_10G_FIBRE:
6424977Sraghus 				nxgep->mac.portmode = PORT_10G_FIBER;
6434977Sraghus 				break;
6444977Sraghus 			case NXGE_PORT_1G_SERDES:
6454977Sraghus 				nxgep->mac.portmode = PORT_1G_SERDES;
6464977Sraghus 				break;
6474977Sraghus 			case NXGE_PORT_10G_SERDES:
6484977Sraghus 				nxgep->mac.portmode = PORT_10G_SERDES;
6494977Sraghus 				break;
6506835Syc148097 			/* Ports 2 and 3 of Alonso or ARTM */
6514977Sraghus 			case NXGE_PORT_1G_RGMII_FIBER:
6524977Sraghus 				nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
6534977Sraghus 				break;
6546835Syc148097 			case NXGE_PORT_TN1010:
6556835Syc148097 				/*
6566835Syc148097 				 * If this port uses the TN1010 copper
6576835Syc148097 				 * PHY, then its speed is not known yet
6586835Syc148097 				 * because nxge_scan_ports_phy could only
6596835Syc148097 				 * figure out the vendor of the PHY but
6606835Syc148097 				 * not its speed. nxge_set_tn1010_param
6616835Syc148097 				 * will read the PHY speed and set
6626835Syc148097 				 * portmode accordingly.
6636835Syc148097 				 */
6646835Syc148097 				if ((status = nxge_set_tn1010_param(nxgep))
6656835Syc148097 				    != NXGE_OK) {
6666835Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6676835Syc148097 					    "nxge_set_tn1010_param failed"));
6686835Syc148097 					return (status);
6696835Syc148097 				}
6706835Syc148097 				break;
6714977Sraghus 			default:
6724977Sraghus 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
6734977Sraghus 				    "<== nxge_setup_xcvr_table: "
6744977Sraghus 				    "Unknown port-type: 0x%x", port_type));
6754977Sraghus 				return (NXGE_ERROR);
6764977Sraghus 			}
6774977Sraghus 		}
6784977Sraghus 
6796835Syc148097 		/*
6806835Syc148097 		 * Above switch has figured out nxge->mac.portmode, now set
6816835Syc148097 		 * nxgep->xcvr (the table) and nxgep->xcvr_addr according
6826835Syc148097 		 * to portmode.
6836835Syc148097 		 */
6844977Sraghus 		switch (nxgep->mac.portmode) {
6854977Sraghus 		case PORT_1G_COPPER:
6864977Sraghus 		case PORT_1G_RGMII_FIBER:
6874732Sdavemq 			nxgep->xcvr = nxge_1G_copper_table;
6885572Ssbehera 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
6894732Sdavemq 			/*
6904732Sdavemq 			 * For Altas 4-1G copper, Xcvr port numbers are
6914732Sdavemq 			 * swapped with ethernet port number. This is
6924977Sraghus 			 * designed for better signal integrity in
6934977Sraghus 			 * routing. This is also the case for the
6944977Sraghus 			 * on-board Neptune copper ports on the Maramba
6954977Sraghus 			 * platform.
6964732Sdavemq 			 */
6974977Sraghus 			switch (nxgep->platform_type) {
6984977Sraghus 			case P_NEPTUNE_ATLAS_4PORT:
6994977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
7004977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
7014977Sraghus 				switch (portn) {
7024977Sraghus 				case 0:
7035572Ssbehera 					nxgep->xcvr_addr += 3;
7044977Sraghus 					break;
7054977Sraghus 				case 1:
7065572Ssbehera 					nxgep->xcvr_addr += 1;
7074977Sraghus 					break;
7084977Sraghus 				case 2:
7095572Ssbehera 					nxgep->xcvr_addr -= 1;
7104977Sraghus 					break;
7114977Sraghus 				case 3:
7125572Ssbehera 					nxgep->xcvr_addr -= 3;
7134977Sraghus 					break;
7144977Sraghus 				default:
7154977Sraghus 					return (NXGE_ERROR);
7164977Sraghus 				}
7174732Sdavemq 				break;
7184732Sdavemq 			default:
7194977Sraghus 				break;
7204732Sdavemq 			}
7215196Ssbehera 
7224977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7234977Sraghus 			    (nxgep->mac.portmode == PORT_1G_COPPER) ?
7244977Sraghus 			    "Copper" : "RGMII Fiber"));
7254732Sdavemq 			break;
7266835Syc148097 
7274977Sraghus 		case PORT_10G_COPPER:
7284732Sdavemq 			nxgep->xcvr = nxge_10G_copper_table;
7294732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
7304732Sdavemq 			break;
7316835Syc148097 
7326835Syc148097 		case PORT_1G_TN1010:
7336835Syc148097 			nxgep->xcvr = nxge_1G_tn1010_table;
7346835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7356835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7366835Syc148097 			    "1G TN1010 copper Xcvr"));
7376835Syc148097 			break;
7386835Syc148097 
7396835Syc148097 		case PORT_10G_TN1010:
7406835Syc148097 			nxgep->xcvr = nxge_10G_tn1010_table;
7416835Syc148097 			nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
7426835Syc148097 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
7436835Syc148097 			    "10G TN1010 copper Xcvr"));
7446835Syc148097 			break;
7456835Syc148097 
7464977Sraghus 		case PORT_1G_FIBER:
7474977Sraghus 		case PORT_1G_SERDES:
7484732Sdavemq 			nxgep->xcvr = nxge_1G_fiber_table;
7495572Ssbehera 			nxgep->xcvr_addr = portn;
7504977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
7514977Sraghus 			    (nxgep->mac.portmode == PORT_1G_FIBER) ?
7524977Sraghus 			    "Fiber" : "Serdes"));
7534732Sdavemq 			break;
7544977Sraghus 		case PORT_10G_FIBER:
7554977Sraghus 		case PORT_10G_SERDES:
7564732Sdavemq 			nxgep->xcvr = nxge_10G_fiber_table;
7575572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
7585572Ssbehera 			    "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
7595572Ssbehera 			    "nxgep->xcvr_addr = [%d]",
7605572Ssbehera 			    nxgep->nxge_hw_p->xcvr_addr[portn],
7615572Ssbehera 			    nxgep->xcvr_addr));
7625572Ssbehera 			if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
7635572Ssbehera 				nxgep->xcvr_addr =
7645572Ssbehera 				    nxgep->nxge_hw_p->xcvr_addr[portn];
7655572Ssbehera 			}
7664977Sraghus 			switch (nxgep->platform_type) {
7674977Sraghus 			case P_NEPTUNE_MARAMBA_P0:
7684977Sraghus 			case P_NEPTUNE_MARAMBA_P1:
7694732Sdavemq 				/*
7704732Sdavemq 				 * Switch off LED for corresponding copper
7714732Sdavemq 				 * port
7724732Sdavemq 				 */
7734732Sdavemq 				nxge_bcm5464_link_led_off(nxgep);
7744977Sraghus 				break;
7754977Sraghus 			default:
7764977Sraghus 				break;
7774732Sdavemq 			}
7784977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
7794977Sraghus 			    (nxgep->mac.portmode == PORT_10G_FIBER) ?
7804977Sraghus 			    "Fiber" : "Serdes"));
7814732Sdavemq 			break;
7825572Ssbehera 
7835572Ssbehera 		case PORT_HSP_MODE:
7845572Ssbehera 			nxgep->xcvr = nxge_10G_fiber_table;
7855572Ssbehera 			nxgep->xcvr.xcvr_inuse = HSP_XCVR;
7865572Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
7875572Ssbehera 			    "Swappable Xcvr (not present)"));
7885572Ssbehera 			break;
7894732Sdavemq 		default:
7904732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
7914732Sdavemq 			    "Unknown port-type: 0x%x", port_type));
7924732Sdavemq 			return (NXGE_ERROR);
7934732Sdavemq 		}
7944732Sdavemq 	}
7954732Sdavemq 
7965572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_FIBER) {
7976604Ssbehera 		uint32_t pma_pmd_id;
7986604Ssbehera 		pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
7996604Ssbehera 		    nxgep->xcvr_addr);
8006604Ssbehera 		if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
8016604Ssbehera 			chip_id = MRVL88X201X_CHIP_ID;
8026604Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8036604Ssbehera 			    "nxge_setup_xcvr_table: "
8046604Ssbehera 			    "Chip ID  MARVELL [0x%x] for 10G xcvr", chip_id));
8056604Ssbehera 		} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
8065572Ssbehera 		    BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
8075572Ssbehera 		    &chip_id)) == NXGE_OK) {
8085572Ssbehera 
8095572Ssbehera 			switch (chip_id) {
8105572Ssbehera 			case BCM8704_CHIP_ID:
8115572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8125572Ssbehera 				    "nxge_setup_xcvr_table: "
8135572Ssbehera 				    "Chip ID 8704 [0x%x] for 10G xcvr",
8145572Ssbehera 				    chip_id));
8155572Ssbehera 				break;
8165572Ssbehera 			case BCM8706_CHIP_ID:
8175572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
8185572Ssbehera 				    "nxge_setup_xcvr_table: "
8195572Ssbehera 				    "Chip ID 8706 [0x%x] for 10G xcvr",
8205572Ssbehera 				    chip_id));
8215572Ssbehera 				break;
8225572Ssbehera 			default:
8235572Ssbehera 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
8245572Ssbehera 				    "nxge_setup_xcvr_table: "
8255572Ssbehera 				    "Unknown Chip ID [0x%x] for 10G xcvr",
8265572Ssbehera 				    chip_id));
8275572Ssbehera 				break;
8285572Ssbehera 			}
8295572Ssbehera 		}
8305572Ssbehera 	}
8315572Ssbehera 
8324732Sdavemq 	nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
8335572Ssbehera 	nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
8345572Ssbehera 	nxgep->chip_id = chip_id;
8354977Sraghus 
8364977Sraghus 	/*
8374977Sraghus 	 * Get the actual device ID value returned by MDIO read.
8384977Sraghus 	 */
8394977Sraghus 	nxgep->statsp->mac_stats.xcvr_id = 0;
8404977Sraghus 
8415572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
8424977Sraghus 	if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
8434977Sraghus 		nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
8444977Sraghus 	} else {
8455572Ssbehera 		pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
8464977Sraghus 		if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
8474977Sraghus 			nxgep->statsp->mac_stats.xcvr_id = pcs_id;
8484977Sraghus 		} else {
8494977Sraghus 			phy_id = nxge_get_cl22_phy_id(nxgep,
8505572Ssbehera 			    nxgep->xcvr_addr);
8514977Sraghus 			if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
8524977Sraghus 				nxgep->statsp->mac_stats.xcvr_id = phy_id;
8534977Sraghus 			}
8544977Sraghus 		}
8554977Sraghus 	}
8564977Sraghus 
8574732Sdavemq 	nxgep->mac.linkchkmode = LINKCHK_TIMER;
8584732Sdavemq 
8594977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
8607801SSantwona.Behera@Sun.COM 	    "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
8615572Ssbehera 	    nxgep->platform_type, nxgep->xcvr_addr));
8624977Sraghus 
8634732Sdavemq 	return (status);
8644732Sdavemq }
8654732Sdavemq 
8663859Sml29623 /* Initialize the entire MAC and physical layer */
8673859Sml29623 
8683859Sml29623 nxge_status_t
8693859Sml29623 nxge_mac_init(p_nxge_t nxgep)
8703859Sml29623 {
8713859Sml29623 	uint8_t			portn;
8723859Sml29623 	nxge_status_t		status = NXGE_OK;
8733859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
8743859Sml29623 
8753859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
8763859Sml29623 
8773859Sml29623 	nxgep->mac.portnum = portn;
8783859Sml29623 	nxgep->mac.porttype = PORT_TYPE_XMAC;
8793859Sml29623 
8803859Sml29623 	if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
8813859Sml29623 		nxgep->mac.porttype = PORT_TYPE_BMAC;
8823859Sml29623 
8836835Syc148097 
8843859Sml29623 	/* Initialize XIF to configure a network mode */
8853859Sml29623 	if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
8863859Sml29623 		goto fail;
8873859Sml29623 	}
8883859Sml29623 
8893859Sml29623 	if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
8903859Sml29623 		goto fail;
8913859Sml29623 	}
8923859Sml29623 
8933859Sml29623 	/* Initialize TX and RX MACs */
8943859Sml29623 	/*
8953859Sml29623 	 * Always perform XIF init first, before TX and RX MAC init
8963859Sml29623 	 */
8973859Sml29623 	if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
8983859Sml29623 		goto fail;
8993859Sml29623 
9003859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
9013859Sml29623 		goto fail;
9023859Sml29623 
9033859Sml29623 	if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
9043859Sml29623 		goto fail;
9053859Sml29623 
9063859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
9073859Sml29623 		goto fail;
9083859Sml29623 
9093859Sml29623 	if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
9103859Sml29623 		goto fail;
9113859Sml29623 
912*9232SMichael.Speer@Sun.COM 	if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
913*9232SMichael.Speer@Sun.COM 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
914*9232SMichael.Speer@Sun.COM 			goto fail;
915*9232SMichael.Speer@Sun.COM 	}
9163859Sml29623 
9175553Smisaki 	/* Initialize MAC control configuration */
9185553Smisaki 	if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
9195553Smisaki 		goto fail;
9205553Smisaki 	}
9215553Smisaki 
9223859Sml29623 	nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
9233859Sml29623 
9245196Ssbehera 	/* The Neptune Serdes needs to be reinitialized again */
9255196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
9265196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
9276835Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
9285196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
9295196Ssbehera 	    ((portn == 0) || (portn == 1))) {
9305196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9315196Ssbehera 		    "nxge_mac_init: reinit Neptune 1G Serdes "));
9325196Ssbehera 		if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
9335196Ssbehera 			goto fail;
9345196Ssbehera 		}
9355196Ssbehera 	}
9365196Ssbehera 
9374977Sraghus 
9383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
9393859Sml29623 
9403859Sml29623 	return (NXGE_OK);
9413859Sml29623 fail:
9423859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
9436929Smisaki 	    "nxge_mac_init: failed to initialize MAC port<%d>", portn));
9443859Sml29623 	return (status);
9453859Sml29623 }
9463859Sml29623 
9473859Sml29623 /* Initialize the Ethernet Link */
9483859Sml29623 
9493859Sml29623 nxge_status_t
9503859Sml29623 nxge_link_init(p_nxge_t nxgep)
9513859Sml29623 {
9523859Sml29623 	nxge_status_t		status = NXGE_OK;
9534977Sraghus 	nxge_port_mode_t	portmode;
9543859Sml29623 #ifdef	NXGE_DEBUG
9553859Sml29623 	uint8_t			portn;
9563859Sml29623 
9573859Sml29623 	portn = nxgep->mac.portnum;
9583859Sml29623 
9593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
9603859Sml29623 #endif
9615572Ssbehera 	if (nxgep->hot_swappable_phy && nxgep->phy_absent) {
9625572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: "
9635572Ssbehera 		    "Phy not present, cannot initialize link"));
9645572Ssbehera 		return (status);
9655572Ssbehera 	}
9663859Sml29623 
9674977Sraghus 	portmode = nxgep->mac.portmode;
9685572Ssbehera 
9696835Syc148097 	/*
9706835Syc148097 	 * Workaround to get link up in both NIU ports. Some portmodes require
9716835Syc148097 	 * that the xcvr be initialized twice, the first time before calling
9726835Syc148097 	 * nxge_serdes_init.
9736835Syc148097 	 */
9744977Sraghus 	if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
9756835Syc148097 	    (portmode != PORT_10G_TN1010) &&
9766835Syc148097 	    (portmode != PORT_1G_TN1010) &&
9774977Sraghus 	    (portmode != PORT_1G_SERDES)) {
9784977Sraghus 		if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
9793859Sml29623 			goto fail;
9804977Sraghus 		}
9813859Sml29623 	}
9826835Syc148097 
9833859Sml29623 	NXGE_DELAY(200000);
9843859Sml29623 	/* Initialize internal serdes */
9853859Sml29623 	if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
9863859Sml29623 		goto fail;
9873859Sml29623 	NXGE_DELAY(200000);
9883859Sml29623 	if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
9893859Sml29623 		goto fail;
9903859Sml29623 
9913859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
9923859Sml29623 
9933859Sml29623 	return (NXGE_OK);
9943859Sml29623 
9953859Sml29623 fail:
9966929Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
9976929Smisaki 	    "failed to initialize Ethernet link on port<%d>", portn));
9983859Sml29623 
9993859Sml29623 	return (status);
10003859Sml29623 }
10013859Sml29623 
10023859Sml29623 
10033859Sml29623 /* Initialize the XIF sub-block within the MAC */
10043859Sml29623 
10053859Sml29623 nxge_status_t
10063859Sml29623 nxge_xif_init(p_nxge_t nxgep)
10073859Sml29623 {
10083859Sml29623 	uint32_t		xif_cfg = 0;
10093859Sml29623 	npi_attr_t		ap;
10103859Sml29623 	uint8_t			portn;
10113859Sml29623 	nxge_port_t		portt;
10123859Sml29623 	nxge_port_mode_t	portmode;
10133859Sml29623 	p_nxge_stats_t		statsp;
10143859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
10153859Sml29623 	npi_handle_t		handle;
10163859Sml29623 
10173859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
10183859Sml29623 
10193859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
10203859Sml29623 
10213859Sml29623 	handle = nxgep->npi_handle;
10223859Sml29623 	portmode = nxgep->mac.portmode;
10233859Sml29623 	portt = nxgep->mac.porttype;
10243859Sml29623 	statsp = nxgep->statsp;
10253859Sml29623 
10265196Ssbehera 	if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
10275196Ssbehera 	    ((nxgep->mac.portmode == PORT_1G_SERDES) ||
10286835Syc148097 	    (nxgep->mac.portmode == PORT_1G_TN1010) ||
10295196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_FIBER)) &&
10305196Ssbehera 	    ((portn == 0) || (portn == 1))) {
10315196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
10325196Ssbehera 		    "nxge_xcvr_init: set ATCA mode"));
10335196Ssbehera 		npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
10345196Ssbehera 	}
10355196Ssbehera 
10363859Sml29623 	if (portt == PORT_TYPE_XMAC) {
10373859Sml29623 
10383859Sml29623 		/* Setup XIF Configuration for XMAC */
10393859Sml29623 
10403859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
10414977Sraghus 		    (portmode == PORT_10G_COPPER) ||
10426835Syc148097 		    (portmode == PORT_10G_TN1010) ||
10434977Sraghus 		    (portmode == PORT_10G_SERDES))
10443859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LFS;
10453859Sml29623 
10466835Syc148097 		/* Bypass PCS so that RGMII will be used */
10473859Sml29623 		if (portmode == PORT_1G_COPPER) {
10483859Sml29623 			xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
10493859Sml29623 		}
10503859Sml29623 
10513859Sml29623 		/* Set MAC Internal Loopback if necessary */
10523859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
10533859Sml29623 			xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
10543859Sml29623 
10553859Sml29623 		if (statsp->mac_stats.link_speed == 100)
10563859Sml29623 			xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
10573859Sml29623 
10583859Sml29623 		xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
10593859Sml29623 
10604977Sraghus 		if ((portmode == PORT_10G_FIBER) ||
10616835Syc148097 		    (portmode == PORT_10G_TN1010) ||
10626835Syc148097 		    (portmode == PORT_1G_TN1010) ||
10634977Sraghus 		    (portmode == PORT_10G_SERDES)) {
10646835Syc148097 			/* Assume LED same for 1G and 10G */
10653859Sml29623 			if (statsp->mac_stats.link_up) {
10663859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
10673859Sml29623 			} else {
10683859Sml29623 				xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
10693859Sml29623 			}
10703859Sml29623 		}
10713859Sml29623 
10723859Sml29623 		rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
10733859Sml29623 		if (rs != NPI_SUCCESS)
10743859Sml29623 			goto fail;
10753859Sml29623 
10763859Sml29623 		nxgep->mac.xif_config = xif_cfg;
10773859Sml29623 
10783859Sml29623 		/* Set Port Mode */
10793859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
10804977Sraghus 		    (portmode == PORT_10G_COPPER) ||
10816835Syc148097 		    (portmode == PORT_10G_TN1010) ||
10824977Sraghus 		    (portmode == PORT_10G_SERDES)) {
10833859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
10846929Smisaki 			    MAC_XGMII_MODE, rs);
10853859Sml29623 			if (rs != NPI_SUCCESS)
10863859Sml29623 				goto fail;
10873859Sml29623 			if (statsp->mac_stats.link_up) {
10883859Sml29623 				if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
10893859Sml29623 					goto fail;
10903859Sml29623 			} else {
10913859Sml29623 				if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
10923859Sml29623 					goto fail;
10933859Sml29623 			}
10943859Sml29623 		} else if ((portmode == PORT_1G_FIBER) ||
10954977Sraghus 		    (portmode == PORT_1G_COPPER) ||
10965196Ssbehera 		    (portmode == PORT_1G_SERDES) ||
10976835Syc148097 		    (portmode == PORT_1G_TN1010) ||
10985196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
10995196Ssbehera 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11005196Ssbehera 			    "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
11015196Ssbehera 			    portn, portmode, statsp->mac_stats.link_speed));
11023859Sml29623 			if (statsp->mac_stats.link_speed == 1000) {
11033859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11046929Smisaki 				    MAC_GMII_MODE, rs);
11053859Sml29623 			} else {
11063859Sml29623 				SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
11076929Smisaki 				    MAC_MII_MODE, rs);
11083859Sml29623 			}
11093859Sml29623 			if (rs != NPI_SUCCESS)
11103859Sml29623 				goto fail;
11113859Sml29623 		} else {
11123859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11136929Smisaki 			    "nxge_xif_init: Unknown port mode (%d)"
11146929Smisaki 			    " for port<%d>", portmode, portn));
11153859Sml29623 			goto fail;
11163859Sml29623 		}
11173859Sml29623 
11185196Ssbehera 		/* Enable ATCA mode */
11195196Ssbehera 
11203859Sml29623 	} else if (portt == PORT_TYPE_BMAC) {
11213859Sml29623 
11223859Sml29623 		/* Setup XIF Configuration for BMAC */
11233859Sml29623 
11245196Ssbehera 		if ((portmode == PORT_1G_COPPER) ||
11255196Ssbehera 		    (portmode == PORT_1G_RGMII_FIBER)) {
11263859Sml29623 			if (statsp->mac_stats.link_speed == 100)
11273859Sml29623 				xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
11283859Sml29623 		}
11293859Sml29623 
11303859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
11313859Sml29623 			xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
11323859Sml29623 
11333859Sml29623 		if (statsp->mac_stats.link_speed == 1000)
11343859Sml29623 			xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
11353859Sml29623 
11363859Sml29623 		xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
11373859Sml29623 
11383859Sml29623 		rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
11393859Sml29623 		if (rs != NPI_SUCCESS)
11403859Sml29623 			goto fail;
11413859Sml29623 		nxgep->mac.xif_config = xif_cfg;
11423859Sml29623 	}
11433859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
11443859Sml29623 	return (NXGE_OK);
11453859Sml29623 fail:
11463859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
11476929Smisaki 	    "nxge_xif_init: Failed to initialize XIF port<%d>", portn));
11483859Sml29623 	return (NXGE_ERROR | rs);
11493859Sml29623 }
11503859Sml29623 
11516835Syc148097 
11526835Syc148097 /*
11536835Syc148097  * Initialize the PCS sub-block in the MAC.  Note that PCS does not
11546835Syc148097  * support loopback like XPCS.
11556835Syc148097  */
11563859Sml29623 nxge_status_t
11573859Sml29623 nxge_pcs_init(p_nxge_t nxgep)
11583859Sml29623 {
11593859Sml29623 	pcs_cfg_t		pcs_cfg;
11603859Sml29623 	uint32_t		val;
11613859Sml29623 	uint8_t			portn;
11623859Sml29623 	nxge_port_mode_t	portmode;
11633859Sml29623 	npi_handle_t		handle;
11643859Sml29623 	p_nxge_stats_t		statsp;
11656835Syc148097 	pcs_ctrl_t		pcs_ctrl;
11663859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
11676835Syc148097 	uint8_t i;
11683859Sml29623 
11693859Sml29623 	handle = nxgep->npi_handle;
11703859Sml29623 	portmode = nxgep->mac.portmode;
11713859Sml29623 	portn = nxgep->mac.portnum;
11723859Sml29623 	statsp = nxgep->statsp;
11733859Sml29623 
11743859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
11753859Sml29623 
11766835Syc148097 	if (portmode == PORT_1G_FIBER ||
11776835Syc148097 	    portmode == PORT_1G_TN1010 ||
11786835Syc148097 	    portmode == PORT_1G_SERDES) {
11796835Syc148097 		if (portmode == PORT_1G_TN1010) {
11806835Syc148097 			/* Reset PCS multiple time in PORT_1G_TN1010 mode */
11816835Syc148097 			for (i = 0; i < 6; i ++) {
11826835Syc148097 				if ((rs = npi_mac_pcs_reset(handle, portn))
11836835Syc148097 				    != NPI_SUCCESS) {
11846835Syc148097 					goto fail;
11856835Syc148097 				}
11866835Syc148097 			}
11876835Syc148097 		} else {
11886835Syc148097 			if ((rs = npi_mac_pcs_reset(handle, portn))
11896835Syc148097 			    != NPI_SUCCESS)
11906835Syc148097 				goto fail;
11914977Sraghus 		}
11924977Sraghus 
11933859Sml29623 		/* Initialize port's PCS */
11943859Sml29623 		pcs_cfg.value = 0;
11953859Sml29623 		pcs_cfg.bits.w0.enable = 1;
11963859Sml29623 		pcs_cfg.bits.w0.mask = 1;
11973859Sml29623 		PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
11983859Sml29623 		PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
11994977Sraghus 
12004977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12014977Sraghus 		    "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
12024977Sraghus 		    portn, pcs_cfg.value));
12036835Syc148097 
12046835Syc148097 		if (portmode == PORT_1G_TN1010) {
12056835Syc148097 			/*
12066835Syc148097 			 * Must disable PCS auto-negotiation when the the driver
12076835Syc148097 			 * is driving the TN1010 based XAUI card  Otherwise the
12086835Syc148097 			 * autonegotiation between the PCS and the TN1010 PCS
12096835Syc148097 			 * will never complete and the Neptune/NIU will not work
12106835Syc148097 			 */
12116835Syc148097 			pcs_ctrl.value = 0;
12126835Syc148097 			PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
12136835Syc148097 			    pcs_ctrl.value);
12146835Syc148097 		}
12156835Syc148097 	} else if (portmode == PORT_10G_FIBER ||
12166835Syc148097 	    portmode == PORT_10G_COPPER ||
12176835Syc148097 	    portmode == PORT_10G_TN1010 ||
12186835Syc148097 	    portmode == PORT_10G_SERDES) {
12193859Sml29623 		/* Use internal XPCS, bypass 1G PCS */
12203859Sml29623 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
12213859Sml29623 		val &= ~XMAC_XIF_XPCS_BYPASS;
12223859Sml29623 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
12233859Sml29623 
12243859Sml29623 		if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
12253859Sml29623 			goto fail;
12263859Sml29623 
12273859Sml29623 		/* Set XPCS Internal Loopback if necessary */
12283859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12296929Smisaki 		    XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
12303859Sml29623 			goto fail;
12316835Syc148097 
12323859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
12336929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_mac1000))
12343859Sml29623 			val |= XPCS_CTRL1_LOOPBK;
12353859Sml29623 		else
12363859Sml29623 			val &= ~XPCS_CTRL1_LOOPBK;
12373859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
12386929Smisaki 		    XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
12393859Sml29623 			goto fail;
12403859Sml29623 
12413859Sml29623 		/* Clear descw errors */
12423859Sml29623 		if ((rs = npi_xmac_xpcs_write(handle, portn,
12436929Smisaki 		    XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
12443859Sml29623 			goto fail;
12453859Sml29623 		/* Clear symbol errors */
12463859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12476929Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
12483859Sml29623 			goto fail;
12493859Sml29623 		if ((rs = npi_xmac_xpcs_read(handle, portn,
12506929Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
12513859Sml29623 			goto fail;
12523859Sml29623 
12535196Ssbehera 	} else if ((portmode == PORT_1G_COPPER) ||
12545196Ssbehera 	    (portmode == PORT_1G_RGMII_FIBER)) {
12555196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12565196Ssbehera 		    "==> nxge_pcs_init: (1G) copper port<%d>", portn));
12573859Sml29623 		if (portn < 4) {
12583859Sml29623 			PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
12596929Smisaki 			    PCS_DATAPATH_MODE_MII);
12603859Sml29623 		}
12613859Sml29623 		if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
12623859Sml29623 			goto fail;
12633859Sml29623 
12643859Sml29623 	} else {
12653859Sml29623 		goto fail;
12663859Sml29623 	}
12673859Sml29623 pass:
12683859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
12693859Sml29623 	return (NXGE_OK);
12703859Sml29623 fail:
12713859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
12726929Smisaki 	    "nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
12733859Sml29623 	return (NXGE_ERROR | rs);
12743859Sml29623 }
12753859Sml29623 
12765553Smisaki /*
12775553Smisaki  * Initialize the MAC CTRL sub-block within the MAC
12785553Smisaki  * Only the receive-pause-cap is supported.
12795553Smisaki  */
12805553Smisaki nxge_status_t
12815553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep)
12825553Smisaki {
12835553Smisaki 	uint8_t			portn;
12845553Smisaki 	nxge_port_t		portt;
12855553Smisaki 	p_nxge_stats_t		statsp;
12865553Smisaki 	npi_handle_t		handle;
12875553Smisaki 	uint32_t		val;
12885553Smisaki 
12895553Smisaki 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
12905553Smisaki 
12915553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
12925553Smisaki 	    portn));
12935553Smisaki 
12945553Smisaki 	handle = nxgep->npi_handle;
12955553Smisaki 	portt = nxgep->mac.porttype;
12965553Smisaki 	statsp = nxgep->statsp;
12975553Smisaki 
12985553Smisaki 	if (portt == PORT_TYPE_XMAC) {
12996835Syc148097 		/* Reading the current XMAC Config Register for XMAC */
13005553Smisaki 		XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
13015553Smisaki 
13025553Smisaki 		/*
13035553Smisaki 		 * Setup XMAC Configuration for XMAC
13045553Smisaki 		 * XMAC only supports receive-pause
13055553Smisaki 		 */
13065553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
13075553Smisaki 			if (!statsp->mac_stats.adv_cap_pause) {
13085553Smisaki 				/*
13095553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13105553Smisaki 				 * is 0, enable receive pause.
13115553Smisaki 				 */
13125553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
13135553Smisaki 			} else {
13145553Smisaki 				/*
13155553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13165553Smisaki 				 * is 1, disable receive pause.  Send pause is
13175553Smisaki 				 * not supported.
13185553Smisaki 				 */
13195553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
13205553Smisaki 			}
13215553Smisaki 		} else {
13226439Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13236439Sml29623 			    "==> nxge_mac_ctrl_init: port<%d>: pause",
13246439Sml29623 			    portn));
13255553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13266439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13276439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13286439Sml29623 				    "enable pause", portn));
13295553Smisaki 				/*
13305553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13315553Smisaki 				 * is 1, enable receive pause.
13325553Smisaki 				 */
13335553Smisaki 				val |= XMAC_RX_CFG_RX_PAUSE_EN;
13345553Smisaki 			} else {
13355553Smisaki 				/*
13365553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13375553Smisaki 				 * is 0, disable receive pause. Send pause is
13385553Smisaki 				 * not supported
13395553Smisaki 				 */
13406439Sml29623 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
13416439Sml29623 				    "==> nxge_mac_ctrl_init: port<%d>: "
13426439Sml29623 				    "disable pause", portn));
13435553Smisaki 				val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
13445553Smisaki 			}
13455553Smisaki 		}
13465553Smisaki 		XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
13475553Smisaki 	} else if (portt == PORT_TYPE_BMAC) {
13486835Syc148097 		/* Reading the current MAC CTRL Config Register for BMAC */
13495553Smisaki 		BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
13505553Smisaki 
13515553Smisaki 		/* Setup MAC CTRL Configuration for BMAC */
13525553Smisaki 		if (statsp->mac_stats.adv_cap_asmpause) {
13535553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13545553Smisaki 				/*
13555553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13565553Smisaki 				 * is 1, disable receive pause. Send pause
13575553Smisaki 				 * is not supported
13585553Smisaki 				 */
13595553Smisaki 				val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
13605553Smisaki 			} else {
13615553Smisaki 				/*
13625553Smisaki 				 * If adv_cap_asmpause is 1 and adv_cap_pause
13635553Smisaki 				 * is 0, enable receive pause and disable
13645553Smisaki 				 * send pause.
13655553Smisaki 				 */
13665553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
13675553Smisaki 				val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
13685553Smisaki 			}
13695553Smisaki 		} else {
13705553Smisaki 			if (statsp->mac_stats.adv_cap_pause) {
13715553Smisaki 				/*
13725553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13735553Smisaki 				 * is 1, enable receive pause. Send pause is
13745553Smisaki 				 * not supported.
13755553Smisaki 				 */
13765553Smisaki 				val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
13775553Smisaki 			} else {
13785553Smisaki 				/*
13795553Smisaki 				 * If adv_cap_asmpause is 0 and adv_cap_pause
13805553Smisaki 				 * is 0, pause capability is not available in
13815553Smisaki 				 * either direction.
13825553Smisaki 				 */
13835553Smisaki 				val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
13846929Smisaki 				    ~MAC_CTRL_CFG_RECV_PAUSE_EN);
13855553Smisaki 			}
13865553Smisaki 		}
13875553Smisaki 		BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
13885553Smisaki 	}
13895553Smisaki 
13905553Smisaki 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
13915553Smisaki 	    portn));
13925553Smisaki 
13935553Smisaki 	return (NXGE_OK);
13945553Smisaki }
13955553Smisaki 
13963859Sml29623 /* Initialize the Internal Serdes */
13973859Sml29623 
13983859Sml29623 nxge_status_t
13993859Sml29623 nxge_serdes_init(p_nxge_t nxgep)
14003859Sml29623 {
14013859Sml29623 	p_nxge_stats_t		statsp;
14023859Sml29623 #ifdef	NXGE_DEBUG
14033859Sml29623 	uint8_t			portn;
14043859Sml29623 #endif
14053859Sml29623 	nxge_status_t		status = NXGE_OK;
14063859Sml29623 
14073859Sml29623 #ifdef	NXGE_DEBUG
14083859Sml29623 	portn = nxgep->mac.portnum;
14093859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14104732Sdavemq 	    "==> nxge_serdes_init port<%d>", portn));
14113859Sml29623 #endif
14123859Sml29623 
14134732Sdavemq 	if (nxgep->xcvr.serdes_init) {
14144732Sdavemq 		statsp = nxgep->statsp;
14154732Sdavemq 		status = nxgep->xcvr.serdes_init(nxgep);
14164732Sdavemq 		if (status != NXGE_OK)
14173859Sml29623 			goto fail;
14184732Sdavemq 		statsp->mac_stats.serdes_inits++;
14193859Sml29623 	}
14203859Sml29623 
14213859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
14224732Sdavemq 	    portn));
14233859Sml29623 
14243859Sml29623 	return (NXGE_OK);
14253859Sml29623 
14263859Sml29623 fail:
14273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
14284732Sdavemq 	    "nxge_serdes_init: Failed to initialize serdes for port<%d>",
14294732Sdavemq 	    portn));
14303859Sml29623 
14313859Sml29623 	return (status);
14323859Sml29623 }
14333859Sml29623 
14343859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
14353859Sml29623 
14364732Sdavemq static nxge_status_t
14373859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep)
14383859Sml29623 {
14393859Sml29623 	uint8_t portn;
14403859Sml29623 	int chan;
14413859Sml29623 	esr_ti_cfgpll_l_t pll_cfg_l;
14424977Sraghus 	esr_ti_cfgpll_l_t pll_sts_l;
14433859Sml29623 	esr_ti_cfgrx_l_t rx_cfg_l;
14443859Sml29623 	esr_ti_cfgrx_h_t rx_cfg_h;
14453859Sml29623 	esr_ti_cfgtx_l_t tx_cfg_l;
14463859Sml29623 	esr_ti_cfgtx_h_t tx_cfg_h;
14474977Sraghus #ifdef NXGE_DEBUG
14484977Sraghus 	esr_ti_testcfg_t cfg;
14494977Sraghus #endif
14503859Sml29623 	esr_ti_testcfg_t test_cfg;
14513859Sml29623 	nxge_status_t status = NXGE_OK;
14523859Sml29623 
14533859Sml29623 	portn = nxgep->mac.portnum;
14543859Sml29623 
14553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
14566929Smisaki 	    portn));
14573859Sml29623 
14583859Sml29623 	tx_cfg_l.value = 0;
14593859Sml29623 	tx_cfg_h.value = 0;
14603859Sml29623 	rx_cfg_l.value = 0;
14613859Sml29623 	rx_cfg_h.value = 0;
14623859Sml29623 	pll_cfg_l.value = 0;
14634977Sraghus 	pll_sts_l.value = 0;
14643859Sml29623 	test_cfg.value = 0;
14653859Sml29623 
14666835Syc148097 	/*
14676835Syc148097 	 * If the nxge driver has been plumbed without a link, then it will
14686835Syc148097 	 * detect a link up when a cable connecting to an anto-negotiation
14696835Syc148097 	 * partner is plugged into the port. Because the TN1010 PHY supports
14706835Syc148097 	 * both 1G and 10G speeds, the driver must re-configure the
14716835Syc148097 	 * Neptune/NIU according to the negotiated speed.  nxge_n2_serdes_init
14726835Syc148097 	 * is called at the post-link-up reconfiguration time. Here it calls
14736835Syc148097 	 * nxge_set_tn1010_param to set portmode before re-initializing
14746835Syc148097 	 * the serdes.
14756835Syc148097 	 */
14766835Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
14776835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
14786835Syc148097 		if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
14796835Syc148097 			goto fail;
14806835Syc148097 		}
14816835Syc148097 	}
14826835Syc148097 
14836835Syc148097 	if (nxgep->mac.portmode == PORT_10G_FIBER ||
14846835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010 ||
14856835Syc148097 	    nxgep->mac.portmode == PORT_10G_SERDES) {
14863859Sml29623 		/* 0x0E01 */
14873859Sml29623 		tx_cfg_l.bits.entx = 1;
14883859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
14893859Sml29623 
14903859Sml29623 		/* 0x9101 */
14913859Sml29623 		rx_cfg_l.bits.enrx = 1;
14923859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
14933859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
14943859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
14953859Sml29623 
14963859Sml29623 		/* 0x0008 */
14973859Sml29623 		rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
14983859Sml29623 
14993859Sml29623 		/* Set loopback mode if necessary */
15003859Sml29623 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
15013859Sml29623 			tx_cfg_l.bits.entest = 1;
15023859Sml29623 			rx_cfg_l.bits.entest = 1;
15033859Sml29623 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
15043859Sml29623 			if ((status = nxge_mdio_write(nxgep, portn,
15056929Smisaki 			    ESR_N2_DEV_ADDR,
15066929Smisaki 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
15073859Sml29623 			goto fail;
15083859Sml29623 		}
15093859Sml29623 
15106835Syc148097 		/* Initialize PLL for 10G */
15116835Syc148097 		pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
15126835Syc148097 		pll_cfg_l.bits.enpll = 1;
15136835Syc148097 		pll_sts_l.bits.enpll = 1;
15146835Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15156835Syc148097 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
15166835Syc148097 			goto fail;
15176835Syc148097 
15186835Syc148097 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15196835Syc148097 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15206835Syc148097 			goto fail;
15216835Syc148097 
15226835Syc148097 #ifdef  NXGE_DEBUG
15236835Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15246835Syc148097 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15256835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15266835Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15276835Syc148097 		    portn, pll_cfg_l.value, cfg.value));
15286835Syc148097 
15296835Syc148097 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15306835Syc148097 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15316835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15326835Syc148097 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
15336835Syc148097 		    portn, pll_sts_l.value, cfg.value));
15346835Syc148097 #endif
15356835Syc148097 	} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
15366835Syc148097 	    nxgep->mac.portmode == PORT_1G_TN1010 ||
15376835Syc148097 	    nxgep->mac.portmode == PORT_1G_SERDES) {
15383859Sml29623 		/* 0x0E21 */
15393859Sml29623 		tx_cfg_l.bits.entx = 1;
15403859Sml29623 		tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
15413859Sml29623 		tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
15423859Sml29623 
15433859Sml29623 		/* 0x9121 */
15443859Sml29623 		rx_cfg_l.bits.enrx = 1;
15453859Sml29623 		rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
15463859Sml29623 		rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
15473859Sml29623 		rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
15483859Sml29623 		rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
15493859Sml29623 
15504977Sraghus 		if (portn == 0) {
15514977Sraghus 			/* 0x8 */
15524977Sraghus 			rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
15534977Sraghus 		}
15543859Sml29623 
15556835Syc148097 		/* Initialize PLL for 1G */
15563859Sml29623 		pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
15573859Sml29623 		pll_cfg_l.bits.enpll = 1;
15584977Sraghus 		pll_sts_l.bits.enpll = 1;
15593859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15606929Smisaki 		    ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
15613859Sml29623 			goto fail;
15624977Sraghus 
15634977Sraghus 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
15644977Sraghus 		    ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
15654977Sraghus 			goto fail;
15664977Sraghus 
15674977Sraghus #ifdef  NXGE_DEBUG
15684977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15694977Sraghus 		    ESR_N2_PLL_CFG_L_REG, &cfg.value);
15704977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15714977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
15724977Sraghus 		    portn, pll_cfg_l.value, cfg.value));
15734977Sraghus 
15744977Sraghus 		nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
15754977Sraghus 		    ESR_N2_PLL_STS_L_REG, &cfg.value);
15764977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15774977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
15784977Sraghus 		    portn, pll_sts_l.value, cfg.value));
15794977Sraghus #endif
15804977Sraghus 
15814977Sraghus 		/* Set loopback mode if necessary */
15824977Sraghus 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
15834977Sraghus 			tx_cfg_l.bits.entest = 1;
15844977Sraghus 			rx_cfg_l.bits.entest = 1;
15854977Sraghus 			test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
15864977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
15874977Sraghus 			    "==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
15884977Sraghus 			    portn, test_cfg.value));
15894977Sraghus 			if ((status = nxge_mdio_write(nxgep, portn,
15904977Sraghus 			    ESR_N2_DEV_ADDR,
15914977Sraghus 			    ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
15924977Sraghus 				goto fail;
15934977Sraghus 			}
15944977Sraghus 		}
15953859Sml29623 	} else {
15963859Sml29623 		goto fail;
15973859Sml29623 	}
15983859Sml29623 
15993859Sml29623 	/*   MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
16003859Sml29623 
16013859Sml29623 	NXGE_DELAY(20);
16023859Sml29623 
16033859Sml29623 	/* init TX channels */
16043859Sml29623 	for (chan = 0; chan < 4; chan++) {
16053859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16066929Smisaki 		    ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
16073859Sml29623 			goto fail;
16083859Sml29623 
16093859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16106929Smisaki 		    ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
16113859Sml29623 			goto fail;
16124977Sraghus 
16134977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16144977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
16154977Sraghus 		    portn, chan, tx_cfg_l.value));
16164977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16174977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
16184977Sraghus 		    portn, chan, tx_cfg_h.value));
16193859Sml29623 	}
16203859Sml29623 
16213859Sml29623 	/* init RX channels */
16223859Sml29623 	for (chan = 0; chan < 4; chan++) {
16233859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16246929Smisaki 		    ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
16253859Sml29623 			goto fail;
16263859Sml29623 
16273859Sml29623 		if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
16286929Smisaki 		    ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
16293859Sml29623 			goto fail;
16304977Sraghus 
16314977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16324977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
16334977Sraghus 		    portn, chan, rx_cfg_l.value));
16346835Syc148097 
16354977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16364977Sraghus 		    "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
16374977Sraghus 		    portn, chan, rx_cfg_h.value));
16383859Sml29623 	}
16393859Sml29623 
16403859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
16416929Smisaki 	    portn));
16423859Sml29623 
16433859Sml29623 	return (NXGE_OK);
16443859Sml29623 fail:
16455572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16465572Ssbehera 	    "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
16475572Ssbehera 	    portn));
16483859Sml29623 
16493859Sml29623 	return (status);
16503859Sml29623 }
16513859Sml29623 
16524732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
16534732Sdavemq 
16544732Sdavemq static nxge_status_t
16554732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
16563859Sml29623 {
16573859Sml29623 	npi_handle_t		handle;
16583859Sml29623 	uint8_t			portn;
16596075Ssbehera 	int			chan, i;
16603859Sml29623 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
16613859Sml29623 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
16623859Sml29623 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
16633859Sml29623 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
16643859Sml29623 	uint64_t		val;
16653859Sml29623 	uint16_t		val16l;
16663859Sml29623 	uint16_t		val16h;
16673859Sml29623 	nxge_status_t		status = NXGE_OK;
16683859Sml29623 
16693859Sml29623 	portn = nxgep->mac.portnum;
16703859Sml29623 
16713859Sml29623 	if ((portn != 0) && (portn != 1))
16723859Sml29623 		return (NXGE_OK);
16733859Sml29623 
16744732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
16754732Sdavemq 	    "==> nxge_neptune_10G_serdes_init port<%d>", portn));
16763859Sml29623 	handle = nxgep->npi_handle;
16774732Sdavemq 	switch (portn) {
16784732Sdavemq 	case 0:
16796028Ssbehera 		/* Reset Serdes */
16806028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
16816028Ssbehera 		NXGE_DELAY(20);
16826028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
16836028Ssbehera 		NXGE_DELAY(2000);
16846028Ssbehera 
16856028Ssbehera 		/* Configure Serdes to 10G mode */
16866028Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
16876028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
16886028Ssbehera 
16894732Sdavemq 		ESR_REG_WR(handle, ESR_0_CONTROL_REG,
16904732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
16914732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
16924732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
16934732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
16944732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
16954732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
16964732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
16974732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
16984732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
16994732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
17004732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
17014732Sdavemq 
17024732Sdavemq 		/* Set Serdes0 Internal Loopback if necessary */
17034732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
17044732Sdavemq 			ESR_REG_WR(handle,
17054732Sdavemq 			    ESR_0_TEST_CONFIG_REG,
17064732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 |
17074732Sdavemq 			    ESR_PAD_LOOPBACK_CH2 |
17084732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 |
17094732Sdavemq 			    ESR_PAD_LOOPBACK_CH0);
17104732Sdavemq 		} else {
17114732Sdavemq 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
17123859Sml29623 		}
17134732Sdavemq 		break;
17144732Sdavemq 	case 1:
17156028Ssbehera 		/* Reset Serdes */
17166028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
17176028Ssbehera 		NXGE_DELAY(20);
17186028Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
17196028Ssbehera 		NXGE_DELAY(2000);
17206028Ssbehera 
17216028Ssbehera 		/* Configure Serdes to 10G mode */
17226028Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
17236028Ssbehera 		    ESR_PLL_CFG_10G_SERDES);
17246028Ssbehera 
17254732Sdavemq 		ESR_REG_WR(handle, ESR_1_CONTROL_REG,
17264732Sdavemq 		    ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
17274732Sdavemq 		    ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
17284732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
17294732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
17304732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
17314732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17324732Sdavemq 		    (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
17334732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
17344732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
17354732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
17364732Sdavemq 		    (0x1 << ESR_CTL_LOSADJ_3_SHIFT));
17374732Sdavemq 
17384732Sdavemq 		/* Set Serdes1 Internal Loopback if necessary */
17394732Sdavemq 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
17404732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
17414732Sdavemq 			    ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
17424732Sdavemq 			    ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
17434732Sdavemq 		} else {
17444732Sdavemq 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
17453859Sml29623 		}
17464732Sdavemq 		break;
17474732Sdavemq 	default:
17484732Sdavemq 		/* Nothing to do here */
17494732Sdavemq 		goto done;
17504732Sdavemq 	}
17514732Sdavemq 
17524732Sdavemq 	/* init TX RX channels */
17534732Sdavemq 	for (chan = 0; chan < 4; chan++) {
17544732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
17554732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17564732Sdavemq 		    &rx_tx_ctrl_l.value)) != NXGE_OK)
17573859Sml29623 			goto fail;
17584732Sdavemq 		if ((status = nxge_mdio_read(nxgep, portn,
17594732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17604732Sdavemq 		    &rx_tx_ctrl_h.value)) != NXGE_OK)
17613859Sml29623 			goto fail;
17623859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
17634732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17644732Sdavemq 		    &glue_ctrl0_l.value)) != NXGE_OK)
17653859Sml29623 			goto fail;
17663859Sml29623 		if ((status = nxge_mdio_read(nxgep, portn,
17674732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17684732Sdavemq 		    &glue_ctrl0_h.value)) != NXGE_OK)
17694732Sdavemq 			goto fail;
17704732Sdavemq 		rx_tx_ctrl_l.bits.enstretch = 1;
17714732Sdavemq 		rx_tx_ctrl_h.bits.vmuxlo = 2;
17724732Sdavemq 		rx_tx_ctrl_h.bits.vpulselo = 2;
17734732Sdavemq 		glue_ctrl0_l.bits.rxlosenable = 1;
17744732Sdavemq 		glue_ctrl0_l.bits.samplerate = 0xF;
17754732Sdavemq 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
17764732Sdavemq 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
17774732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
17784732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
17794732Sdavemq 		    rx_tx_ctrl_l.value)) != NXGE_OK)
17804732Sdavemq 			goto fail;
17814732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
17824732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
17834732Sdavemq 		    rx_tx_ctrl_h.value)) != NXGE_OK)
17844732Sdavemq 			goto fail;
17854732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
17864732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
17874732Sdavemq 		    glue_ctrl0_l.value)) != NXGE_OK)
17884732Sdavemq 			goto fail;
17894732Sdavemq 		if ((status = nxge_mdio_write(nxgep, portn,
17904732Sdavemq 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
17914732Sdavemq 		    glue_ctrl0_h.value)) != NXGE_OK)
17923859Sml29623 			goto fail;
17933859Sml29623 		}
17943859Sml29623 
17954732Sdavemq 	/* Apply Tx core reset */
17964732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn,
17974732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
17984732Sdavemq 	    (uint16_t)0)) != NXGE_OK)
17994732Sdavemq 		goto fail;
18004732Sdavemq 
18014732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18024732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
18034732Sdavemq 	    NXGE_OK)
18044732Sdavemq 		goto fail;
18054732Sdavemq 
18064732Sdavemq 	NXGE_DELAY(200);
18074732Sdavemq 
18084732Sdavemq 	/* Apply Rx core reset */
18094732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18104732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
18114732Sdavemq 	    NXGE_OK)
18124732Sdavemq 		goto fail;
18134732Sdavemq 
18144732Sdavemq 	NXGE_DELAY(200);
18154732Sdavemq 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18164732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
18174732Sdavemq 		goto fail;
18184732Sdavemq 
18194732Sdavemq 	NXGE_DELAY(200);
18204732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn,
18214732Sdavemq 	    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
18224732Sdavemq 	    &val16l)) != NXGE_OK)
18234732Sdavemq 		goto fail;
18244732Sdavemq 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
18254732Sdavemq 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
18264732Sdavemq 		goto fail;
18274732Sdavemq 	if ((val16l != 0) || (val16h != 0)) {
18284732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18295196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
18305196Ssbehera 		    "(val16l 0x%x val16h 0x%x)",
18315196Ssbehera 		    portn, val16l, val16h));
18324732Sdavemq 	}
18334732Sdavemq 
18344732Sdavemq 	if (portn == 0) {
18356075Ssbehera 		/* Wait for serdes to be ready */
18366075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
18376075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
18386075Ssbehera 			if ((val & ESR_SIG_P0_BITS_MASK) !=
18396075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
18406075Ssbehera 			    ESR_SIG_XSERDES_RDY_P0 |
18416075Ssbehera 			    ESR_SIG_XDETECT_P0_CH3 |
18426075Ssbehera 			    ESR_SIG_XDETECT_P0_CH2 |
18436075Ssbehera 			    ESR_SIG_XDETECT_P0_CH1 |
18446075Ssbehera 			    ESR_SIG_XDETECT_P0_CH0))
18456075Ssbehera 
18466075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
18476075Ssbehera 			else
18486075Ssbehera 				break;
18496075Ssbehera 		}
18506075Ssbehera 
18516075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
18526650Sjoycey 			/*
18536650Sjoycey 			 * RDY signal stays low may due to the absent of the
18546650Sjoycey 			 * external PHY, it is not an error condition. But still
18556650Sjoycey 			 * print the message for the debugging purpose when link
18566650Sjoycey 			 * stays down
18576650Sjoycey 			 */
18586075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18596075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
18606075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
18616835Syc148097 				goto done;
18624732Sdavemq 		}
18634732Sdavemq 	} else if (portn == 1) {
18646075Ssbehera 		/* Wait for serdes to be ready */
18656075Ssbehera 		for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
18666075Ssbehera 			ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
18676075Ssbehera 			if ((val & ESR_SIG_P1_BITS_MASK) !=
18686075Ssbehera 			    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
18696075Ssbehera 			    ESR_SIG_XSERDES_RDY_P1 |
18706075Ssbehera 			    ESR_SIG_XDETECT_P1_CH3 |
18716075Ssbehera 			    ESR_SIG_XDETECT_P1_CH2 |
18726075Ssbehera 			    ESR_SIG_XDETECT_P1_CH1 |
18736075Ssbehera 			    ESR_SIG_XDETECT_P1_CH0))
18746075Ssbehera 
18756075Ssbehera 				NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
18766075Ssbehera 			else
18776075Ssbehera 				break;
18786075Ssbehera 		}
18796075Ssbehera 
18806075Ssbehera 		if (i == MAX_SERDES_RDY_RETRIES) {
18816650Sjoycey 			/*
18826650Sjoycey 			 * RDY signal stays low may due to the absent of the
18836650Sjoycey 			 * external PHY, it is not an error condition. But still
18846650Sjoycey 			 * print the message for the debugging purpose when link
18856650Sjoycey 			 * stays down
18866650Sjoycey 			 */
18876075Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18886075Ssbehera 			    "nxge_neptune_10G_serdes_init: "
18896075Ssbehera 			    "Serdes/signal for port<%d> not ready", portn));
18906835Syc148097 				goto done;
18913859Sml29623 		}
18923859Sml29623 	}
18933859Sml29623 
18943859Sml29623 done:
18954732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
18964732Sdavemq 	    "<== nxge_neptune_10G_serdes_init port<%d>", portn));
18974732Sdavemq 
18983859Sml29623 	return (NXGE_OK);
18993859Sml29623 fail:
19005572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19014732Sdavemq 	    "nxge_neptune_10G_serdes_init: "
19024732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>", portn));
19033859Sml29623 
19043859Sml29623 	return (status);
19053859Sml29623 }
19063859Sml29623 
19074732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */
19084732Sdavemq 
19094732Sdavemq static nxge_status_t
19104732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep)
19113859Sml29623 {
19124732Sdavemq 	npi_handle_t		handle;
19134732Sdavemq 	uint8_t			portn;
19145196Ssbehera 	int			chan;
19155196Ssbehera 	sr_rx_tx_ctrl_l_t	rx_tx_ctrl_l;
19165196Ssbehera 	sr_rx_tx_ctrl_h_t	rx_tx_ctrl_h;
19175196Ssbehera 	sr_glue_ctrl0_l_t	glue_ctrl0_l;
19185196Ssbehera 	sr_glue_ctrl0_h_t	glue_ctrl0_h;
19194732Sdavemq 	uint64_t		val;
19205196Ssbehera 	uint16_t		val16l;
19215196Ssbehera 	uint16_t		val16h;
19225196Ssbehera 	nxge_status_t		status = NXGE_OK;
19233859Sml29623 
19243859Sml29623 	portn = nxgep->mac.portnum;
19254732Sdavemq 
19264732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
19274732Sdavemq 	    "==> nxge_1G_serdes_init port<%d>", portn));
19284732Sdavemq 
19294732Sdavemq 	handle = nxgep->npi_handle;
19304732Sdavemq 
19314732Sdavemq 	switch (portn) {
19324732Sdavemq 	case 0:
19335196Ssbehera 		/* Assert the reset register */
19345196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
19355196Ssbehera 		val |= ESR_RESET_0;
19365196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
19375196Ssbehera 
19385196Ssbehera 		/* Set the PLL register to 0x79 */
19395196Ssbehera 		ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
19405196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
19415196Ssbehera 
19425196Ssbehera 		/* Set the control register to 0x249249f */
19435196Ssbehera 		ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
19445196Ssbehera 
19455196Ssbehera 		/* Set Serdes0 Internal Loopback if necessary */
19465196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
19475196Ssbehera 			/* Set pad loopback modes 0xaa */
19485196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
19495196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
19505196Ssbehera 		} else {
19515196Ssbehera 			ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
19525196Ssbehera 		}
19535196Ssbehera 
19545196Ssbehera 		/* Deassert 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);
19584732Sdavemq 		break;
19595196Ssbehera 
19604732Sdavemq 	case 1:
19615196Ssbehera 		/* Assert the reset register */
19625196Ssbehera 		ESR_REG_RD(handle, ESR_RESET_REG, &val);
19635196Ssbehera 		val |= ESR_RESET_1;
19645196Ssbehera 		ESR_REG_WR(handle, ESR_RESET_REG, val);
19655196Ssbehera 
19665196Ssbehera 		/* Set PLL register to 0x79 */
19675196Ssbehera 		ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
19685196Ssbehera 		    ESR_PLL_CFG_1G_SERDES);
19695196Ssbehera 
19705196Ssbehera 		/* Set the control register to 0x249249f */
19715196Ssbehera 		ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
19725196Ssbehera 
19735196Ssbehera 		/* Set Serdes1 Internal Loopback if necessary */
19745196Ssbehera 		if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
19755196Ssbehera 			/* Set pad loopback mode 0xaa */
19765196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
19775196Ssbehera 			    ESR_TSTCFG_LBTEST_PAD);
19785196Ssbehera 		} else {
19795196Ssbehera 			ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
19805196Ssbehera 		}
19815196Ssbehera 
19825196Ssbehera 		/* Deassert 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);
19864732Sdavemq 		break;
19875196Ssbehera 
19884732Sdavemq 	default:
19895196Ssbehera 		/* Nothing to do here */
19905196Ssbehera 		goto done;
19915196Ssbehera 	}
19925196Ssbehera 
19935196Ssbehera 	/* init TX RX channels */
19945196Ssbehera 	for (chan = 0; chan < 4; chan++) {
19955196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
19965196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
19975196Ssbehera 		    &rx_tx_ctrl_l.value)) != NXGE_OK) {
19985196Ssbehera 			goto fail;
19995196Ssbehera 		}
20005196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20015196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
20025196Ssbehera 		    &rx_tx_ctrl_h.value)) != NXGE_OK) {
20035196Ssbehera 			goto fail;
20045196Ssbehera 		}
20055196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20065196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
20075196Ssbehera 		    &glue_ctrl0_l.value)) != NXGE_OK) {
20085196Ssbehera 			goto fail;
20095196Ssbehera 		}
20105196Ssbehera 		if ((status = nxge_mdio_read(nxgep, portn,
20115196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
20125196Ssbehera 		    &glue_ctrl0_h.value)) != NXGE_OK) {
20135196Ssbehera 			goto fail;
20145196Ssbehera 		}
20155196Ssbehera 
20165196Ssbehera 		rx_tx_ctrl_l.bits.enstretch = 1;
20175196Ssbehera 		rx_tx_ctrl_h.bits.vmuxlo = 2;
20185196Ssbehera 		rx_tx_ctrl_h.bits.vpulselo = 2;
20195196Ssbehera 		glue_ctrl0_l.bits.rxlosenable = 1;
20205196Ssbehera 		glue_ctrl0_l.bits.samplerate = 0xF;
20215196Ssbehera 		glue_ctrl0_l.bits.thresholdcount = 0xFF;
20225196Ssbehera 		glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
20235196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20245196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
20255196Ssbehera 		    rx_tx_ctrl_l.value)) != NXGE_OK) {
20265196Ssbehera 			goto fail;
20275196Ssbehera 		}
20285196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20295196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
20305196Ssbehera 		    rx_tx_ctrl_h.value)) != NXGE_OK) {
20315196Ssbehera 			goto fail;
20325196Ssbehera 		}
20335196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20345196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
20355196Ssbehera 		    glue_ctrl0_l.value)) != NXGE_OK) {
20365196Ssbehera 			goto fail;
20375196Ssbehera 		}
20385196Ssbehera 		if ((status = nxge_mdio_write(nxgep, portn,
20395196Ssbehera 		    ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
20405196Ssbehera 		    glue_ctrl0_h.value)) != NXGE_OK) {
20415196Ssbehera 			goto fail;
20425196Ssbehera 		}
20435196Ssbehera 	}
20445196Ssbehera 
20455196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20465196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
20474732Sdavemq 		goto fail;
20483859Sml29623 	}
20495196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20505196Ssbehera 	    ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
20515196Ssbehera 		goto fail;
20525196Ssbehera 	}
20535196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20545196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
20555196Ssbehera 		goto fail;
20565196Ssbehera 	}
20575196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20585196Ssbehera 	    ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
20595196Ssbehera 		goto fail;
20605196Ssbehera 	}
20615196Ssbehera 
20625196Ssbehera 	/* Apply Tx core reset */
20635196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20645196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
20655196Ssbehera 		goto fail;
20665196Ssbehera 	}
20675196Ssbehera 
20685196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20695196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
20705196Ssbehera 	    NXGE_OK) {
20715196Ssbehera 		goto fail;
20725196Ssbehera 	}
20735196Ssbehera 
20745196Ssbehera 	NXGE_DELAY(200);
20755196Ssbehera 
20765196Ssbehera 	/* Apply Rx core reset */
20775196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20785196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
20795196Ssbehera 	    NXGE_OK) {
20805196Ssbehera 		goto fail;
20815196Ssbehera 	}
20825196Ssbehera 
20835196Ssbehera 	NXGE_DELAY(200);
20845196Ssbehera 	if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20855196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
20865196Ssbehera 		goto fail;
20875196Ssbehera 	}
20885196Ssbehera 
20895196Ssbehera 	NXGE_DELAY(200);
20905196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20915196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
20925196Ssbehera 		goto fail;
20935196Ssbehera 	}
20945196Ssbehera 	if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
20955196Ssbehera 	    ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
20965196Ssbehera 		goto fail;
20975196Ssbehera 	}
20985196Ssbehera 	if ((val16l != 0) || (val16h != 0)) {
20995196Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21005196Ssbehera 		    "Failed to reset port<%d> XAUI Serdes "
21015196Ssbehera 		    "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
21025196Ssbehera 		status = NXGE_ERROR;
21035196Ssbehera 		goto fail;
21045196Ssbehera 	}
21055196Ssbehera 
21065196Ssbehera 	NXGE_DELAY(200);
21075196Ssbehera 	ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
21085196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21095196Ssbehera 	    "nxge_neptune_serdes_init: read internal signal reg port<%d> "
21105196Ssbehera 	    "val 0x%x", portn, val));
21115196Ssbehera 	if (portn == 0) {
21125196Ssbehera 		if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
21135196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
21146650Sjoycey 			/*
21156650Sjoycey 			 * RDY signal stays low may due to the absent of the
21166650Sjoycey 			 * external PHY, it is not an error condition. But still
21176650Sjoycey 			 * print the message for the debugging purpose when link
21186650Sjoycey 			 * stays down
21196650Sjoycey 			 */
21205196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21216650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
21226650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
21236835Syc148097 				goto done;
21245196Ssbehera 		}
21255196Ssbehera 	} else if (portn == 1) {
21265196Ssbehera 		if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
21275196Ssbehera 		    (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
21286650Sjoycey 			/*
21296650Sjoycey 			 * RDY signal stays low may due to the absent of the
21306650Sjoycey 			 * external PHY, it is not an error condition. But still
21316650Sjoycey 			 * print the message for the debugging purpose when link
21326650Sjoycey 			 * stays down
21336650Sjoycey 			 */
21345196Ssbehera 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21356650Sjoycey 			    "nxge_neptune_1G_serdes_init: "
21366650Sjoycey 			    "Serdes/signal for port<%d> not ready", portn));
21376835Syc148097 				goto done;
21386835Syc148097 
21395196Ssbehera 		}
21405196Ssbehera 	}
21415196Ssbehera done:
21424732Sdavemq 
21434732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
21444732Sdavemq 	    "<== nxge_1G_serdes_init port<%d>", portn));
21453859Sml29623 	return (NXGE_OK);
21464732Sdavemq fail:
21475196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21484732Sdavemq 	    "nxge_1G_serdes_init: "
21494732Sdavemq 	    "Failed to initialize Neptune serdes for port<%d>",
21504732Sdavemq 	    portn));
21514732Sdavemq 
21525196Ssbehera 	return (status);
21533859Sml29623 }
21543859Sml29623 
21555572Ssbehera /* Initialize the BCM 8704 xcvr */
21564732Sdavemq 
21574732Sdavemq static nxge_status_t
21585572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
21593859Sml29623 {
21603859Sml29623 	uint16_t		val;
21613859Sml29623 #ifdef	NXGE_DEBUG
21623859Sml29623 	uint8_t			portn;
21633859Sml29623 	uint16_t		val1;
21643859Sml29623 #endif
21653859Sml29623 	uint8_t			phy_port_addr;
21663859Sml29623 	pmd_tx_control_t	tx_ctl;
21673859Sml29623 	control_t		ctl;
21683859Sml29623 	phyxs_control_t		phyxs_ctl;
21693859Sml29623 	pcs_control_t		pcs_ctl;
21703859Sml29623 	uint32_t		delay = 0;
21713859Sml29623 	optics_dcntr_t		op_ctr;
21723859Sml29623 	nxge_status_t		status = NXGE_OK;
21733859Sml29623 #ifdef	NXGE_DEBUG
21743859Sml29623 	portn = nxgep->mac.portnum;
21753859Sml29623 #endif
21765572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
21774732Sdavemq 	    portn));
21784732Sdavemq 
21794732Sdavemq 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
21804732Sdavemq 
21814732Sdavemq 	/* Reset the transceiver */
21824732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
21834732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
21844732Sdavemq 		goto fail;
21854732Sdavemq 
21864732Sdavemq 	phyxs_ctl.bits.reset = 1;
21874732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
21884732Sdavemq 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
21894732Sdavemq 		goto fail;
21904732Sdavemq 
21914732Sdavemq 	do {
21924732Sdavemq 		drv_usecwait(500);
21934732Sdavemq 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
21944732Sdavemq 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
21954732Sdavemq 		    &phyxs_ctl.value)) != NXGE_OK)
21964732Sdavemq 			goto fail;
21974732Sdavemq 		delay++;
21984732Sdavemq 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
21994732Sdavemq 	if (delay == 100) {
22004732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
22014732Sdavemq 		    "failed to reset Transceiver on port<%d>", portn));
22024732Sdavemq 		status = NXGE_ERROR;
22034732Sdavemq 		goto fail;
22044732Sdavemq 	}
22054732Sdavemq 
22064732Sdavemq 	/* Set to 0x7FBF */
22074732Sdavemq 	ctl.value = 0;
22084732Sdavemq 	ctl.bits.res1 = 0x3F;
22094732Sdavemq 	ctl.bits.optxon_lvl = 1;
22104732Sdavemq 	ctl.bits.oprxflt_lvl = 1;
22114732Sdavemq 	ctl.bits.optrxlos_lvl = 1;
22124732Sdavemq 	ctl.bits.optxflt_lvl = 1;
22134732Sdavemq 	ctl.bits.opprflt_lvl = 1;
22144732Sdavemq 	ctl.bits.obtmpflt_lvl = 1;
22154732Sdavemq 	ctl.bits.opbiasflt_lvl = 1;
22164732Sdavemq 	ctl.bits.optxrst_lvl = 1;
22174732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22184732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
22194732Sdavemq 	    != NXGE_OK)
22204732Sdavemq 		goto fail;
22214732Sdavemq 
22224732Sdavemq 	/* Set to 0x164 */
22234732Sdavemq 	tx_ctl.value = 0;
22244732Sdavemq 	tx_ctl.bits.tsck_lpwren = 1;
22254732Sdavemq 	tx_ctl.bits.tx_dac_txck = 0x2;
22264732Sdavemq 	tx_ctl.bits.tx_dac_txd = 0x1;
22274732Sdavemq 	tx_ctl.bits.xfp_clken = 1;
22284732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22294732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
22304732Sdavemq 	    tx_ctl.value)) != NXGE_OK)
22314732Sdavemq 		goto fail;
22324732Sdavemq 	/*
22334732Sdavemq 	 * According to Broadcom's instruction, SW needs to read
22344732Sdavemq 	 * back these registers twice after written.
22354732Sdavemq 	 */
22364732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22374732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
22384732Sdavemq 	    != NXGE_OK)
22394732Sdavemq 		goto fail;
22404732Sdavemq 
22414732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22424732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
22434732Sdavemq 	    != NXGE_OK)
22444732Sdavemq 		goto fail;
22454732Sdavemq 
22464732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22474732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
22484732Sdavemq 	    != NXGE_OK)
22494732Sdavemq 		goto fail;
22504732Sdavemq 
22514732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22524732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
22534732Sdavemq 	    != NXGE_OK)
22544732Sdavemq 		goto fail;
22554732Sdavemq 
22564732Sdavemq 	/* Enable Tx and Rx LEDs to be driven by traffic */
22574732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22584732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
22594732Sdavemq 	    &op_ctr.value)) != NXGE_OK)
22604732Sdavemq 		goto fail;
22615553Smisaki 	if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
22625553Smisaki 		op_ctr.bits.gpio_sel = 0x1;
22635553Smisaki 	} else {
22645553Smisaki 		op_ctr.bits.gpio_sel = 0x3;
22655553Smisaki 	}
22664732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22674732Sdavemq 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
22684732Sdavemq 	    op_ctr.value)) != NXGE_OK)
22694732Sdavemq 		goto fail;
22704732Sdavemq 
22714732Sdavemq 	NXGE_DELAY(1000000);
22724732Sdavemq 
22734732Sdavemq 	/* Set BCM8704 Internal Loopback mode if necessary */
22744732Sdavemq 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
22754732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
22764732Sdavemq 	    != NXGE_OK)
22774732Sdavemq 		goto fail;
22784732Sdavemq 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
22794732Sdavemq 		pcs_ctl.bits.loopback = 1;
22804732Sdavemq 	else
22814732Sdavemq 		pcs_ctl.bits.loopback = 0;
22824732Sdavemq 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
22834732Sdavemq 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
22844732Sdavemq 	    != NXGE_OK)
22854732Sdavemq 		goto fail;
22864732Sdavemq 
22874732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
22884732Sdavemq 	if (status != NXGE_OK)
22894732Sdavemq 		goto fail;
22904732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
22914732Sdavemq 	    "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
22924732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
22934732Sdavemq 	if (status != NXGE_OK)
22944732Sdavemq 		goto fail;
22954732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
22964732Sdavemq 	    "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
22974732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
22984732Sdavemq 	if (status != NXGE_OK)
22994732Sdavemq 		goto fail;
23004732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23014732Sdavemq 	    "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
23024732Sdavemq 
23034732Sdavemq #ifdef	NXGE_DEBUG
23044732Sdavemq 	/* Diagnose link issue if link is not up */
23054732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
23064732Sdavemq 	    BCM8704_USER_ANALOG_STATUS0_REG,
23074732Sdavemq 	    &val);
23084732Sdavemq 	if (status != NXGE_OK)
23094732Sdavemq 		goto fail;
23104732Sdavemq 
23114732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23126929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
23134732Sdavemq 	if (status != NXGE_OK)
23144732Sdavemq 		goto fail;
23154732Sdavemq 
23164732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23176929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
23184732Sdavemq 	if (status != NXGE_OK)
23194732Sdavemq 		goto fail;
23204732Sdavemq 
23214732Sdavemq 	status = nxge_mdio_read(nxgep, phy_port_addr,
23226929Smisaki 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
23234732Sdavemq 	if (status != NXGE_OK)
23244732Sdavemq 		goto fail;
23254732Sdavemq 
23264732Sdavemq 	if (val != 0x3FC) {
23274732Sdavemq 		if ((val == 0x43BC) && (val1 != 0)) {
23284732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
23294732Sdavemq 			    "Cable not connected to peer or bad"
23304732Sdavemq 			    " cable on port<%d>\n", portn));
23314732Sdavemq 		} else if (val == 0x639C) {
23324732Sdavemq 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23334732Sdavemq 			    "Optical module (XFP) is bad or absent"
23344732Sdavemq 			    " on port<%d>\n", portn));
23354732Sdavemq 		}
23364732Sdavemq 	}
23374732Sdavemq #endif
23384732Sdavemq 
23395572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
23405572Ssbehera 	    portn));
23415572Ssbehera 	return (NXGE_OK);
23425572Ssbehera 
23435572Ssbehera fail:
23445572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23455572Ssbehera 	    "nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
23465572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
23475572Ssbehera 	return (NXGE_ERROR);
23485572Ssbehera }
23495572Ssbehera 
23505572Ssbehera /* Initialize the BCM 8706 Transceiver */
23515572Ssbehera 
23525572Ssbehera static nxge_status_t
23535572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
23545572Ssbehera {
23555572Ssbehera 	uint8_t			phy_port_addr;
23565572Ssbehera 	phyxs_control_t		phyxs_ctl;
23575572Ssbehera 	pcs_control_t		pcs_ctl;
23585572Ssbehera 	uint32_t		delay = 0;
23595572Ssbehera 	optics_dcntr_t		op_ctr;
23605572Ssbehera 	nxge_status_t		status = NXGE_OK;
23615572Ssbehera #ifdef	NXGE_DEBUG
23625572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
23635572Ssbehera #endif
23645572Ssbehera 
23655572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
23665572Ssbehera 	    portn));
23675572Ssbehera 
23685572Ssbehera 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
23695572Ssbehera 
23705572Ssbehera 	/* Reset the transceiver */
23715572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23725572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
23735572Ssbehera 		goto fail;
23745572Ssbehera 
23755572Ssbehera 	phyxs_ctl.bits.reset = 1;
23765572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
23775572Ssbehera 	    BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
23785572Ssbehera 		goto fail;
23795572Ssbehera 	do {
23805572Ssbehera 		drv_usecwait(500);
23815572Ssbehera 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
23825572Ssbehera 		    BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
23835572Ssbehera 		    &phyxs_ctl.value)) != NXGE_OK)
23845572Ssbehera 			goto fail;
23855572Ssbehera 		delay++;
23865572Ssbehera 	} while ((phyxs_ctl.bits.reset) && (delay < 100));
23875572Ssbehera 
23885572Ssbehera 	if (delay == 100) {
23895572Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
23905572Ssbehera 		    "failed to reset Transceiver on port<%d>", portn));
23915572Ssbehera 		status = NXGE_ERROR;
23925572Ssbehera 		goto fail;
23935572Ssbehera 	}
23945572Ssbehera 
23955572Ssbehera 	NXGE_DELAY(1000000);
23965572Ssbehera 
23975572Ssbehera 	/* Set BCM8706 Internal Loopback mode if necessary */
23985572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
23995572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
24005572Ssbehera 	    != NXGE_OK)
24015572Ssbehera 		goto fail;
24025572Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24035572Ssbehera 		pcs_ctl.bits.loopback = 1;
24045572Ssbehera 	else
24055572Ssbehera 		pcs_ctl.bits.loopback = 0;
24065572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24075572Ssbehera 	    BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
24085572Ssbehera 	    != NXGE_OK)
24095572Ssbehera 		goto fail;
24105572Ssbehera 
24115572Ssbehera 	/* Enable Tx and Rx LEDs to be driven by traffic */
24125572Ssbehera 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
24135572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24145572Ssbehera 	    &op_ctr.value)) != NXGE_OK)
24155572Ssbehera 		goto fail;
24165572Ssbehera 	op_ctr.bits.gpio_sel = 0x3;
24175572Ssbehera 	op_ctr.bits.res2 = 0x1;
24185572Ssbehera 
24195572Ssbehera 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
24205572Ssbehera 	    BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
24215572Ssbehera 	    op_ctr.value)) != NXGE_OK)
24225572Ssbehera 		goto fail;
24235572Ssbehera 
24245572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
24255572Ssbehera 	    portn));
24265572Ssbehera 	return (NXGE_OK);
24275572Ssbehera 
24285572Ssbehera fail:
24295572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24305572Ssbehera 	    "nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
24315572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
24325572Ssbehera 	return (status);
24335572Ssbehera }
24345572Ssbehera 
24356604Ssbehera #define	CHK_STAT(x)	status = (x); if (status != NXGE_OK) goto fail
24366604Ssbehera 
24376604Ssbehera #define	MRVL88X2011_RD(nxgep, port, d, r, p) \
24386604Ssbehera 	CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
24396604Ssbehera 
24406604Ssbehera #define	MRVL88X2011_WR(nxgep, port, d, r, p) \
24416604Ssbehera 	CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
24426604Ssbehera 
24436604Ssbehera 
24446604Ssbehera static void
24456604Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
24466604Ssbehera {
24476604Ssbehera 	uint16_t	value;
24486604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
24496604Ssbehera 
24506604Ssbehera 	if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
24516604Ssbehera 	    MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
24526604Ssbehera 		value &= ~MRVL_88X2011_LED_BLK_MASK;
24536604Ssbehera 		value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
24546604Ssbehera 		(void) nxge_mdio_write(nxgep, phy,
24556604Ssbehera 		    MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
24566604Ssbehera 		    value);
24576604Ssbehera 	}
24586604Ssbehera }
24596604Ssbehera 
24606604Ssbehera static nxge_status_t
24616604Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
24626604Ssbehera {
24636604Ssbehera 	nxge_status_t	status;
24646604Ssbehera 	pcs_control_t	pcs_ctl;
24656604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
24666604Ssbehera 
24676604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
24686604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
24696604Ssbehera 
24706604Ssbehera 	if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
24716604Ssbehera 		pcs_ctl.bits.loopback = 1;
24726604Ssbehera 	else
24736604Ssbehera 		pcs_ctl.bits.loopback = 0;
24746604Ssbehera 
24756604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
24766604Ssbehera 	    MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
24776604Ssbehera 
24786604Ssbehera fail:
24796604Ssbehera 	return (status);
24806604Ssbehera }
24816604Ssbehera 
24826604Ssbehera 
24836604Ssbehera static void
24846604Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep,  uint16_t val)
24856604Ssbehera {
24866604Ssbehera 	uint16_t	val2;
24876604Ssbehera 	uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
24886604Ssbehera 
24896604Ssbehera 	val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
24906604Ssbehera 	val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
24916604Ssbehera 	    MRVL_88X2011_LED_CTL_MASK);
24926604Ssbehera 	val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
24936604Ssbehera 
24946604Ssbehera 	if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
24956604Ssbehera 	    MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
24966604Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24976604Ssbehera 		    "nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
24986604Ssbehera 	}
24996604Ssbehera }
25006604Ssbehera 
25016604Ssbehera 
25026604Ssbehera static nxge_status_t
25036604Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
25046604Ssbehera {
25056604Ssbehera 	uint8_t		phy;
25066604Ssbehera 	nxge_status_t	status;
25076604Ssbehera 	uint16_t	clk;
25086604Ssbehera 
25096604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
25106604Ssbehera 
25116604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
25126604Ssbehera 	    "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
25136604Ssbehera 	    nxgep->mac.portnum, phy));
25146604Ssbehera 
25156604Ssbehera 	/* Set LED functions	*/
25166604Ssbehera 	nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
25176604Ssbehera 	/* PCS activity */
25186604Ssbehera 	nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
25196604Ssbehera 
25206604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
25216604Ssbehera 	    MRVL_88X2011_GEN_CTL, &clk);
25226604Ssbehera 	clk |= MRVL_88X2011_ENA_XFPREFCLK;
25236604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
25246604Ssbehera 	    MRVL_88X2011_GEN_CTL, clk);
25256604Ssbehera 
25266604Ssbehera 	/* Set internal loopback mode if necessary */
25276604Ssbehera 
25286604Ssbehera 	CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
25296604Ssbehera 
25306604Ssbehera 	/* Enable PMD */
25316604Ssbehera 	MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
25326604Ssbehera 	    MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
25336604Ssbehera 
25346604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
25356604Ssbehera 
25366604Ssbehera fail:
25376604Ssbehera 	return (status);
25386604Ssbehera }
25396604Ssbehera 
25406604Ssbehera 
25416604Ssbehera 
25425572Ssbehera /* Initialize the 10G Transceiver */
25435572Ssbehera 
25445572Ssbehera static nxge_status_t
25455572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep)
25465572Ssbehera {
25475572Ssbehera 	p_nxge_stats_t		statsp;
25486439Sml29623 	p_nxge_param_t		param_arr = nxgep->param_arr;
25495572Ssbehera 	nxge_status_t		status = NXGE_OK;
25505572Ssbehera #ifdef	NXGE_DEBUG
25515572Ssbehera 	uint8_t			portn = nxgep->mac.portnum;
25525572Ssbehera #endif
25535572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
25545572Ssbehera 	    portn));
25555572Ssbehera 
25565572Ssbehera 	statsp = nxgep->statsp;
25575572Ssbehera 
25585572Ssbehera 	if (nxgep->mac.portmode == PORT_10G_SERDES) {
25595572Ssbehera 		goto done;
25605572Ssbehera 	}
25615572Ssbehera 
25625572Ssbehera 	/* Disable Link LEDs */
25635572Ssbehera 	if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
25645572Ssbehera 		goto fail;
25655572Ssbehera 
25665572Ssbehera 	/* Set Clause 45 */
25675572Ssbehera 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
25685572Ssbehera 
25695572Ssbehera 	switch (nxgep->chip_id) {
25705572Ssbehera 	case BCM8704_CHIP_ID:
25716835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25725572Ssbehera 		    "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
25735572Ssbehera 		status = nxge_BCM8704_xcvr_init(nxgep);
25745572Ssbehera 		break;
25755572Ssbehera 	case BCM8706_CHIP_ID:
25766835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25775572Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
25785572Ssbehera 		status = nxge_BCM8706_xcvr_init(nxgep);
25795572Ssbehera 		break;
25806604Ssbehera 	case MRVL88X201X_CHIP_ID:
25816835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
25826604Ssbehera 		    "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
25836604Ssbehera 		status = nxge_mrvl88x2011_xcvr_init(nxgep);
25846604Ssbehera 		break;
25855572Ssbehera 	default:
25865572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
25875572Ssbehera 		    "Unknown chip ID 0x%x for 10G xcvr addr[%d]",
25885572Ssbehera 		    nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
25895572Ssbehera 		goto fail;
25905572Ssbehera 	}
25915572Ssbehera 
25925572Ssbehera 	if (status != NXGE_OK) {
25935572Ssbehera 		goto fail;
25945572Ssbehera 	}
25954977Sraghus done:
25964732Sdavemq 	statsp->mac_stats.cap_10gfdx = 1;
25974732Sdavemq 	statsp->mac_stats.lp_cap_10gfdx = 1;
25986439Sml29623 	statsp->mac_stats.adv_cap_asmpause =
25996439Sml29623 	    param_arr[param_anar_asmpause].value;
26006439Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
26014732Sdavemq 
26024732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
26034732Sdavemq 	    portn));
26044732Sdavemq 	return (NXGE_OK);
26054732Sdavemq 
26064732Sdavemq fail:
26075572Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
26084732Sdavemq 	    "nxge_10G_xcvr_init: failed to initialize transceiver for "
26095572Ssbehera 	    "port<%d>", nxgep->mac.portnum));
26105572Ssbehera 	return (NXGE_ERROR);
26114732Sdavemq }
26124732Sdavemq 
26134732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */
26144732Sdavemq 
26154732Sdavemq static nxge_status_t
26164732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep)
26174732Sdavemq {
26184732Sdavemq 	p_nxge_param_t		param_arr = nxgep->param_arr;
26194732Sdavemq 	p_nxge_stats_t		statsp = nxgep->statsp;
26204732Sdavemq 	nxge_status_t		status = NXGE_OK;
26214732Sdavemq 
26224977Sraghus 	if (nxgep->mac.portmode == PORT_1G_SERDES) {
26234977Sraghus 		statsp->mac_stats.cap_1000fdx =
26244977Sraghus 		    param_arr[param_anar_1000fdx].value;
26254977Sraghus 		goto done;
26264977Sraghus 	}
26274977Sraghus 
26284732Sdavemq 	/* Set Clause 22 */
26294732Sdavemq 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
26304732Sdavemq 
26314732Sdavemq 	/* Set capability flags */
26324732Sdavemq 	statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
26334977Sraghus 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
26344977Sraghus 	    (nxgep->mac.portmode == PORT_1G_FIBER)) {
26354977Sraghus 		statsp->mac_stats.cap_100fdx =
26364977Sraghus 		    param_arr[param_anar_100fdx].value;
26374977Sraghus 		statsp->mac_stats.cap_10fdx =
26384977Sraghus 		    param_arr[param_anar_10fdx].value;
26394977Sraghus 	}
26404732Sdavemq 
26414732Sdavemq 	status = nxge_mii_xcvr_init(nxgep);
26424977Sraghus done:
26434732Sdavemq 	return (status);
26444732Sdavemq }
26454732Sdavemq 
26466835Syc148097 /*
26476835Syc148097  * Although the Teranetics copper transceiver (TN1010) does not need
26486835Syc148097  * to be initialized by the driver for passing packets, this funtion
26496835Syc148097  * initializes the members of nxgep->statsp->mac_stats struct for
26506835Syc148097  * kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
26516835Syc148097  * It also configures the TN1010 for PHY loopback to support SunVTS.
26526835Syc148097  *
26536835Syc148097  * TN1010 only has the option to disable advertisement for the 10G
26546835Syc148097  * mode. So we can set it to either Dual Mode or 1G Only mode but
26556835Syc148097  * can't set it to 10G Only mode.
26566835Syc148097  *
26576835Syc148097  * ndd -set command can set the following 6 speed/duplex related parameters.
26586835Syc148097  *
26596835Syc148097  * ----------------------------------------------------------------
26606835Syc148097  * ndd -set /dev/nxgeX param n		kstat nxge:X | grep param
26616835Syc148097  * ----------------------------------------------------------------
26626835Syc148097  * adv_autoneg_cap		kstat nxge:1 | grep adv_cap_autoneg
26636835Syc148097  * adv_10gfdx_cap
26646835Syc148097  * adv_1000fdx_cap		kstat nxge:1 | grep adv_cap_1000fdx
26656835Syc148097  * adv_100fdx_cap		kstat nxge:1 | grep adv_cap_100fdx
26666835Syc148097  * adv_10fdx_cap		kstat nxge:1 | grep adv_cap_10fdx
26676835Syc148097  * adv_pause_cap		kstat nxge:1 | grep adv_cap_pause
26686835Syc148097  * ----------------------------------------------------------------
26696835Syc148097  */
26706835Syc148097 static nxge_status_t
26716835Syc148097 nxge_tn1010_xcvr_init(p_nxge_t nxgep)
26726835Syc148097 {
26736835Syc148097 	p_nxge_param_t		param_arr;
26746835Syc148097 	p_nxge_stats_t		statsp;
26756835Syc148097 	tn1010_pcs_ctrl_t	tn1010_pcs_ctrl;
26766835Syc148097 	uint16_t		speed;
26776835Syc148097 	uint8_t			phy_port_addr;
26786835Syc148097 	uint8_t			portn = NXGE_GET_PORT_NUM(nxgep->function_num);
26796835Syc148097 	int			status = NXGE_OK;
26806835Syc148097 
26816835Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
26826835Syc148097 
26836835Syc148097 	param_arr	= nxgep->param_arr;
26846835Syc148097 	statsp		= nxgep->statsp;
26856835Syc148097 
26866835Syc148097 	/*
26876835Syc148097 	 * Initialize the xcvr statistics which are NOT controlled by ndd
26886835Syc148097 	 */
26896835Syc148097 	statsp->mac_stats.cap_autoneg  = 1; /* TN1010 autoneg is always on */
26906835Syc148097 	statsp->mac_stats.cap_100T4    = 0;
26916835Syc148097 
26926835Syc148097 	/*
26936835Syc148097 	 * Read the TN1010 link speed and initialize capabilities kstat. Note
26946835Syc148097 	 * that function nxge_check_tn1010_link repeatedly invoked by the
26956835Syc148097 	 * timer will update link_speed real time.
26966835Syc148097 	 */
26976835Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
26986835Syc148097 		goto fail;
26996835Syc148097 	}
27006835Syc148097 	if (speed == TN1010_SPEED_1G) {
27016835Syc148097 		statsp->mac_stats.cap_10gfdx = 0;
27026835Syc148097 	} else {
27036835Syc148097 		statsp->mac_stats.cap_10gfdx = 1;
27046835Syc148097 	}
27056835Syc148097 
27066835Syc148097 	/* Whether we are in 1G or 10G mode, we always have the 1G capability */
27076835Syc148097 	statsp->mac_stats.cap_1000fdx  = 1;
27086835Syc148097 
27096835Syc148097 	/* TN1010 is not able to operate in the following states */
27106835Syc148097 	statsp->mac_stats.cap_1000hdx  = 0;
27116835Syc148097 	statsp->mac_stats.cap_100fdx   = 0;
27126835Syc148097 	statsp->mac_stats.cap_100hdx   = 0;
27136835Syc148097 	statsp->mac_stats.cap_10fdx    = 0;
27146835Syc148097 	statsp->mac_stats.cap_10hdx    = 0;
27156835Syc148097 
27166835Syc148097 	/* param_anar_pause can be modified by ndd -set */
27176835Syc148097 	statsp->mac_stats.cap_pause    = param_arr[param_anar_pause].value;
27186835Syc148097 
27196835Syc148097 	/*
27206835Syc148097 	 * The following 4 lines actually overwrites what ever the ndd command
27216835Syc148097 	 * has set. For example, by command
27226835Syc148097 	 * 	ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1)
27236835Syc148097 	 * we could set param_arr[param_autoneg].value to n.  However, because
27246835Syc148097 	 * here we assign constants to these parameters, whatever we set with
27256835Syc148097 	 * the "ndd -set" command will be replaced. So command
27266835Syc148097 	 *	kstat nxge:X | grep param
27276835Syc148097 	 * will always show those constant values.  In other words, the
27286835Syc148097 	 * "ndd -set" command can NOT change the values of these 4 parameters
27296835Syc148097 	 * even though the command appears to be successful.
27306835Syc148097 	 *
27316835Syc148097 	 * Note: TN1010 auto negotiation is always enabled.
27326835Syc148097 	 */
27336835Syc148097 	statsp->mac_stats.adv_cap_autoneg
27346835Syc148097 	    = param_arr[param_autoneg].value = 1;
27356835Syc148097 	statsp->mac_stats.adv_cap_1000fdx
27366835Syc148097 	    = param_arr[param_anar_1000fdx].value = 1;
27376835Syc148097 	statsp->mac_stats.adv_cap_100fdx
27386835Syc148097 	    = param_arr[param_anar_100fdx].value = 0;
27396835Syc148097 	statsp->mac_stats.adv_cap_10fdx
27406835Syc148097 	    = param_arr[param_anar_10fdx].value = 0;
27416835Syc148097 
27426835Syc148097 	/*
27436835Syc148097 	 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
27446835Syc148097 	 * defined in nxge_param_arr[], therefore they are not seen by the
27456835Syc148097 	 * "ndd -get" command and can not be changed by ndd.  We just set
27466835Syc148097 	 * them (both ndd param and kstat values) to constant 0 because TN1010
27476835Syc148097 	 * does not support those speeds.
27486835Syc148097 	 */
27496835Syc148097 	statsp->mac_stats.adv_cap_100T4
27506835Syc148097 	    = param_arr[param_anar_100T4].value = 0;
27516835Syc148097 	statsp->mac_stats.adv_cap_1000hdx
27526835Syc148097 	    = param_arr[param_anar_1000hdx].value = 0;
27536835Syc148097 	statsp->mac_stats.adv_cap_100hdx
27546835Syc148097 	    = param_arr[param_anar_100hdx].value = 0;
27556835Syc148097 	statsp->mac_stats.adv_cap_10hdx
27566835Syc148097 	    = param_arr[param_anar_10hdx].value = 0;
27576835Syc148097 
27586835Syc148097 	/*
27596835Syc148097 	 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
27606835Syc148097 	 * by ndd
27616835Syc148097 	 */
27626835Syc148097 	statsp->mac_stats.adv_cap_pause    = param_arr[param_anar_pause].value;
27636835Syc148097 
27646835Syc148097 	/*
27656835Syc148097 	 * nxge_param_arr[] defines the adv_cap_asmpause with type
27666835Syc148097 	 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
27676835Syc148097 	 * "ndd -get" command and can not be changed by ndd. Here we do not
27686835Syc148097 	 * assign a constant to it so the default value defined in
27696835Syc148097 	 * nxge_param_arr[] will be used to set the parameter and
27706835Syc148097 	 * will be shown by the kstat.
27716835Syc148097 	 */
27726835Syc148097 	statsp->mac_stats.adv_cap_asmpause
27736835Syc148097 	    = param_arr[param_anar_asmpause].value;
27746835Syc148097 
27756835Syc148097 	/*
27766835Syc148097 	 * Initialize the link statistics.
27776835Syc148097 	 */
27786835Syc148097 	statsp->mac_stats.link_T4 = 0;
27796835Syc148097 	statsp->mac_stats.link_asmpause = 0;
27806835Syc148097 	statsp->mac_stats.link_pause = 0;
27816835Syc148097 	if (speed == TN1010_SPEED_1G) {
27826835Syc148097 		statsp->mac_stats.link_speed = 1000;
27836835Syc148097 		statsp->mac_stats.link_duplex = 2;	/* Full duplex */
27846835Syc148097 		statsp->mac_stats.link_up = 1;
27856835Syc148097 	} else {
27866835Syc148097 		statsp->mac_stats.link_speed = 10000;
27876835Syc148097 		statsp->mac_stats.link_duplex = 2;
27886835Syc148097 		statsp->mac_stats.link_up = 1;
27896835Syc148097 	}
27906835Syc148097 
27916835Syc148097 	/*
27926835Syc148097 	 * Because TN1010 does not have a link partner register, to
27936835Syc148097 	 * figure out the link partner's capabilities is tricky. Here we
27946835Syc148097 	 * just set the kstat based on our knowledge about the partner
27956835Syc148097 	 * (The partner must support auto-neg because auto-negotiation
27966835Syc148097 	 * has completed, it must support 1G or 10G because that is the
27976835Syc148097 	 * negotiated speed we are using.)
27986835Syc148097 	 *
27996835Syc148097 	 * Note: Current kstat does not show lp_cap_10gfdx and
28006835Syc148097 	 *	lp_cap_10ghdx.
28016835Syc148097 	 */
28026835Syc148097 	if (speed == TN1010_SPEED_1G) {
28036835Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 1;
28046835Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 0;
28056835Syc148097 	} else {
28066835Syc148097 		statsp->mac_stats.lp_cap_1000fdx  = 0;
28076835Syc148097 		statsp->mac_stats.lp_cap_10gfdx   = 1;
28086835Syc148097 	}
28096835Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
28106835Syc148097 	statsp->mac_stats.lp_cap_1000hdx  = 0;
28116835Syc148097 	statsp->mac_stats.lp_cap_100fdx   = 0;
28126835Syc148097 	statsp->mac_stats.lp_cap_100hdx   = 0;
28136835Syc148097 	statsp->mac_stats.lp_cap_10fdx    = 0;
28146835Syc148097 	statsp->mac_stats.lp_cap_10hdx    = 0;
28156835Syc148097 	statsp->mac_stats.lp_cap_10gfdx   = 0;
28166835Syc148097 	statsp->mac_stats.lp_cap_10ghdx   = 0;
28176835Syc148097 	statsp->mac_stats.lp_cap_100T4    = 0;
28186835Syc148097 	statsp->mac_stats.lp_cap_autoneg  = 1;
28196835Syc148097 	statsp->mac_stats.lp_cap_asmpause = 0;
28206835Syc148097 	statsp->mac_stats.lp_cap_pause    = 0;
28216835Syc148097 
28226835Syc148097 	/* Handle PHY loopback for SunVTS loopback test */
28236835Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
28246835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
28256835Syc148097 
28266835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
28276835Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
28286835Syc148097 	    &tn1010_pcs_ctrl.value)) != NXGE_OK) {
28296835Syc148097 		goto fail;
28306835Syc148097 	}
28316835Syc148097 	if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
28326835Syc148097 	    (statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
28336835Syc148097 		tn1010_pcs_ctrl.bits.loopback = 1;
28346835Syc148097 	} else {
28356835Syc148097 		tn1010_pcs_ctrl.bits.loopback = 0;
28366835Syc148097 	}
28376835Syc148097 	if ((status = nxge_mdio_write(nxgep, phy_port_addr,
28386835Syc148097 	    TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
28396835Syc148097 	    tn1010_pcs_ctrl.value)) != NXGE_OK) {
28406835Syc148097 		goto fail;
28416835Syc148097 	}
28426835Syc148097 
28436835Syc148097 	statsp->mac_stats.xcvr_inits++;
28446835Syc148097 
28456835Syc148097 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
28466835Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
28476835Syc148097 	return (status);
28486835Syc148097 fail:
28496835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
28506835Syc148097 	    "<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
28516835Syc148097 	return (status);
28526835Syc148097 }
28536835Syc148097 
28544732Sdavemq /* Initialize transceiver */
28554732Sdavemq 
28564732Sdavemq nxge_status_t
28574732Sdavemq nxge_xcvr_init(p_nxge_t nxgep)
28584732Sdavemq {
28594732Sdavemq 	p_nxge_stats_t		statsp;
28604732Sdavemq #ifdef	NXGE_DEBUG
28614732Sdavemq 	uint8_t			portn;
28624732Sdavemq #endif
28634732Sdavemq 
28644732Sdavemq 	nxge_status_t		status = NXGE_OK;
28654732Sdavemq #ifdef	NXGE_DEBUG
28664732Sdavemq 	portn = nxgep->mac.portnum;
28674732Sdavemq #endif
28683859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
28693859Sml29623 	statsp = nxgep->statsp;
28703859Sml29623 
28713859Sml29623 	/*
28726835Syc148097 	 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
28736835Syc148097 	 * modify mac_stats.
28743859Sml29623 	 */
28753859Sml29623 	statsp->mac_stats.cap_autoneg = 0;
28763859Sml29623 	statsp->mac_stats.cap_100T4 = 0;
28773859Sml29623 	statsp->mac_stats.cap_100fdx = 0;
28783859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
28793859Sml29623 	statsp->mac_stats.cap_10fdx = 0;
28803859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
28813859Sml29623 	statsp->mac_stats.cap_asmpause = 0;
28823859Sml29623 	statsp->mac_stats.cap_pause = 0;
28833859Sml29623 	statsp->mac_stats.cap_1000fdx = 0;
28843859Sml29623 	statsp->mac_stats.cap_1000hdx = 0;
28853859Sml29623 	statsp->mac_stats.cap_10gfdx = 0;
28863859Sml29623 	statsp->mac_stats.cap_10ghdx = 0;
28873859Sml29623 
28883859Sml29623 	/*
28893859Sml29623 	 * Initialize the link statistics.
28903859Sml29623 	 */
28913859Sml29623 	statsp->mac_stats.link_T4 = 0;
28923859Sml29623 	statsp->mac_stats.link_asmpause = 0;
28933859Sml29623 	statsp->mac_stats.link_pause = 0;
28943859Sml29623 
28954732Sdavemq 	if (nxgep->xcvr.xcvr_init) {
28964732Sdavemq 		status = nxgep->xcvr.xcvr_init(nxgep);
28973859Sml29623 		if (status != NXGE_OK)
28983859Sml29623 			goto fail;
28994732Sdavemq 		statsp->mac_stats.xcvr_inits++;
29003859Sml29623 	}
29013859Sml29623 
29024732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
29034732Sdavemq 	    portn));
29043859Sml29623 	return (NXGE_OK);
29053859Sml29623 
29063859Sml29623 fail:
29073859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29084732Sdavemq 	    "nxge_xcvr_init: failed to initialize transceiver for port<%d>",
29094732Sdavemq 	    portn));
29103859Sml29623 	return (status);
29113859Sml29623 }
29123859Sml29623 
29134977Sraghus /* Look for transceiver type */
29144977Sraghus 
29154977Sraghus nxge_status_t
29164977Sraghus nxge_xcvr_find(p_nxge_t nxgep)
29174977Sraghus {
29185196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
29195196Ssbehera 	    nxgep->mac.portnum));
29204977Sraghus 
29214977Sraghus 	if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
29224977Sraghus 		return (NXGE_ERROR);
29234977Sraghus 
29244977Sraghus 	if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
29254977Sraghus 		return (NXGE_ERROR);
29264977Sraghus 
29274977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
29284977Sraghus 	    nxgep->statsp->mac_stats.xcvr_inuse));
29294977Sraghus 	return (NXGE_OK);
29304977Sraghus }
29313859Sml29623 
29323859Sml29623 /* Initialize the TxMAC sub-block */
29333859Sml29623 
29343859Sml29623 nxge_status_t
29353859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep)
29363859Sml29623 {
29373859Sml29623 	npi_attr_t		ap;
29383859Sml29623 	uint8_t			portn;
29393859Sml29623 	nxge_port_mode_t	portmode;
29403859Sml29623 	nxge_port_t		portt;
29413859Sml29623 	npi_handle_t		handle;
29423859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
29433859Sml29623 
29443859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
29453859Sml29623 	portt    = nxgep->mac.porttype;
29463859Sml29623 	handle   = nxgep->npi_handle;
29473859Sml29623 	portmode = nxgep->mac.portmode;
29483859Sml29623 
29493859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
29506929Smisaki 	    portn));
29513859Sml29623 	/* Set Max and Min Frame Size */
29526439Sml29623 	/*
29536439Sml29623 	 * Use maxframesize to configure the hardware maxframe size
29546835Syc148097 	 * and minframesize to configure the hardware minframe size.
29556439Sml29623 	 */
29566439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
29576439Sml29623 	    "==> nxge_tx_mac_init: port<%d> "
29586439Sml29623 	    "min framesize %d max framesize %d ",
29596439Sml29623 	    nxgep->mac.minframesize,
29606439Sml29623 	    nxgep->mac.maxframesize,
29616439Sml29623 	    portn));
29626439Sml29623 
29636439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
29646439Sml29623 	    MAC_PORT_FRAME_SIZE,
29656439Sml29623 	    nxgep->mac.minframesize,
29666439Sml29623 	    nxgep->mac.maxframesize,
29676439Sml29623 	    rs);
29683859Sml29623 	if (rs != NPI_SUCCESS)
29693859Sml29623 		goto fail;
29703859Sml29623 
29713859Sml29623 	if (portt == PORT_TYPE_XMAC) {
29723859Sml29623 		if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
29736929Smisaki 		    0)) != NPI_SUCCESS)
29743859Sml29623 			goto fail;
29753859Sml29623 		nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
29763859Sml29623 		if ((portmode == PORT_10G_FIBER) ||
29774977Sraghus 		    (portmode == PORT_10G_COPPER) ||
29786835Syc148097 		    (portmode == PORT_10G_TN1010) ||
29794977Sraghus 		    (portmode == PORT_10G_SERDES)) {
29803859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
29816929Smisaki 			    XGMII_IPG_12_15, rs);
29823859Sml29623 			if (rs != NPI_SUCCESS)
29833859Sml29623 				goto fail;
29843859Sml29623 			nxgep->mac.ipg[0] = XGMII_IPG_12_15;
29853859Sml29623 		} else {
29863859Sml29623 			SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
29876929Smisaki 			    MII_GMII_IPG_12, rs);
29883859Sml29623 			if (rs != NPI_SUCCESS)
29893859Sml29623 				goto fail;
29903859Sml29623 			nxgep->mac.ipg[0] = MII_GMII_IPG_12;
29913859Sml29623 		}
29923859Sml29623 		if ((rs = npi_xmac_tx_config(handle, INIT, portn,
29936929Smisaki 		    CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
29943859Sml29623 			goto fail;
29953859Sml29623 		nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
29963859Sml29623 		nxgep->mac.maxburstsize = 0;	/* not programmable */
29973859Sml29623 		nxgep->mac.ctrltype = 0;	/* not programmable */
29983859Sml29623 		nxgep->mac.pa_size = 0;		/* not programmable */
29993859Sml29623 
30003859Sml29623 		if ((rs = npi_xmac_zap_tx_counters(handle, portn))
30016929Smisaki 		    != NPI_SUCCESS)
30023859Sml29623 			goto fail;
30033859Sml29623 
30043859Sml29623 	} else {
30053859Sml29623 		if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
30066929Smisaki 		    0)) != NPI_SUCCESS)
30073859Sml29623 			goto fail;
30083859Sml29623 		nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
30093859Sml29623 
30103859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
30116929Smisaki 		    rs);
30123859Sml29623 		if (rs != NPI_SUCCESS)
30133859Sml29623 			goto fail;
30143859Sml29623 		nxgep->mac.ctrltype = 0x8808;
30153859Sml29623 
30163859Sml29623 		SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
30173859Sml29623 		if (rs != NPI_SUCCESS)
30183859Sml29623 			goto fail;
30193859Sml29623 		nxgep->mac.pa_size = 0x7;
30203859Sml29623 
30213859Sml29623 		if ((rs = npi_bmac_tx_config(handle, INIT, portn,
30226929Smisaki 		    CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
30233859Sml29623 			goto fail;
30243859Sml29623 		nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
30253859Sml29623 	}
30263859Sml29623 
30273859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
30286929Smisaki 	    portn));
30293859Sml29623 
30303859Sml29623 	return (NXGE_OK);
30313859Sml29623 fail:
30323859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
30336929Smisaki 	    "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
30343859Sml29623 
30353859Sml29623 	return (NXGE_ERROR | rs);
30363859Sml29623 }
30373859Sml29623 
30386495Sspeer 
30393859Sml29623 /* Initialize the RxMAC sub-block */
30403859Sml29623 
30413859Sml29623 nxge_status_t
30423859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep)
30433859Sml29623 {
30443859Sml29623 	npi_attr_t		ap;
30453859Sml29623 	uint32_t		i;
30463859Sml29623 	uint16_t		hashtab_e;
30473859Sml29623 	p_hash_filter_t		hash_filter;
30483859Sml29623 	nxge_port_t		portt;
30493859Sml29623 	uint8_t			portn;
30503859Sml29623 	npi_handle_t		handle;
30513859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
30523859Sml29623 	uint16_t 		*addr16p;
30533859Sml29623 	uint16_t 		addr0, addr1, addr2;
30543859Sml29623 	xmac_rx_config_t	xconfig;
30553859Sml29623 	bmac_rx_config_t	bconfig;
30563859Sml29623 
30573859Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
30583859Sml29623 
30593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
30606929Smisaki 	    portn));
30613859Sml29623 	handle = nxgep->npi_handle;
30623859Sml29623 	portt = nxgep->mac.porttype;
30633859Sml29623 
30643859Sml29623 	addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
30653859Sml29623 	addr0 = ntohs(addr16p[2]);
30663859Sml29623 	addr1 = ntohs(addr16p[1]);
30673859Sml29623 	addr2 = ntohs(addr16p[0]);
30683859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2,
30696929Smisaki 	    rs);
30703859Sml29623 
30713859Sml29623 	if (rs != NPI_SUCCESS)
30723859Sml29623 		goto fail;
30733859Sml29623 	SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
30743859Sml29623 	if (rs != NPI_SUCCESS)
30753859Sml29623 		goto fail;
30763859Sml29623 	SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
30773859Sml29623 	if (rs != NPI_SUCCESS)
30783859Sml29623 		goto fail;
30793859Sml29623 
30803859Sml29623 	/*
30813859Sml29623 	 * Load the multicast hash filter bits.
30823859Sml29623 	 */
30833859Sml29623 	hash_filter = nxgep->hash_filter;
30843859Sml29623 	for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
30853859Sml29623 		if (hash_filter != NULL) {
30863859Sml29623 			hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
30876929Smisaki 			    (NMCFILTER_REGS - 1) - i];
30883859Sml29623 		} else {
30893859Sml29623 			hashtab_e = 0;
30903859Sml29623 		}
30913859Sml29623 
30923859Sml29623 		if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
30936929Smisaki 		    (uint16_t *)&hashtab_e)) != NPI_SUCCESS)
30943859Sml29623 			goto fail;
30953859Sml29623 	}
30963859Sml29623 
30973859Sml29623 	if (portt == PORT_TYPE_XMAC) {
30983859Sml29623 		if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
30996929Smisaki 		    0)) != NPI_SUCCESS)
31003859Sml29623 			goto fail;
31013859Sml29623 		nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
31023859Sml29623 
31033859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
31043859Sml29623 
31053859Sml29623 		xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
31066929Smisaki 		    CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
31076929Smisaki 		    ~CFG_XMAC_RX_STRIP_CRC;
31083859Sml29623 
31093859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
31103859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUS;
31113859Sml29623 
31123859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
31133859Sml29623 			xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
31143859Sml29623 
31153859Sml29623 		xconfig |= CFG_XMAC_RX_HASH_FILTER;
31163859Sml29623 
31173859Sml29623 		if ((rs = npi_xmac_rx_config(handle, INIT, portn,
31186929Smisaki 		    xconfig)) != NPI_SUCCESS)
31193859Sml29623 			goto fail;
31203859Sml29623 		nxgep->mac.rx_config = xconfig;
31213859Sml29623 
31223859Sml29623 		/* Comparison of mac unique address is always enabled on XMAC */
31233859Sml29623 
31243859Sml29623 		if ((rs = npi_xmac_zap_rx_counters(handle, portn))
31256929Smisaki 		    != NPI_SUCCESS)
31263859Sml29623 			goto fail;
31273859Sml29623 	} else {
31283859Sml29623 		(void) nxge_fflp_init_hostinfo(nxgep);
31293859Sml29623 
31303859Sml29623 		if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
31316929Smisaki 		    0) != NPI_SUCCESS)
31323859Sml29623 			goto fail;
31333859Sml29623 		nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
31343859Sml29623 
31353859Sml29623 		bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
31366929Smisaki 		    ~CFG_BMAC_RX_STRIP_CRC;
31373859Sml29623 
31383859Sml29623 		if (nxgep->filter.all_phys_cnt != 0)
31393859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUS;
31403859Sml29623 
31413859Sml29623 		if (nxgep->filter.all_multicast_cnt != 0)
31423859Sml29623 			bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
31433859Sml29623 
31443859Sml29623 		bconfig |= CFG_BMAC_RX_HASH_FILTER;
31453859Sml29623 		if ((rs = npi_bmac_rx_config(handle, INIT, portn,
31466929Smisaki 		    bconfig)) != NPI_SUCCESS)
31473859Sml29623 			goto fail;
31483859Sml29623 		nxgep->mac.rx_config = bconfig;
31493859Sml29623 
31503859Sml29623 		/* Always enable comparison of mac unique address */
31513859Sml29623 		if ((rs = npi_mac_altaddr_enable(handle, portn, 0))
31526929Smisaki 		    != NPI_SUCCESS)
31533859Sml29623 			goto fail;
31543859Sml29623 	}
31553859Sml29623 
31563859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
31576929Smisaki 	    portn));
31583859Sml29623 
31593859Sml29623 	return (NXGE_OK);
31603859Sml29623 
31613859Sml29623 fail:
31623859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
31636929Smisaki 	    "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
31643859Sml29623 
31653859Sml29623 	return (NXGE_ERROR | rs);
31663859Sml29623 }
31673859Sml29623 
31683859Sml29623 /* Enable TXMAC */
31693859Sml29623 
31703859Sml29623 nxge_status_t
31713859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep)
31723859Sml29623 {
31733859Sml29623 	npi_handle_t	handle;
31743859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
31753859Sml29623 	nxge_status_t	status = NXGE_OK;
31763859Sml29623 
31773859Sml29623 	handle = nxgep->npi_handle;
31783859Sml29623 
31793859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
31806929Smisaki 	    nxgep->mac.portnum));
31813859Sml29623 
31823859Sml29623 	if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
31833859Sml29623 		goto fail;
31843859Sml29623 
31853859Sml29623 	/* based on speed */
31863859Sml29623 	nxgep->msg_min = ETHERMIN;
31873859Sml29623 
31883859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
31893859Sml29623 		if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
31906929Smisaki 		    CFG_XMAC_TX)) != NPI_SUCCESS)
31913859Sml29623 			goto fail;
31923859Sml29623 	} else {
31933859Sml29623 		if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
31946929Smisaki 		    CFG_BMAC_TX)) != NPI_SUCCESS)
31953859Sml29623 			goto fail;
31963859Sml29623 	}
31973859Sml29623 
31983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
31996929Smisaki 	    nxgep->mac.portnum));
32003859Sml29623 
32013859Sml29623 	return (NXGE_OK);
32023859Sml29623 fail:
32033859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32046929Smisaki 	    "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
32056929Smisaki 	    nxgep->mac.portnum));
32063859Sml29623 	if (rs != NPI_SUCCESS)
32073859Sml29623 		return (NXGE_ERROR | rs);
32083859Sml29623 	else
32093859Sml29623 		return (status);
32103859Sml29623 }
32113859Sml29623 
32123859Sml29623 /* Disable TXMAC */
32133859Sml29623 
32143859Sml29623 nxge_status_t
32153859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep)
32163859Sml29623 {
32173859Sml29623 	npi_handle_t	handle;
32183859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
32193859Sml29623 
32206495Sspeer 	if (isLDOMguest(nxgep))
32216495Sspeer 		return (NXGE_OK);
32226495Sspeer 
32233859Sml29623 	handle = nxgep->npi_handle;
32243859Sml29623 
32253859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
32266929Smisaki 	    nxgep->mac.portnum));
32273859Sml29623 
32283859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
32293859Sml29623 		if ((rs = npi_xmac_tx_config(handle, DISABLE,
32306929Smisaki 		    nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
32313859Sml29623 			goto fail;
32323859Sml29623 	} else {
32333859Sml29623 		if ((rs = npi_bmac_tx_config(handle, DISABLE,
32346929Smisaki 		    nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
32353859Sml29623 			goto fail;
32363859Sml29623 	}
32373859Sml29623 
32383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
32396929Smisaki 	    nxgep->mac.portnum));
32403859Sml29623 	return (NXGE_OK);
32413859Sml29623 fail:
32423859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32436929Smisaki 	    "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
32446929Smisaki 	    nxgep->mac.portnum));
32453859Sml29623 	return (NXGE_ERROR | rs);
32463859Sml29623 }
32473859Sml29623 
32483859Sml29623 /* Enable RXMAC */
32493859Sml29623 
32503859Sml29623 nxge_status_t
32513859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep)
32523859Sml29623 {
32533859Sml29623 	npi_handle_t	handle;
32543859Sml29623 	uint8_t 	portn;
32553859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
32563859Sml29623 	nxge_status_t	status = NXGE_OK;
32573859Sml29623 
32586495Sspeer 	/* This is a service-domain-only activity. */
32596495Sspeer 	if (isLDOMguest(nxgep))
32606495Sspeer 		return (status);
32616495Sspeer 
32623859Sml29623 	handle = nxgep->npi_handle;
32633859Sml29623 	portn = nxgep->mac.portnum;
32643859Sml29623 
32653859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
32666929Smisaki 	    portn));
32673859Sml29623 
32683859Sml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
32693859Sml29623 		goto fail;
32703859Sml29623 
32713859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
32723859Sml29623 		if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
32736495Sspeer 		    CFG_XMAC_RX)) != NPI_SUCCESS)
32743859Sml29623 			goto fail;
32753859Sml29623 	} else {
32763859Sml29623 		if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
32776495Sspeer 		    CFG_BMAC_RX)) != NPI_SUCCESS)
32783859Sml29623 			goto fail;
32793859Sml29623 	}
32803859Sml29623 
32816495Sspeer 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
32826495Sspeer 	    "<== nxge_rx_mac_enable: port<%d>", portn));
32833859Sml29623 
32843859Sml29623 	return (NXGE_OK);
32853859Sml29623 fail:
32863859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
32876495Sspeer 	    "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
32883859Sml29623 
32893859Sml29623 	if (rs != NPI_SUCCESS)
32903859Sml29623 		return (NXGE_ERROR | rs);
32913859Sml29623 	else
32923859Sml29623 		return (status);
32933859Sml29623 }
32943859Sml29623 
32953859Sml29623 /* Disable RXMAC */
32963859Sml29623 
32973859Sml29623 nxge_status_t
32983859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep)
32993859Sml29623 {
33003859Sml29623 	npi_handle_t	handle;
33013859Sml29623 	uint8_t		portn;
33023859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
33033859Sml29623 
33046495Sspeer 	/* If we are a guest domain driver, don't bother. */
33056495Sspeer 	if (isLDOMguest(nxgep))
33066495Sspeer 		return (NXGE_OK);
33076495Sspeer 
33083859Sml29623 	handle = nxgep->npi_handle;
33093859Sml29623 	portn = nxgep->mac.portnum;
33103859Sml29623 
33113859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
33126929Smisaki 	    portn));
33133859Sml29623 
33143859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
33153859Sml29623 		if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
33166929Smisaki 		    CFG_XMAC_RX)) != NPI_SUCCESS)
33173859Sml29623 			goto fail;
33183859Sml29623 	} else {
33193859Sml29623 		if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
33206929Smisaki 		    CFG_BMAC_RX)) != NPI_SUCCESS)
33213859Sml29623 			goto fail;
33223859Sml29623 	}
33233859Sml29623 
33243859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
33256929Smisaki 	    portn));
33263859Sml29623 	return (NXGE_OK);
33273859Sml29623 fail:
33283859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33296929Smisaki 	    "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
33303859Sml29623 
33313859Sml29623 	return (NXGE_ERROR | rs);
33323859Sml29623 }
33333859Sml29623 
33343859Sml29623 /* Reset TXMAC */
33353859Sml29623 
33363859Sml29623 nxge_status_t
33373859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep)
33383859Sml29623 {
33393859Sml29623 	npi_handle_t	handle;
33403859Sml29623 	uint8_t		portn;
33413859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
33423859Sml29623 
33433859Sml29623 	handle = nxgep->npi_handle;
33443859Sml29623 	portn = nxgep->mac.portnum;
33453859Sml29623 
33463859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
33476929Smisaki 	    portn));
33483859Sml29623 
33493859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
33503859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
33513859Sml29623 		    != NPI_SUCCESS)
33523859Sml29623 			goto fail;
33533859Sml29623 	} else {
33543859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
33556929Smisaki 		    != NPI_SUCCESS)
33563859Sml29623 			goto fail;
33573859Sml29623 	}
33583859Sml29623 
33593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
33606929Smisaki 	    portn));
33613859Sml29623 
33623859Sml29623 	return (NXGE_OK);
33633859Sml29623 fail:
33643859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
33656929Smisaki 	    "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
33663859Sml29623 
33673859Sml29623 	return (NXGE_ERROR | rs);
33683859Sml29623 }
33693859Sml29623 
33703859Sml29623 /* Reset RXMAC */
33713859Sml29623 
33723859Sml29623 nxge_status_t
33733859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep)
33743859Sml29623 {
33753859Sml29623 	npi_handle_t	handle;
33763859Sml29623 	uint8_t		portn;
33773859Sml29623 	npi_status_t	rs = NPI_SUCCESS;
33783859Sml29623 
33793859Sml29623 	handle = nxgep->npi_handle;
33803859Sml29623 	portn = nxgep->mac.portnum;
33813859Sml29623 
33823859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
33836929Smisaki 	    portn));
33843859Sml29623 
33853859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
33863859Sml29623 		if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
33873859Sml29623 		    != NPI_SUCCESS)
33883859Sml29623 		goto fail;
33893859Sml29623 	} else {
33903859Sml29623 		if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
33916929Smisaki 		    != NPI_SUCCESS)
33923859Sml29623 		goto fail;
33933859Sml29623 	}
33943859Sml29623 
33953859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
33966929Smisaki 	    portn));
33973859Sml29623 
33983859Sml29623 	return (NXGE_OK);
33993859Sml29623 fail:
34003859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
34016929Smisaki 	    "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
34023859Sml29623 	return (NXGE_ERROR | rs);
34033859Sml29623 }
34043859Sml29623 
34054732Sdavemq /* 10G fiber link interrupt start routine */
34064732Sdavemq 
34074732Sdavemq static nxge_status_t
34084732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep)
34094732Sdavemq {
34104732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34114732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34124732Sdavemq 
34134732Sdavemq 	rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
34144732Sdavemq 
34154732Sdavemq 	if (rs != NPI_SUCCESS)
34164732Sdavemq 		return (NXGE_ERROR | rs);
34174732Sdavemq 	else
34184732Sdavemq 		return (NXGE_OK);
34194732Sdavemq }
34204732Sdavemq 
34214732Sdavemq /* 10G fiber link interrupt stop routine */
34224732Sdavemq 
34234732Sdavemq static nxge_status_t
34244732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep)
34254732Sdavemq {
34264732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34274732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34284732Sdavemq 
34294732Sdavemq 	rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
34304732Sdavemq 
34314732Sdavemq 	if (rs != NPI_SUCCESS)
34324732Sdavemq 		return (NXGE_ERROR | rs);
34334732Sdavemq 	else
34344732Sdavemq 		return (NXGE_OK);
34354732Sdavemq }
34364732Sdavemq 
34374732Sdavemq /* 1G fiber link interrupt start routine */
34384732Sdavemq 
34394732Sdavemq static nxge_status_t
34404732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
34414732Sdavemq {
34424732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34434732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34444732Sdavemq 
34454732Sdavemq 	rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
34464732Sdavemq 	if (rs != NPI_SUCCESS)
34474732Sdavemq 		return (NXGE_ERROR | rs);
34484732Sdavemq 	else
34494732Sdavemq 		return (NXGE_OK);
34504732Sdavemq }
34514732Sdavemq 
34524732Sdavemq /* 1G fiber link interrupt stop routine */
34534732Sdavemq 
34544732Sdavemq static nxge_status_t
34554732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
34564732Sdavemq {
34574732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34584732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34594732Sdavemq 
34604732Sdavemq 	rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
34614732Sdavemq 
34624732Sdavemq 	if (rs != NPI_SUCCESS)
34634732Sdavemq 		return (NXGE_ERROR | rs);
34644732Sdavemq 	else
34654732Sdavemq 		return (NXGE_OK);
34664732Sdavemq }
34674732Sdavemq 
34684732Sdavemq /* 1G copper link interrupt start routine */
34694732Sdavemq 
34704732Sdavemq static nxge_status_t
34714732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
34724732Sdavemq {
34734732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34744732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34754732Sdavemq 
34764732Sdavemq 	rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
34775203Ssbehera 	    MII_STATUS, MII_STATUS_LINKUP);
34784732Sdavemq 
34794732Sdavemq 	if (rs != NPI_SUCCESS)
34804732Sdavemq 		return (NXGE_ERROR | rs);
34814732Sdavemq 	else
34824732Sdavemq 		return (NXGE_OK);
34834732Sdavemq }
34844732Sdavemq 
34854732Sdavemq /* 1G copper link interrupt stop routine */
34864732Sdavemq 
34874732Sdavemq static nxge_status_t
34884732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
34894732Sdavemq {
34904732Sdavemq 	npi_status_t	rs = NPI_SUCCESS;
34914732Sdavemq 	uint8_t		portn = nxgep->mac.portnum;
34924732Sdavemq 
34934732Sdavemq 	rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
34944732Sdavemq 
34954732Sdavemq 	if (rs != NPI_SUCCESS)
34964732Sdavemq 		return (NXGE_ERROR | rs);
34974732Sdavemq 	else
34984732Sdavemq 		return (NXGE_OK);
34994732Sdavemq }
35004732Sdavemq 
35014732Sdavemq /* Enable/Disable Link Status change interrupt */
35023859Sml29623 
35033859Sml29623 nxge_status_t
35043859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
35053859Sml29623 {
35064732Sdavemq 	uint8_t		portn;
35074732Sdavemq 	nxge_status_t	status = NXGE_OK;
35083859Sml29623 
35093859Sml29623 	portn = nxgep->mac.portnum;
35103859Sml29623 
35113859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
35124732Sdavemq 	if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
35134732Sdavemq 		return (NXGE_OK);
35144732Sdavemq 
35154732Sdavemq 	if (enable == LINK_INTR_START)
35164732Sdavemq 		status = nxgep->xcvr.link_intr_start(nxgep);
35174732Sdavemq 	else if (enable == LINK_INTR_STOP)
35184732Sdavemq 		status = nxgep->xcvr.link_intr_stop(nxgep);
35194732Sdavemq 	if (status != NXGE_OK)
35204732Sdavemq 		goto fail;
35213859Sml29623 
35223859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
35233859Sml29623 
35243859Sml29623 	return (NXGE_OK);
35253859Sml29623 fail:
35263859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
35276929Smisaki 	    "nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
35283859Sml29623 
35294732Sdavemq 	return (status);
35303859Sml29623 }
35313859Sml29623 
35323859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */
35333859Sml29623 
35343859Sml29623 nxge_status_t
35353859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep)
35363859Sml29623 {
35373859Sml29623 	p_nxge_param_t	param_arr;
35383859Sml29623 	p_nxge_stats_t	statsp;
35393859Sml29623 	uint8_t		xcvr_portn;
35403859Sml29623 	p_mii_regs_t	mii_regs;
35413859Sml29623 	mii_bmcr_t	bmcr;
35423859Sml29623 	mii_bmsr_t	bmsr;
35433859Sml29623 	mii_anar_t	anar;
35443859Sml29623 	mii_gcr_t	gcr;
35453859Sml29623 	mii_esr_t	esr;
35463859Sml29623 	mii_aux_ctl_t	bcm5464r_aux;
35473859Sml29623 	int		status = NXGE_OK;
35483859Sml29623 
35493859Sml29623 	uint_t delay;
35503859Sml29623 
35513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
35523859Sml29623 
35533859Sml29623 	param_arr = nxgep->param_arr;
35543859Sml29623 	statsp = nxgep->statsp;
35553859Sml29623 	xcvr_portn = statsp->mac_stats.xcvr_portn;
35563859Sml29623 
35573859Sml29623 	mii_regs = NULL;
35583859Sml29623 
35593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
35606929Smisaki 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
35613859Sml29623 
35623859Sml29623 	/*
35635196Ssbehera 	 * The mif phy mode may be connected to either a copper link
35645196Ssbehera 	 * or fiber link. Read the mode control register to get the fiber
35655196Ssbehera 	 * configuration if it is hard-wired to fiber link.
35665196Ssbehera 	 */
35675196Ssbehera 	(void) nxge_mii_get_link_mode(nxgep);
35685196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
35695196Ssbehera 		return (nxge_mii_xcvr_fiber_init(nxgep));
35705196Ssbehera 	}
35715196Ssbehera 
35725196Ssbehera 	/*
35733859Sml29623 	 * Reset the transceiver.
35743859Sml29623 	 */
35753859Sml29623 	delay = 0;
35763859Sml29623 	bmcr.value = 0;
35773859Sml29623 	bmcr.bits.reset = 1;
35783859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
35795125Sjoycey #if defined(__i386)
35806929Smisaki 	    (uint8_t)(uint32_t)&mii_regs->bmcr,
35815125Sjoycey #else
35826929Smisaki 	    (uint8_t)(uint64_t)&mii_regs->bmcr,
35835125Sjoycey #endif
35846929Smisaki 	    bmcr.value)) != NXGE_OK)
35853859Sml29623 		goto fail;
35863859Sml29623 	do {
35873859Sml29623 		drv_usecwait(500);
35883859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
35895125Sjoycey #if defined(__i386)
35906929Smisaki 		    (uint8_t)(uint32_t)&mii_regs->bmcr,
35915125Sjoycey #else
35926929Smisaki 		    (uint8_t)(uint64_t)&mii_regs->bmcr,
35935125Sjoycey #endif
35946929Smisaki 		    &bmcr.value)) != NXGE_OK)
35953859Sml29623 			goto fail;
35963859Sml29623 		delay++;
35973859Sml29623 	} while ((bmcr.bits.reset) && (delay < 1000));
35983859Sml29623 	if (delay == 1000) {
35993859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
36003859Sml29623 		goto fail;
36013859Sml29623 	}
36023859Sml29623 
36033859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
36045125Sjoycey #if defined(__i386)
36056929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
36065125Sjoycey #else
36076929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
36085125Sjoycey #endif
36096929Smisaki 	    &bmsr.value)) != NXGE_OK)
36103859Sml29623 		goto fail;
36113859Sml29623 
36123859Sml29623 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
36133859Sml29623 	param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
36143859Sml29623 	param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
36153859Sml29623 	param_arr[param_anar_100hdx].value = 0;
36163859Sml29623 	param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
36173859Sml29623 	param_arr[param_anar_10hdx].value = 0;
36183859Sml29623 
36193859Sml29623 	/*
36203859Sml29623 	 * Initialize the xcvr statistics.
36213859Sml29623 	 */
36223859Sml29623 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
36233859Sml29623 	statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
36243859Sml29623 	statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
36253859Sml29623 	statsp->mac_stats.cap_100hdx = 0;
36263859Sml29623 	statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
36273859Sml29623 	statsp->mac_stats.cap_10hdx = 0;
36283859Sml29623 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
36293859Sml29623 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
36303859Sml29623 
36313859Sml29623 	/*
36326835Syc148097 	 * Initialize the xcvr advertised capability statistics.
36333859Sml29623 	 */
36343859Sml29623 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
36353859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
36363859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
36373859Sml29623 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
36383859Sml29623 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
36393859Sml29623 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
36403859Sml29623 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
36413859Sml29623 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
36423859Sml29623 	statsp->mac_stats.adv_cap_asmpause =
36436929Smisaki 	    param_arr[param_anar_asmpause].value;
36443859Sml29623 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
36453859Sml29623 
36463859Sml29623 
36473859Sml29623 	/*
36483859Sml29623 	 * Check for extended status just in case we're
36493859Sml29623 	 * running a Gigibit phy.
36503859Sml29623 	 */
36513859Sml29623 	if (bmsr.bits.extend_status) {
36523859Sml29623 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
36535125Sjoycey #if defined(__i386)
36546929Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->esr),
36555125Sjoycey #else
36566929Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->esr),
36575125Sjoycey #endif
36586929Smisaki 		    &esr.value)) != NXGE_OK)
36593859Sml29623 			goto fail;
36606929Smisaki 		param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
36613859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
36623859Sml29623 
36633859Sml29623 		statsp->mac_stats.cap_1000fdx =
36646929Smisaki 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
36653859Sml29623 		statsp->mac_stats.cap_1000hdx = 0;
36663859Sml29623 	} else {
36673859Sml29623 		param_arr[param_anar_1000fdx].value = 0;
36683859Sml29623 		param_arr[param_anar_1000hdx].value = 0;
36693859Sml29623 	}
36703859Sml29623 
36713859Sml29623 	/*
36723859Sml29623 	 * Initialize 1G Statistics once the capability is established.
36733859Sml29623 	 */
36743859Sml29623 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
36753859Sml29623 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
36763859Sml29623 
36773859Sml29623 	/*
36786835Syc148097 	 * Initialize the link statistics.
36793859Sml29623 	 */
36803859Sml29623 	statsp->mac_stats.link_T4 = 0;
36813859Sml29623 	statsp->mac_stats.link_asmpause = 0;
36823859Sml29623 	statsp->mac_stats.link_pause = 0;
36833859Sml29623 	statsp->mac_stats.link_speed = 0;
36843859Sml29623 	statsp->mac_stats.link_duplex = 0;
36853859Sml29623 	statsp->mac_stats.link_up = 0;
36863859Sml29623 
36873859Sml29623 	/*
36883859Sml29623 	 * Switch off Auto-negotiation, 100M and full duplex.
36893859Sml29623 	 */
36903859Sml29623 	bmcr.value = 0;
36913859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
36925125Sjoycey #if defined(__i386)
36936929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
36945125Sjoycey #else
36956929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
36965125Sjoycey #endif
36976929Smisaki 	    bmcr.value)) != NXGE_OK)
36983859Sml29623 		goto fail;
36993859Sml29623 
37003859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
37016929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
37023859Sml29623 		bmcr.bits.loopback = 1;
37033859Sml29623 		bmcr.bits.enable_autoneg = 0;
37043859Sml29623 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
37053859Sml29623 			bmcr.bits.speed_1000_sel = 1;
37063859Sml29623 		bmcr.bits.duplex_mode = 1;
37073859Sml29623 		param_arr[param_autoneg].value = 0;
37083859Sml29623 	} else {
37093859Sml29623 		bmcr.bits.loopback = 0;
37103859Sml29623 	}
37113859Sml29623 
37123859Sml29623 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
37136929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
37146929Smisaki 	    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
37153859Sml29623 		param_arr[param_autoneg].value = 0;
37163859Sml29623 		bcm5464r_aux.value = 0;
37173859Sml29623 		bcm5464r_aux.bits.ext_lb = 1;
37183859Sml29623 		bcm5464r_aux.bits.write_1 = 1;
37193859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
37206929Smisaki 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
37213859Sml29623 			goto fail;
37223859Sml29623 	}
37233859Sml29623 
37246835Syc148097 	/* If auto-negotiation is desired */
37253859Sml29623 	if (param_arr[param_autoneg].value) {
37263859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
37276929Smisaki 		    "Restarting Auto-negotiation."));
37283859Sml29623 		/*
37293859Sml29623 		 * Setup our Auto-negotiation advertisement register.
37303859Sml29623 		 */
37313859Sml29623 		anar.value = 0;
37323859Sml29623 		anar.bits.selector = 1;
37333859Sml29623 		anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
37343859Sml29623 		anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
37353859Sml29623 		anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
37363859Sml29623 		anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
37373859Sml29623 		anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
37383859Sml29623 		anar.bits.cap_asmpause = 0;
37393859Sml29623 		anar.bits.cap_pause = 0;
37403859Sml29623 		if (param_arr[param_anar_1000fdx].value ||
37416929Smisaki 		    param_arr[param_anar_100fdx].value ||
37426929Smisaki 		    param_arr[param_anar_10fdx].value) {
37433859Sml29623 			anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
37443859Sml29623 			anar.bits.cap_pause = statsp->mac_stats.cap_pause;
37453859Sml29623 		}
37463859Sml29623 
37476835Syc148097 		/* Write to the auto-negotiation advertisement register */
37483859Sml29623 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
37495125Sjoycey #if defined(__i386)
37506929Smisaki 		    (uint8_t)(uint32_t)(&mii_regs->anar),
37515125Sjoycey #else
37526929Smisaki 		    (uint8_t)(uint64_t)(&mii_regs->anar),
37535125Sjoycey #endif
37546929Smisaki 		    anar.value)) != NXGE_OK)
37553859Sml29623 			goto fail;
37563859Sml29623 		if (bmsr.bits.extend_status) {
37573859Sml29623 			gcr.value = 0;
37583859Sml29623 			gcr.bits.ms_mode_en =
37596929Smisaki 			    param_arr[param_master_cfg_enable].value;
37603859Sml29623 			gcr.bits.master =
37616929Smisaki 			    param_arr[param_master_cfg_value].value;
37623859Sml29623 			gcr.bits.link_1000fdx =
37636929Smisaki 			    param_arr[param_anar_1000fdx].value;
37643859Sml29623 			gcr.bits.link_1000hdx =
37656929Smisaki 			    param_arr[param_anar_1000hdx].value;
37663859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
37675125Sjoycey #if defined(__i386)
37686929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
37695125Sjoycey #else
37706929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
37715125Sjoycey #endif
37726929Smisaki 			    gcr.value)) != NXGE_OK)
37733859Sml29623 				goto fail;
37743859Sml29623 		}
37753859Sml29623 
37763859Sml29623 		bmcr.bits.enable_autoneg = 1;
37773859Sml29623 		bmcr.bits.restart_autoneg = 1;
37783859Sml29623 
37793859Sml29623 	} else {
37803859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
37813859Sml29623 		bmcr.bits.speed_1000_sel =
37826929Smisaki 		    param_arr[param_anar_1000fdx].value |
37836929Smisaki 		    param_arr[param_anar_1000hdx].value;
37843859Sml29623 		bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
37856929Smisaki 		    (param_arr[param_anar_100fdx].value |
37866929Smisaki 		    param_arr[param_anar_100hdx].value);
37876835Syc148097 
37886835Syc148097 		/* Force to 1G */
37893859Sml29623 		if (bmcr.bits.speed_1000_sel) {
37903859Sml29623 			statsp->mac_stats.link_speed = 1000;
37913859Sml29623 			gcr.value = 0;
37923859Sml29623 			gcr.bits.ms_mode_en =
37936929Smisaki 			    param_arr[param_master_cfg_enable].value;
37943859Sml29623 			gcr.bits.master =
37956929Smisaki 			    param_arr[param_master_cfg_value].value;
37963859Sml29623 			if ((status = nxge_mii_write(nxgep, xcvr_portn,
37975125Sjoycey #if defined(__i386)
37986929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gcr),
37995125Sjoycey #else
38006929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gcr),
38015125Sjoycey #endif
38026929Smisaki 			    gcr.value)) != NXGE_OK)
38033859Sml29623 				goto fail;
38043859Sml29623 			if (param_arr[param_anar_1000fdx].value) {
38053859Sml29623 				bmcr.bits.duplex_mode = 1;
38063859Sml29623 				statsp->mac_stats.link_duplex = 2;
38073859Sml29623 			} else
38083859Sml29623 				statsp->mac_stats.link_duplex = 1;
38096835Syc148097 
38106835Syc148097 		/* Force to 100M */
38113859Sml29623 		} else if (bmcr.bits.speed_sel) {
38123859Sml29623 			statsp->mac_stats.link_speed = 100;
38133859Sml29623 			if (param_arr[param_anar_100fdx].value) {
38143859Sml29623 				bmcr.bits.duplex_mode = 1;
38153859Sml29623 				statsp->mac_stats.link_duplex = 2;
38163859Sml29623 			} else
38173859Sml29623 				statsp->mac_stats.link_duplex = 1;
38186835Syc148097 
38196835Syc148097 		/* Force to 10M */
38203859Sml29623 		} else {
38213859Sml29623 			statsp->mac_stats.link_speed = 10;
38223859Sml29623 			if (param_arr[param_anar_10fdx].value) {
38233859Sml29623 				bmcr.bits.duplex_mode = 1;
38243859Sml29623 				statsp->mac_stats.link_duplex = 2;
38253859Sml29623 			} else
38263859Sml29623 				statsp->mac_stats.link_duplex = 1;
38273859Sml29623 		}
38283859Sml29623 		if (statsp->mac_stats.link_duplex != 1) {
38293859Sml29623 			statsp->mac_stats.link_asmpause =
38306929Smisaki 			    statsp->mac_stats.cap_asmpause;
38313859Sml29623 			statsp->mac_stats.link_pause =
38326929Smisaki 			    statsp->mac_stats.cap_pause;
38333859Sml29623 		}
38343859Sml29623 
38353859Sml29623 		if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
38366929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext100) ||
38376929Smisaki 		    (statsp->port_stats.lb_mode == nxge_lb_ext10)) {
38383859Sml29623 			if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
38393859Sml29623 				/* BCM5464R 1000mbps external loopback mode */
38403859Sml29623 				gcr.value = 0;
38413859Sml29623 				gcr.bits.ms_mode_en = 1;
38423859Sml29623 				gcr.bits.master = 1;
38433859Sml29623 				if ((status = nxge_mii_write(nxgep, xcvr_portn,
38445125Sjoycey #if defined(__i386)
38456929Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gcr),
38465125Sjoycey #else
38476929Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gcr),
38485125Sjoycey #endif
38496929Smisaki 				    gcr.value)) != NXGE_OK)
38503859Sml29623 					goto fail;
38513859Sml29623 				bmcr.value = 0;
38523859Sml29623 				bmcr.bits.speed_1000_sel = 1;
38533859Sml29623 				statsp->mac_stats.link_speed = 1000;
38543859Sml29623 			} else if (statsp->port_stats.lb_mode
38553859Sml29623 			    == nxge_lb_ext100) {
38563859Sml29623 				/* BCM5464R 100mbps external loopback mode */
38573859Sml29623 				bmcr.value = 0;
38583859Sml29623 				bmcr.bits.speed_sel = 1;
38593859Sml29623 				bmcr.bits.duplex_mode = 1;
38603859Sml29623 				statsp->mac_stats.link_speed = 100;
38613859Sml29623 			} else if (statsp->port_stats.lb_mode
38623859Sml29623 			    == nxge_lb_ext10) {
38633859Sml29623 				/* BCM5464R 10mbps external loopback mode */
38643859Sml29623 				bmcr.value = 0;
38653859Sml29623 				bmcr.bits.duplex_mode = 1;
38663859Sml29623 				statsp->mac_stats.link_speed = 10;
38673859Sml29623 			}
38683859Sml29623 		}
38693859Sml29623 	}
38703859Sml29623 
38713859Sml29623 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
38725125Sjoycey #if defined(__i386)
38736929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
38745125Sjoycey #else
38756929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
38765125Sjoycey #endif
38776929Smisaki 	    bmcr.value)) != NXGE_OK)
38783859Sml29623 		goto fail;
38793859Sml29623 
38803859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
38815125Sjoycey #if defined(__i386)
38826929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
38835125Sjoycey #else
38846929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
38855125Sjoycey #endif
38866929Smisaki 	    &bmcr.value)) != NXGE_OK)
38873859Sml29623 		goto fail;
38883859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
38893859Sml29623 
38903859Sml29623 	/*
38913859Sml29623 	 * Initialize the xcvr status kept in the context structure.
38923859Sml29623 	 */
38933859Sml29623 	nxgep->soft_bmsr.value = 0;
38943859Sml29623 
38953859Sml29623 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
38965125Sjoycey #if defined(__i386)
38976929Smisaki 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
38985125Sjoycey #else
38996929Smisaki 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
39005125Sjoycey #endif
39016929Smisaki 	    &nxgep->bmsr.value)) != NXGE_OK)
39023859Sml29623 		goto fail;
39033859Sml29623 
39043859Sml29623 	statsp->mac_stats.xcvr_inits++;
39053859Sml29623 	nxgep->bmsr.value = 0;
39063859Sml29623 
39073859Sml29623 fail:
39083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39096929Smisaki 	    "<== nxge_mii_xcvr_init status 0x%x", status));
39103859Sml29623 	return (status);
39113859Sml29623 }
39123859Sml29623 
39135196Ssbehera nxge_status_t
39145196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
39155196Ssbehera {
39165196Ssbehera 	p_nxge_param_t	param_arr;
39175196Ssbehera 	p_nxge_stats_t	statsp;
39185196Ssbehera 	uint8_t		xcvr_portn;
39195196Ssbehera 	p_mii_regs_t	mii_regs;
39205196Ssbehera 	mii_bmcr_t	bmcr;
39215196Ssbehera 	mii_bmsr_t	bmsr;
39225196Ssbehera 	mii_gcr_t	gcr;
39235196Ssbehera 	mii_esr_t	esr;
39245196Ssbehera 	mii_aux_ctl_t	bcm5464r_aux;
39255196Ssbehera 	int		status = NXGE_OK;
39265196Ssbehera 
39275196Ssbehera 	uint_t delay;
39285196Ssbehera 
39295196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
39305196Ssbehera 
39315196Ssbehera 	param_arr = nxgep->param_arr;
39325196Ssbehera 	statsp = nxgep->statsp;
39335196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
39345196Ssbehera 
39355196Ssbehera 	mii_regs = NULL;
39365196Ssbehera 
39375196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
39385196Ssbehera 	    "nxge_mii_xcvr_fiber_init: "
39395196Ssbehera 	    "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
39405196Ssbehera 
39415196Ssbehera 	/*
39425196Ssbehera 	 * Reset the transceiver.
39435196Ssbehera 	 */
39445196Ssbehera 	delay = 0;
39455196Ssbehera 	bmcr.value = 0;
39465196Ssbehera 	bmcr.bits.reset = 1;
39475196Ssbehera 
39485196Ssbehera #if defined(__i386)
39495196Ssbehera 
39505196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
39515196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
39525196Ssbehera 		goto fail;
39535196Ssbehera #else
39545196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
39555196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
39565196Ssbehera 		goto fail;
39575196Ssbehera #endif
39585196Ssbehera 	do {
39595196Ssbehera 		drv_usecwait(500);
39605196Ssbehera #if defined(__i386)
39615196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
39625196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value))
39635196Ssbehera 		    != NXGE_OK)
39645196Ssbehera 			goto fail;
39655196Ssbehera #else
39665196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
39675196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
39685196Ssbehera 		    != NXGE_OK)
39695196Ssbehera 			goto fail;
39705196Ssbehera #endif
39715196Ssbehera 		delay++;
39725196Ssbehera 	} while ((bmcr.bits.reset) && (delay < 1000));
39735196Ssbehera 	if (delay == 1000) {
39745196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
39755196Ssbehera 		goto fail;
39765196Ssbehera 	}
39775196Ssbehera 
39785196Ssbehera #if defined(__i386)
39795196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39805196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
39815196Ssbehera 		goto fail;
39825196Ssbehera #else
39835196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
39845196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
39855196Ssbehera 		goto fail;
39865196Ssbehera #endif
39875196Ssbehera 
39885196Ssbehera 	param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
39895196Ssbehera 	param_arr[param_anar_100T4].value = 0;
39905196Ssbehera 	param_arr[param_anar_100fdx].value = 0;
39915196Ssbehera 	param_arr[param_anar_100hdx].value = 0;
39925196Ssbehera 	param_arr[param_anar_10fdx].value = 0;
39935196Ssbehera 	param_arr[param_anar_10hdx].value = 0;
39945196Ssbehera 
39955196Ssbehera 	/*
39965196Ssbehera 	 * Initialize the xcvr statistics.
39975196Ssbehera 	 */
39985196Ssbehera 	statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
39995196Ssbehera 	statsp->mac_stats.cap_100T4 = 0;
40005196Ssbehera 	statsp->mac_stats.cap_100fdx = 0;
40015196Ssbehera 	statsp->mac_stats.cap_100hdx = 0;
40025196Ssbehera 	statsp->mac_stats.cap_10fdx = 0;
40035196Ssbehera 	statsp->mac_stats.cap_10hdx = 0;
40045196Ssbehera 	statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
40055196Ssbehera 	statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
40065196Ssbehera 
40075196Ssbehera 	/*
40085196Ssbehera 	 * Initialize the xcvr advertised capability statistics.
40095196Ssbehera 	 */
40105196Ssbehera 	statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
40115196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
40125196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
40135196Ssbehera 	statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
40145196Ssbehera 	statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
40155196Ssbehera 	statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
40165196Ssbehera 	statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
40175196Ssbehera 	statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
40185196Ssbehera 	statsp->mac_stats.adv_cap_asmpause =
40195196Ssbehera 	    param_arr[param_anar_asmpause].value;
40205196Ssbehera 	statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
40215196Ssbehera 
40225196Ssbehera 	/*
40235196Ssbehera 	 * Check for extended status just in case we're
40245196Ssbehera 	 * running a Gigibit phy.
40255196Ssbehera 	 */
40265196Ssbehera 	if (bmsr.bits.extend_status) {
40275196Ssbehera #if defined(__i386)
40285196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
40295196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) !=
40305196Ssbehera 		    NXGE_OK)
40315196Ssbehera 			goto fail;
40325196Ssbehera #else
40335196Ssbehera 		if ((status = nxge_mii_read(nxgep, xcvr_portn,
40345196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
40355196Ssbehera 		    NXGE_OK)
40365196Ssbehera 			goto fail;
40375196Ssbehera #endif
40385196Ssbehera 		param_arr[param_anar_1000fdx].value &=
40395196Ssbehera 		    esr.bits.link_1000fdx;
40405196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
40415196Ssbehera 
40425196Ssbehera 		statsp->mac_stats.cap_1000fdx =
40435196Ssbehera 		    (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
40445196Ssbehera 		statsp->mac_stats.cap_1000hdx = 0;
40455196Ssbehera 	} else {
40465196Ssbehera 		param_arr[param_anar_1000fdx].value = 0;
40475196Ssbehera 		param_arr[param_anar_1000hdx].value = 0;
40485196Ssbehera 	}
40495196Ssbehera 
40505196Ssbehera 	/*
40515196Ssbehera 	 * Initialize 1G Statistics once the capability is established.
40525196Ssbehera 	 */
40535196Ssbehera 	statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
40545196Ssbehera 	statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
40555196Ssbehera 
40565196Ssbehera 	/*
40575196Ssbehera 	 * Initialize the link statistics.
40585196Ssbehera 	 */
40595196Ssbehera 	statsp->mac_stats.link_T4 = 0;
40605196Ssbehera 	statsp->mac_stats.link_asmpause = 0;
40615196Ssbehera 	statsp->mac_stats.link_pause = 0;
40625196Ssbehera 	statsp->mac_stats.link_speed = 0;
40635196Ssbehera 	statsp->mac_stats.link_duplex = 0;
40645196Ssbehera 	statsp->mac_stats.link_up = 0;
40655196Ssbehera 
40665196Ssbehera 	/*
40675196Ssbehera 	 * Switch off Auto-negotiation, 100M and full duplex.
40685196Ssbehera 	 */
40695196Ssbehera 	bmcr.value = 0;
40705196Ssbehera #if defined(__i386)
40715196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
40725196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
40735196Ssbehera 		goto fail;
40745196Ssbehera #else
40755196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
40765196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
40775196Ssbehera 		goto fail;
40785196Ssbehera #endif
40795196Ssbehera 
40805196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
40815196Ssbehera 	    (statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
40825196Ssbehera 		bmcr.bits.loopback = 1;
40835196Ssbehera 		bmcr.bits.enable_autoneg = 0;
40845196Ssbehera 		if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
40855196Ssbehera 			bmcr.bits.speed_1000_sel = 1;
40865196Ssbehera 		bmcr.bits.duplex_mode = 1;
40875196Ssbehera 		param_arr[param_autoneg].value = 0;
40885196Ssbehera 	} else {
40895196Ssbehera 		bmcr.bits.loopback = 0;
40905196Ssbehera 	}
40915196Ssbehera 
40925196Ssbehera 	if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
40935196Ssbehera 		param_arr[param_autoneg].value = 0;
40945196Ssbehera 		bcm5464r_aux.value = 0;
40955196Ssbehera 		bcm5464r_aux.bits.ext_lb = 1;
40965196Ssbehera 		bcm5464r_aux.bits.write_1 = 1;
40975196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
40985196Ssbehera 		    BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
40995196Ssbehera 			goto fail;
41005196Ssbehera 	}
41015196Ssbehera 
41025196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
41035196Ssbehera 	bmcr.bits.speed_1000_sel = 1;
41045196Ssbehera 	bmcr.bits.speed_sel = 0;
41055196Ssbehera 	bmcr.bits.duplex_mode = 1;
41065196Ssbehera 	statsp->mac_stats.link_speed = 1000;
41075196Ssbehera 	statsp->mac_stats.link_duplex = 2;
41085196Ssbehera 
41095196Ssbehera 	if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
41105196Ssbehera 		/* BCM5464R 1000mbps external loopback mode */
41115196Ssbehera 		gcr.value = 0;
41125196Ssbehera 		gcr.bits.ms_mode_en = 1;
41135196Ssbehera 		gcr.bits.master = 1;
41145196Ssbehera #if defined(__i386)
41155196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
41165196Ssbehera 		    (uint8_t)(uint32_t)(&mii_regs->gcr),
41175196Ssbehera 		    gcr.value)) != NXGE_OK)
41185196Ssbehera 			goto fail;
41195196Ssbehera #else
41205196Ssbehera 		if ((status = nxge_mii_write(nxgep, xcvr_portn,
41215196Ssbehera 		    (uint8_t)(uint64_t)(&mii_regs->gcr),
41225196Ssbehera 		    gcr.value)) != NXGE_OK)
41235196Ssbehera 			goto fail;
41245196Ssbehera #endif
41255196Ssbehera 		bmcr.value = 0;
41265196Ssbehera 		bmcr.bits.speed_1000_sel = 1;
41275196Ssbehera 		statsp->mac_stats.link_speed = 1000;
41285196Ssbehera 	}
41295196Ssbehera 
41305196Ssbehera #if defined(__i386)
41315196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
41325196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr),
41335196Ssbehera 	    bmcr.value)) != NXGE_OK)
41345196Ssbehera 		goto fail;
41355196Ssbehera #else
41365196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
41375196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr),
41385196Ssbehera 	    bmcr.value)) != NXGE_OK)
41395196Ssbehera 		goto fail;
41405196Ssbehera #endif
41415196Ssbehera 
41425196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41435196Ssbehera 	    "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
41445196Ssbehera 	    bmcr.value));
41455196Ssbehera 
41465196Ssbehera #if defined(__i386)
41475196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41485196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
41495196Ssbehera 		goto fail;
41505196Ssbehera #else
41515196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41525196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
41535196Ssbehera 		goto fail;
41545196Ssbehera #endif
41555196Ssbehera 
41565196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41575196Ssbehera 	    "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
41585196Ssbehera 
41595196Ssbehera 	/*
41605196Ssbehera 	 * Initialize the xcvr status kept in the context structure.
41615196Ssbehera 	 */
41625196Ssbehera 	nxgep->soft_bmsr.value = 0;
41635196Ssbehera #if defined(__i386)
41645196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41655196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr),
41665196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
41675196Ssbehera 		goto fail;
41685196Ssbehera #else
41695196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
41705196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr),
41715196Ssbehera 	    &nxgep->bmsr.value)) != NXGE_OK)
41725196Ssbehera 		goto fail;
41735196Ssbehera #endif
41745196Ssbehera 
41755196Ssbehera 	statsp->mac_stats.xcvr_inits++;
41765196Ssbehera 	nxgep->bmsr.value = 0;
41775196Ssbehera 
41785196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
41795196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
41805196Ssbehera 	return (status);
41815196Ssbehera 
41825196Ssbehera fail:
41835196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
41845196Ssbehera 	    "<== nxge_mii_xcvr_fiber_init status 0x%x", status));
41855196Ssbehera 	return (status);
41865196Ssbehera }
41875196Ssbehera 
41883859Sml29623 /* Read from a MII compliant register */
41893859Sml29623 
41903859Sml29623 nxge_status_t
41913859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
41923859Sml29623 		uint16_t *value)
41933859Sml29623 {
41943859Sml29623 	npi_status_t rs = NPI_SUCCESS;
41953859Sml29623 
41963859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
41976929Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
41983859Sml29623 
41996075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
42003859Sml29623 
42015196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
42025196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
42033859Sml29623 		if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
42046929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42053859Sml29623 			goto fail;
42064977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42074977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
42083859Sml29623 		if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
42096929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42103859Sml29623 			goto fail;
42113859Sml29623 	} else
42123859Sml29623 		goto fail;
42133859Sml29623 
42146075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42153859Sml29623 
42163859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
42176929Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
42183859Sml29623 	return (NXGE_OK);
42193859Sml29623 fail:
42206075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42213859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42226929Smisaki 	    "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
42233859Sml29623 
42243859Sml29623 	return (NXGE_ERROR | rs);
42253859Sml29623 }
42263859Sml29623 
42273859Sml29623 /* Write to a MII compliant Register */
42283859Sml29623 
42293859Sml29623 nxge_status_t
42303859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
42313859Sml29623 		uint16_t value)
42323859Sml29623 {
42333859Sml29623 	npi_status_t rs = NPI_SUCCESS;
42343859Sml29623 
42353859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
42366929Smisaki 	    "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
42373859Sml29623 
42386075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
42393859Sml29623 
42405196Ssbehera 	if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
42415196Ssbehera 	    (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
42423859Sml29623 		if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
42436929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42443859Sml29623 			goto fail;
42454977Sraghus 	} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
42464977Sraghus 	    (nxgep->mac.portmode == PORT_1G_SERDES)) {
42473859Sml29623 		if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
42486929Smisaki 		    xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
42493859Sml29623 			goto fail;
42503859Sml29623 	} else
42513859Sml29623 		goto fail;
42523859Sml29623 
42536075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42543859Sml29623 
42553859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
42566929Smisaki 	    "xcvr_reg<%d>", xcvr_portn, xcvr_reg));
42573859Sml29623 	return (NXGE_OK);
42583859Sml29623 fail:
42596075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42603859Sml29623 
42613859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42626929Smisaki 	    "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
42633859Sml29623 
42643859Sml29623 	return (NXGE_ERROR | rs);
42653859Sml29623 }
42663859Sml29623 
42676835Syc148097 /*
42686835Syc148097  * Perform write to Clause45 serdes / transceiver device
42696835Syc148097  * Arguments:
42706835Syc148097  *	xcvr_portn: 	The IEEE 802.3 Clause45 PHYAD, it is the same as port
42716835Syc148097  *			number if nxge_mdio_write is used for accessing the
42726835Syc148097  *			internal LSIL serdes. Otherwise PHYAD is different
42736835Syc148097  * 			for different platforms.
42746835Syc148097  *	device:		With each PHYAD, the driver can use MDIO to control
42756835Syc148097  *			multiple devices inside the PHY, here "device" is an
42766835Syc148097  *			MMD (MDIO managable device).
42776835Syc148097  *	xcvr_reg:	Each device has multiple registers. xcvr_reg specifies
42786835Syc148097  *			the register which the driver will write value to.
42796835Syc148097  *	value:		The register value will be filled in.
42806835Syc148097  */
42813859Sml29623 nxge_status_t
42823859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
42833859Sml29623 		uint16_t xcvr_reg, uint16_t *value)
42843859Sml29623 {
42853859Sml29623 	npi_status_t rs = NPI_SUCCESS;
42863859Sml29623 
42873859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
42886929Smisaki 	    xcvr_portn));
42893859Sml29623 
42905780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
42913859Sml29623 
42923859Sml29623 	if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
42936929Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
42943859Sml29623 		goto fail;
42953859Sml29623 
42965780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
42973859Sml29623 
42983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
42996929Smisaki 	    xcvr_portn));
43003859Sml29623 	return (NXGE_OK);
43013859Sml29623 fail:
43025780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43033859Sml29623 
43043859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43056929Smisaki 	    "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
43063859Sml29623 
43073859Sml29623 	return (NXGE_ERROR | rs);
43083859Sml29623 }
43093859Sml29623 
43103859Sml29623 /* Perform write to Clause45 serdes / transceiver device */
43113859Sml29623 
43123859Sml29623 nxge_status_t
43133859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
43143859Sml29623 		uint16_t xcvr_reg, uint16_t value)
43153859Sml29623 {
43163859Sml29623 	npi_status_t rs = NPI_SUCCESS;
43173859Sml29623 
43183859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
43196929Smisaki 	    xcvr_portn));
43203859Sml29623 
43215780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
43223859Sml29623 
43233859Sml29623 	if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
43246929Smisaki 	    xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
43253859Sml29623 		goto fail;
43263859Sml29623 
43275780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43283859Sml29623 
43293859Sml29623 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
43306929Smisaki 	    xcvr_portn));
43313859Sml29623 	return (NXGE_OK);
43323859Sml29623 fail:
43335780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
43343859Sml29623 
43353859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43366929Smisaki 	    "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
43373859Sml29623 
43383859Sml29623 	return (NXGE_ERROR | rs);
43393859Sml29623 }
43403859Sml29623 
43413859Sml29623 
43423859Sml29623 /* Check MII to see if there is any link status change */
43433859Sml29623 
43443859Sml29623 nxge_status_t
43453859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
43463859Sml29623 		nxge_link_state_t *link_up)
43473859Sml29623 {
43483859Sml29623 	p_nxge_param_t	param_arr;
43493859Sml29623 	p_nxge_stats_t	statsp;
43503859Sml29623 	p_mii_regs_t	mii_regs;
43513859Sml29623 	p_mii_bmsr_t	soft_bmsr;
43523859Sml29623 	mii_anar_t	anar;
43533859Sml29623 	mii_anlpar_t	anlpar;
43543859Sml29623 	mii_anar_t	an_common;
43553859Sml29623 	mii_aner_t	aner;
43563859Sml29623 	mii_gsr_t	gsr;
43573859Sml29623 	nxge_status_t	status = NXGE_OK;
43583859Sml29623 
43593859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
43603859Sml29623 
43613859Sml29623 	mii_regs = NULL;
43623859Sml29623 	param_arr = nxgep->param_arr;
43633859Sml29623 	statsp = nxgep->statsp;
43643859Sml29623 	soft_bmsr = &nxgep->soft_bmsr;
43653859Sml29623 	*link_up = LINK_NO_CHANGE;
43663859Sml29623 
43675196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43685196Ssbehera 	    "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
43695196Ssbehera 	    bmsr.value, bmsr_ints.value));
43705196Ssbehera 
43713859Sml29623 	if (bmsr_ints.bits.link_status) {
43725196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43735196Ssbehera 		    "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
43745196Ssbehera 		    bmsr.value, bmsr_ints.value));
43753859Sml29623 		if (bmsr.bits.link_status) {
43763859Sml29623 			soft_bmsr->bits.link_status = 1;
43775196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43785196Ssbehera 		    "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
43795196Ssbehera 		    "0x%x", bmsr.value, bmsr_ints.value));
43803859Sml29623 		} else {
43813859Sml29623 			statsp->mac_stats.link_up = 0;
43823859Sml29623 			soft_bmsr->bits.link_status = 0;
43833859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
43846929Smisaki 			    "Link down cable problem"));
43853859Sml29623 			*link_up = LINK_IS_DOWN;
43863859Sml29623 		}
43873859Sml29623 	}
43883859Sml29623 
43895196Ssbehera 	if (nxgep->mac.portmode == PORT_1G_COPPER &&
43905196Ssbehera 	    param_arr[param_autoneg].value) {
43913859Sml29623 		if (bmsr_ints.bits.auto_neg_complete) {
43923859Sml29623 			if (bmsr.bits.auto_neg_complete)
43933859Sml29623 				soft_bmsr->bits.auto_neg_complete = 1;
43943859Sml29623 			else
43953859Sml29623 				soft_bmsr->bits.auto_neg_complete = 0;
43963859Sml29623 		}
43973859Sml29623 		if (soft_bmsr->bits.link_status == 0) {
43983859Sml29623 			statsp->mac_stats.link_T4 = 0;
43993859Sml29623 			statsp->mac_stats.link_speed = 0;
44003859Sml29623 			statsp->mac_stats.link_duplex = 0;
44013859Sml29623 			statsp->mac_stats.link_asmpause = 0;
44023859Sml29623 			statsp->mac_stats.link_pause = 0;
44033859Sml29623 			statsp->mac_stats.lp_cap_autoneg = 0;
44043859Sml29623 			statsp->mac_stats.lp_cap_100T4 = 0;
44053859Sml29623 			statsp->mac_stats.lp_cap_1000fdx = 0;
44063859Sml29623 			statsp->mac_stats.lp_cap_1000hdx = 0;
44073859Sml29623 			statsp->mac_stats.lp_cap_100fdx = 0;
44083859Sml29623 			statsp->mac_stats.lp_cap_100hdx = 0;
44093859Sml29623 			statsp->mac_stats.lp_cap_10fdx = 0;
44103859Sml29623 			statsp->mac_stats.lp_cap_10hdx = 0;
44113859Sml29623 			statsp->mac_stats.lp_cap_10gfdx = 0;
44123859Sml29623 			statsp->mac_stats.lp_cap_10ghdx = 0;
44133859Sml29623 			statsp->mac_stats.lp_cap_asmpause = 0;
44143859Sml29623 			statsp->mac_stats.lp_cap_pause = 0;
44153859Sml29623 		}
44163859Sml29623 	} else
44173859Sml29623 		soft_bmsr->bits.auto_neg_complete = 1;
44183859Sml29623 
44193859Sml29623 	if ((bmsr_ints.bits.link_status ||
44206929Smisaki 	    bmsr_ints.bits.auto_neg_complete) &&
44216929Smisaki 	    soft_bmsr->bits.link_status &&
44226929Smisaki 	    soft_bmsr->bits.auto_neg_complete) {
44233859Sml29623 		statsp->mac_stats.link_up = 1;
44245196Ssbehera 
44255196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
44265196Ssbehera 		    "==> nxge_mii_check "
44275196Ssbehera 		    "(auto negotiation complete or link up) "
44285196Ssbehera 		    "soft bmsr 0x%x bmsr_int 0x%x",
44295196Ssbehera 		    bmsr.value, bmsr_ints.value));
44305196Ssbehera 
44315196Ssbehera 		if (nxgep->mac.portmode == PORT_1G_COPPER &&
44325196Ssbehera 		    param_arr[param_autoneg].value) {
44333859Sml29623 			if ((status = nxge_mii_read(nxgep,
44346929Smisaki 			    statsp->mac_stats.xcvr_portn,
44355125Sjoycey #if defined(__i386)
44366929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anar),
44375125Sjoycey #else
44386929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anar),
44395125Sjoycey #endif
44406929Smisaki 			    &anar.value)) != NXGE_OK)
44413859Sml29623 				goto fail;
44423859Sml29623 			if ((status = nxge_mii_read(nxgep,
44436929Smisaki 			    statsp->mac_stats.xcvr_portn,
44445125Sjoycey #if defined(__i386)
44456929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
44465125Sjoycey #else
44476929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
44485125Sjoycey #endif
44496929Smisaki 			    &anlpar.value)) != NXGE_OK)
44503859Sml29623 				goto fail;
44513859Sml29623 			if ((status = nxge_mii_read(nxgep,
44526929Smisaki 			    statsp->mac_stats.xcvr_portn,
44535125Sjoycey #if defined(__i386)
44546929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->aner),
44555125Sjoycey #else
44566929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->aner),
44575125Sjoycey #endif
44586929Smisaki 			    &aner.value)) != NXGE_OK)
44593859Sml29623 				goto fail;
44603859Sml29623 			statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
44613859Sml29623 			statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
44623859Sml29623 			statsp->mac_stats.lp_cap_100fdx =
44636929Smisaki 			    anlpar.bits.cap_100fdx;
44643859Sml29623 			statsp->mac_stats.lp_cap_100hdx =
44656929Smisaki 			    anlpar.bits.cap_100hdx;
44663859Sml29623 			statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
44673859Sml29623 			statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
44683859Sml29623 			statsp->mac_stats.lp_cap_asmpause =
44696929Smisaki 			    anlpar.bits.cap_asmpause;
44703859Sml29623 			statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
44713859Sml29623 			an_common.value = anar.value & anlpar.value;
44723859Sml29623 			if (param_arr[param_anar_1000fdx].value ||
44736929Smisaki 			    param_arr[param_anar_1000hdx].value) {
44743859Sml29623 				if ((status = nxge_mii_read(nxgep,
44756929Smisaki 				    statsp->mac_stats.xcvr_portn,
44765125Sjoycey #if defined(__i386)
44776929Smisaki 				    (uint8_t)(uint32_t)(&mii_regs->gsr),
44785125Sjoycey #else
44796929Smisaki 				    (uint8_t)(uint64_t)(&mii_regs->gsr),
44805125Sjoycey #endif
44816929Smisaki 				    &gsr.value)) != NXGE_OK)
44823859Sml29623 					goto fail;
44833859Sml29623 				statsp->mac_stats.lp_cap_1000fdx =
44846929Smisaki 				    gsr.bits.link_1000fdx;
44853859Sml29623 				statsp->mac_stats.lp_cap_1000hdx =
44866929Smisaki 				    gsr.bits.link_1000hdx;
44873859Sml29623 				if (param_arr[param_anar_1000fdx].value &&
44886929Smisaki 				    gsr.bits.link_1000fdx) {
44893859Sml29623 					statsp->mac_stats.link_speed = 1000;
44903859Sml29623 					statsp->mac_stats.link_duplex = 2;
44913859Sml29623 				} else if (
44926929Smisaki 				    param_arr[param_anar_1000hdx].value &&
44936929Smisaki 				    gsr.bits.link_1000hdx) {
44943859Sml29623 					statsp->mac_stats.link_speed = 1000;
44953859Sml29623 					statsp->mac_stats.link_duplex = 1;
44963859Sml29623 				}
44973859Sml29623 			}
44983859Sml29623 			if ((an_common.value != 0) &&
44996929Smisaki 			    !(statsp->mac_stats.link_speed)) {
45003859Sml29623 				if (an_common.bits.cap_100T4) {
45013859Sml29623 					statsp->mac_stats.link_T4 = 1;
45023859Sml29623 					statsp->mac_stats.link_speed = 100;
45033859Sml29623 					statsp->mac_stats.link_duplex = 1;
45043859Sml29623 				} else if (an_common.bits.cap_100fdx) {
45053859Sml29623 					statsp->mac_stats.link_speed = 100;
45063859Sml29623 					statsp->mac_stats.link_duplex = 2;
45073859Sml29623 				} else if (an_common.bits.cap_100hdx) {
45083859Sml29623 					statsp->mac_stats.link_speed = 100;
45093859Sml29623 					statsp->mac_stats.link_duplex = 1;
45103859Sml29623 				} else if (an_common.bits.cap_10fdx) {
45113859Sml29623 					statsp->mac_stats.link_speed = 10;
45123859Sml29623 					statsp->mac_stats.link_duplex = 2;
45133859Sml29623 				} else if (an_common.bits.cap_10hdx) {
45143859Sml29623 					statsp->mac_stats.link_speed = 10;
45153859Sml29623 					statsp->mac_stats.link_duplex = 1;
45163859Sml29623 				} else {
45173859Sml29623 					goto fail;
45183859Sml29623 				}
45193859Sml29623 			}
45203859Sml29623 			if (statsp->mac_stats.link_duplex != 1) {
45216929Smisaki 				int	link_pause;
45226929Smisaki 				int	cp, lcp;
45236929Smisaki 
45243859Sml29623 				statsp->mac_stats.link_asmpause =
45256929Smisaki 				    an_common.bits.cap_asmpause;
45266929Smisaki 				cp = statsp->mac_stats.cap_pause;
45276929Smisaki 				lcp = statsp->mac_stats.lp_cap_pause;
45286929Smisaki 				if (statsp->mac_stats.link_asmpause) {
45296929Smisaki 					if ((cp == 0) && (lcp == 1)) {
45306929Smisaki 						link_pause = 0;
45316929Smisaki 					} else {
45326929Smisaki 						link_pause = 1;
45336929Smisaki 					}
45346929Smisaki 				} else {
45356929Smisaki 					link_pause = an_common.bits.cap_pause;
45366929Smisaki 				}
45376929Smisaki 				statsp->mac_stats.link_pause = link_pause;
45383859Sml29623 			}
45395196Ssbehera 		} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
45405196Ssbehera 			statsp->mac_stats.link_speed = 1000;
45415196Ssbehera 			statsp->mac_stats.link_duplex = 2;
45423859Sml29623 		}
45433859Sml29623 		*link_up = LINK_IS_UP;
45443859Sml29623 	}
45453859Sml29623 
45463859Sml29623 	if (nxgep->link_notify) {
45473859Sml29623 		*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
45486929Smisaki 		    LINK_IS_DOWN);
45493859Sml29623 		nxgep->link_notify = B_FALSE;
45503859Sml29623 	}
45513859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
45523859Sml29623 	return (NXGE_OK);
45533859Sml29623 fail:
45543859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
45556929Smisaki 	    "nxge_mii_check: Unable to check MII"));
45563859Sml29623 	return (status);
45573859Sml29623 }
45583859Sml29623 
45596835Syc148097 /*
45606835Syc148097  * Check PCS to see if there is any link status change.
45616835Syc148097  * This function is called by PORT_1G_SERDES only.
45626835Syc148097  */
45636835Syc148097 void
45644977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
45654977Sraghus {
45664977Sraghus 	p_nxge_stats_t	statsp;
45674977Sraghus 	boolean_t	linkup;
45684977Sraghus 
45694977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
45704977Sraghus 
45714977Sraghus 	statsp = nxgep->statsp;
45724977Sraghus 	*link_up = LINK_NO_CHANGE;
45734977Sraghus 
45744977Sraghus 	(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
45754977Sraghus 	if (linkup) {
45764977Sraghus 		if (nxgep->link_notify ||
45774977Sraghus 		    nxgep->statsp->mac_stats.link_up == 0) {
45784977Sraghus 			statsp->mac_stats.link_up = 1;
45794977Sraghus 			statsp->mac_stats.link_speed = 1000;
45804977Sraghus 			statsp->mac_stats.link_duplex = 2;
45814977Sraghus 			*link_up = LINK_IS_UP;
45824977Sraghus 			nxgep->link_notify = B_FALSE;
45834977Sraghus 		}
45844977Sraghus 	} else {
45854977Sraghus 		if (nxgep->link_notify ||
45864977Sraghus 		    nxgep->statsp->mac_stats.link_up == 1) {
45874977Sraghus 			statsp->mac_stats.link_up = 0;
45884977Sraghus 			statsp->mac_stats.link_speed = 0;
45894977Sraghus 			statsp->mac_stats.link_duplex = 0;
45904977Sraghus 			*link_up = LINK_IS_DOWN;
45914977Sraghus 			nxgep->link_notify = B_FALSE;
45924977Sraghus 		}
45934977Sraghus 	}
45944977Sraghus 
45954977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
45964977Sraghus }
45974977Sraghus 
45983859Sml29623 /* Add a multicast address entry into the HW hash table */
45993859Sml29623 
46003859Sml29623 nxge_status_t
46013859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
46023859Sml29623 {
46033859Sml29623 	uint32_t mchash;
46043859Sml29623 	p_hash_filter_t hash_filter;
46053859Sml29623 	uint16_t hash_bit;
46063859Sml29623 	boolean_t rx_init = B_FALSE;
46073859Sml29623 	uint_t j;
46083859Sml29623 	nxge_status_t status = NXGE_OK;
46093859Sml29623 
46103859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
46113859Sml29623 
46123859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
46133859Sml29623 	mchash = crc32_mchash(addrp);
46143859Sml29623 	if (nxgep->hash_filter == NULL) {
46153859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
46166929Smisaki 		    "Allocating hash filter storage."));
46173859Sml29623 		nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
46186929Smisaki 		    KM_SLEEP);
46193859Sml29623 	}
46203859Sml29623 	hash_filter = nxgep->hash_filter;
46213859Sml29623 	j = mchash / HASH_REG_WIDTH;
46223859Sml29623 	hash_bit = (1 << (mchash % HASH_REG_WIDTH));
46233859Sml29623 	hash_filter->hash_filter_regs[j] |= hash_bit;
46243859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]++;
46253859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
46263859Sml29623 		hash_filter->hash_ref_cnt++;
46273859Sml29623 		rx_init = B_TRUE;
46283859Sml29623 	}
46293859Sml29623 	if (rx_init) {
46303859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
46313859Sml29623 			goto fail;
46323859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
46333859Sml29623 			goto fail;
46343859Sml29623 	}
46353859Sml29623 
46363859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46373859Sml29623 
46383859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
46393859Sml29623 
46403859Sml29623 	return (NXGE_OK);
46413859Sml29623 fail:
46423859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46433859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
46446929Smisaki 	    "Unable to add multicast address"));
46453859Sml29623 	return (status);
46463859Sml29623 }
46473859Sml29623 
46483859Sml29623 /* Remove a multicast address entry from the HW hash table */
46493859Sml29623 
46503859Sml29623 nxge_status_t
46513859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
46523859Sml29623 {
46533859Sml29623 	uint32_t mchash;
46543859Sml29623 	p_hash_filter_t hash_filter;
46553859Sml29623 	uint16_t hash_bit;
46563859Sml29623 	boolean_t rx_init = B_FALSE;
46573859Sml29623 	uint_t j;
46583859Sml29623 	nxge_status_t status = NXGE_OK;
46593859Sml29623 
46603859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
46613859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
46623859Sml29623 	mchash = crc32_mchash(addrp);
46633859Sml29623 	if (nxgep->hash_filter == NULL) {
46643859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
46656929Smisaki 		    "Hash filter already de_allocated."));
46663859Sml29623 		RW_EXIT(&nxgep->filter_lock);
46673859Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
46683859Sml29623 		return (NXGE_OK);
46693859Sml29623 	}
46703859Sml29623 	hash_filter = nxgep->hash_filter;
46713859Sml29623 	hash_filter->hash_bit_ref_cnt[mchash]--;
46723859Sml29623 	if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
46733859Sml29623 		j = mchash / HASH_REG_WIDTH;
46743859Sml29623 		hash_bit = (1 << (mchash % HASH_REG_WIDTH));
46753859Sml29623 		hash_filter->hash_filter_regs[j] &= ~hash_bit;
46763859Sml29623 		hash_filter->hash_ref_cnt--;
46773859Sml29623 		rx_init = B_TRUE;
46783859Sml29623 	}
46793859Sml29623 	if (hash_filter->hash_ref_cnt == 0) {
46803859Sml29623 		NXGE_DEBUG_MSG((NULL, STR_CTL,
46816929Smisaki 		    "De-allocating hash filter storage."));
46823859Sml29623 		KMEM_FREE(hash_filter, sizeof (hash_filter_t));
46833859Sml29623 		nxgep->hash_filter = NULL;
46843859Sml29623 	}
46853859Sml29623 
46863859Sml29623 	if (rx_init) {
46873859Sml29623 		if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
46883859Sml29623 			goto fail;
46893859Sml29623 		if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
46903859Sml29623 			goto fail;
46913859Sml29623 	}
46923859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46933859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
46943859Sml29623 
46953859Sml29623 	return (NXGE_OK);
46963859Sml29623 fail:
46973859Sml29623 	RW_EXIT(&nxgep->filter_lock);
46983859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
46996929Smisaki 	    "Unable to remove multicast address"));
47003859Sml29623 
47013859Sml29623 	return (status);
47023859Sml29623 }
47033859Sml29623 
47043859Sml29623 /* Set MAC address into MAC address HW registers */
47053859Sml29623 
47063859Sml29623 nxge_status_t
47073859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
47083859Sml29623 {
47093859Sml29623 	nxge_status_t status = NXGE_OK;
47103859Sml29623 
47113859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
47123859Sml29623 
47133859Sml29623 	MUTEX_ENTER(&nxgep->ouraddr_lock);
47143859Sml29623 	/*
47153859Sml29623 	 * Exit if the address is same as ouraddr or multicast or broadcast
47163859Sml29623 	 */
47173859Sml29623 	if (((addrp->ether_addr_octet[0] & 01) == 1) ||
47186929Smisaki 	    (ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
47196929Smisaki 	    (ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
47203859Sml29623 		goto nxge_set_mac_addr_exit;
47213859Sml29623 	}
47223859Sml29623 	nxgep->ouraddr = *addrp;
47233859Sml29623 	/*
47243859Sml29623 	 * Set new interface local address and re-init device.
47253859Sml29623 	 * This is destructive to any other streams attached
47263859Sml29623 	 * to this device.
47273859Sml29623 	 */
47283859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
47293859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
47303859Sml29623 		goto fail;
47313859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
47323859Sml29623 		goto fail;
47333859Sml29623 
47343859Sml29623 	RW_EXIT(&nxgep->filter_lock);
47353859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47363859Sml29623 	goto nxge_set_mac_addr_end;
47373859Sml29623 nxge_set_mac_addr_exit:
47383859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47393859Sml29623 nxge_set_mac_addr_end:
47403859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
47413859Sml29623 
47423859Sml29623 	return (NXGE_OK);
47433859Sml29623 fail:
47443859Sml29623 	MUTEX_EXIT(&nxgep->ouraddr_lock);
47453859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
47466929Smisaki 	    "Unable to set mac address"));
47473859Sml29623 	return (status);
47483859Sml29623 }
47493859Sml29623 
47504693Stm144005 static
47514693Stm144005 check_link_state_t
47526835Syc148097 nxge_check_link_stop(nxge_t *nxge)
47534693Stm144005 {
47544693Stm144005 	/* If the poll has been cancelled, return STOP. */
47554693Stm144005 	MUTEX_ENTER(&nxge->poll_lock);
47564693Stm144005 	if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
47574693Stm144005 		nxge->poll_state = LINK_MONITOR_STOP;
47584693Stm144005 		nxge->nxge_link_poll_timerid = 0;
47594693Stm144005 		cv_broadcast(&nxge->poll_cv);
47604693Stm144005 		MUTEX_EXIT(&nxge->poll_lock);
47614693Stm144005 
47624693Stm144005 		NXGE_DEBUG_MSG((nxge, MAC_CTL,
47634693Stm144005 		    "nxge_check_%s_link(port<%d>) stopped.",
47644693Stm144005 		    nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
47654693Stm144005 		    nxge->mac.portnum));
47664693Stm144005 		return (CHECK_LINK_STOP);
47674693Stm144005 	}
47684693Stm144005 	MUTEX_EXIT(&nxge->poll_lock);
47694693Stm144005 
47704693Stm144005 	return (CHECK_LINK_RESCHEDULE);
47714693Stm144005 }
47724693Stm144005 
47736835Syc148097 /*
47746835Syc148097  * Check status of MII (MIF or PCS) link.
47756835Syc148097  * This function is called once per second, that is because this function
47766835Syc148097  * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
47776835Syc148097  * call this function recursively.
47786835Syc148097  */
47794732Sdavemq static nxge_status_t
47803859Sml29623 nxge_check_mii_link(p_nxge_t nxgep)
47813859Sml29623 {
47823859Sml29623 	mii_bmsr_t bmsr_ints, bmsr_data;
47833859Sml29623 	mii_anlpar_t anlpar;
47843859Sml29623 	mii_gsr_t gsr;
47853859Sml29623 	p_mii_regs_t mii_regs;
47863859Sml29623 	nxge_status_t status = NXGE_OK;
47873859Sml29623 	uint8_t portn;
47883859Sml29623 	nxge_link_state_t link_up;
47893859Sml29623 
47904693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
47914693Stm144005 		return (NXGE_ERROR);
47924693Stm144005 
47934693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
47944693Stm144005 		return (NXGE_OK);
47954693Stm144005 
47963859Sml29623 	portn = nxgep->mac.portnum;
47973859Sml29623 
47983859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
47994693Stm144005 	    portn));
48003859Sml29623 
48013859Sml29623 	mii_regs = NULL;
48023859Sml29623 
48033859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
48043859Sml29623 
48053859Sml29623 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
48063859Sml29623 		goto nxge_check_mii_link_exit;
48073859Sml29623 
48084977Sraghus 	switch (nxgep->mac.portmode) {
48094977Sraghus 	default:
48105196Ssbehera 		bmsr_data.value = 0;
48113859Sml29623 		if ((status = nxge_mii_read(nxgep,
48124977Sraghus 		    nxgep->statsp->mac_stats.xcvr_portn,
48135125Sjoycey #if defined(__i386)
48145125Sjoycey 		    (uint8_t)(uint32_t)(&mii_regs->bmsr),
48155125Sjoycey #else
48164977Sraghus 		    (uint8_t)(uint64_t)(&mii_regs->bmsr),
48175125Sjoycey #endif
48184977Sraghus 		    &bmsr_data.value)) != NXGE_OK) {
48193859Sml29623 			goto fail;
48203859Sml29623 		}
48214977Sraghus 
48225196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48235196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> "
48245196Ssbehera 		    "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
48255572Ssbehera 		    portn, bmsr_data.value, nxgep->bmsr.value));
48265196Ssbehera 
48274977Sraghus 		if (nxgep->param_arr[param_autoneg].value) {
48284977Sraghus 			if ((status = nxge_mii_read(nxgep,
48296929Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
48305125Sjoycey #if defined(__i386)
48316929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->gsr),
48325125Sjoycey #else
48336929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->gsr),
48345125Sjoycey #endif
48356929Smisaki 			    &gsr.value)) != NXGE_OK)
48364977Sraghus 				goto fail;
48374977Sraghus 			if ((status = nxge_mii_read(nxgep,
48386929Smisaki 			    nxgep->statsp->mac_stats.xcvr_portn,
48395125Sjoycey #if defined(__i386)
48406929Smisaki 			    (uint8_t)(uint32_t)(&mii_regs->anlpar),
48415125Sjoycey #else
48426929Smisaki 			    (uint8_t)(uint64_t)(&mii_regs->anlpar),
48435125Sjoycey #endif
48446929Smisaki 			    &anlpar.value)) != NXGE_OK)
48454977Sraghus 				goto fail;
48465196Ssbehera 			if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
48475196Ssbehera 
48485196Ssbehera 				if (nxgep->statsp->mac_stats.link_up &&
48495196Ssbehera 				    ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
48505196Ssbehera 				    gsr.bits.link_1000fdx) ||
48515196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_1000hdx ^
48525196Ssbehera 				    gsr.bits.link_1000hdx) ||
48535196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100T4 ^
48545196Ssbehera 				    anlpar.bits.cap_100T4) ||
48555196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100fdx ^
48565196Ssbehera 				    anlpar.bits.cap_100fdx) ||
48575196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_100hdx ^
48585196Ssbehera 				    anlpar.bits.cap_100hdx) ||
48595196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10fdx ^
48605196Ssbehera 				    anlpar.bits.cap_10fdx) ||
48615196Ssbehera 				    (nxgep->statsp->mac_stats.lp_cap_10hdx ^
48625196Ssbehera 				    anlpar.bits.cap_10hdx))) {
48635196Ssbehera 					bmsr_data.bits.link_status = 0;
48645196Ssbehera 				}
48654977Sraghus 			}
48664977Sraghus 		}
48674977Sraghus 
48684977Sraghus 		/* Workaround for link down issue */
48694977Sraghus 		if (bmsr_data.value == 0) {
48704977Sraghus 			cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
48714977Sraghus 			goto nxge_check_mii_link_exit;
48724977Sraghus 		}
48734977Sraghus 
48745196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48755196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> :"
48765196Ssbehera 		    "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
48775572Ssbehera 		    portn, nxgep->bmsr.value, bmsr_data.value));
48785196Ssbehera 
48794977Sraghus 		bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
48804977Sraghus 		nxgep->bmsr.value = bmsr_data.value;
48815196Ssbehera 
48825196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
48835196Ssbehera 		    "==> nxge_check_mii_link port<0x%x> CALLING "
48845196Ssbehera 		    "bmsr_data 0x%x bmsr_ints.value 0x%x",
48855572Ssbehera 		    portn, bmsr_data.value, bmsr_ints.value));
48865196Ssbehera 
48874977Sraghus 		if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
48884977Sraghus 		    &link_up)) != NXGE_OK) {
48894977Sraghus 			goto fail;
48904977Sraghus 		}
48914977Sraghus 		break;
48924977Sraghus 
48934977Sraghus 	case PORT_1G_SERDES:
48946835Syc148097 		/*
48956835Syc148097 		 * Above default is for all cases except PORT_1G_SERDES.
48966835Syc148097 		 * The default case gets information from the PHY, but a
48976835Syc148097 		 * nxge whose portmode equals PORT_1G_SERDES does not
48986835Syc148097 		 * have a PHY.
48996835Syc148097 		 */
49004977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49014977Sraghus 		    "==> nxge_check_mii_link port<%d> (SERDES)", portn));
49026835Syc148097 		nxge_pcs_check(nxgep, portn, &link_up);
49034977Sraghus 		break;
49043859Sml29623 	}
49053859Sml29623 
49063859Sml29623 nxge_check_mii_link_exit:
49073859Sml29623 	RW_EXIT(&nxgep->filter_lock);
49083859Sml29623 	if (link_up == LINK_IS_UP) {
49093859Sml29623 		nxge_link_is_up(nxgep);
49103859Sml29623 	} else if (link_up == LINK_IS_DOWN) {
49113859Sml29623 		nxge_link_is_down(nxgep);
49123859Sml29623 	}
49133859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
49143859Sml29623 
49153859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
49166929Smisaki 	    portn));
49173859Sml29623 	return (NXGE_OK);
49183859Sml29623 
49193859Sml29623 fail:
49203859Sml29623 	RW_EXIT(&nxgep->filter_lock);
49213859Sml29623 
49223859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
49233859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
49246929Smisaki 	    "nxge_check_mii_link: Failed to check link port<%d>", portn));
49253859Sml29623 	return (status);
49263859Sml29623 }
49273859Sml29623 
49283859Sml29623 /*ARGSUSED*/
49294732Sdavemq static nxge_status_t
49303859Sml29623 nxge_check_10g_link(p_nxge_t nxgep)
49313859Sml29623 {
49323859Sml29623 	uint8_t		portn;
49333859Sml29623 	nxge_status_t	status = NXGE_OK;
49345422Ssbehera 	boolean_t	link_up;
49354977Sraghus 	uint32_t	val;
49364977Sraghus 	npi_status_t	rs;
49373859Sml29623 
49384693Stm144005 	if (nxgep->nxge_magic != NXGE_MAGIC)
49394693Stm144005 		return (NXGE_ERROR);
49404693Stm144005 
49414693Stm144005 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
49424693Stm144005 		return (NXGE_OK);
49434693Stm144005 
49443859Sml29623 	portn = nxgep->mac.portnum;
49455196Ssbehera 	val = 0;
49465196Ssbehera 	rs = NPI_SUCCESS;
49473859Sml29623 
49483859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
49494693Stm144005 	    portn));
49503859Sml29623 
49514977Sraghus 	switch (nxgep->mac.portmode) {
49524977Sraghus 	default:
49535572Ssbehera 		/*
49545572Ssbehera 		 * Check if the phy is present in case of hot swappable phy
49555572Ssbehera 		 */
49565572Ssbehera 		if (nxgep->hot_swappable_phy) {
49575572Ssbehera 			boolean_t phy_present_now = B_FALSE;
49585572Ssbehera 
49595572Ssbehera 			/*
49605572Ssbehera 			 * If this is the 2nd Goa port, then check 2 addresses
49615572Ssbehera 			 * to take care of the Goa NEM card requirements.
49625572Ssbehera 			 */
49635572Ssbehera 			if (portn == 1) {
49645572Ssbehera 				if (nxge_is_phy_present(nxgep,
49656835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR,
49665572Ssbehera 				    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
49675572Ssbehera 					phy_present_now = B_TRUE;
49685572Ssbehera 					nxgep->xcvr_addr =
49696835Syc148097 					    ALT_GOA_CLAUSE45_PORT1_ADDR;
49705572Ssbehera 					goto phy_check_done;
49715572Ssbehera 				}
49725572Ssbehera 			}
49735572Ssbehera 			if (nxge_is_phy_present(nxgep,
49746835Syc148097 			    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn,
49755572Ssbehera 			    BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
49765572Ssbehera 				nxgep->xcvr_addr =
49776835Syc148097 				    (GOA_CLAUSE45_PORT_ADDR_BASE) + portn;
49785572Ssbehera 				phy_present_now = B_TRUE;
49795572Ssbehera 			}
49805572Ssbehera 
49815572Ssbehera phy_check_done:
49825572Ssbehera 			if (nxgep->phy_absent) {
49835572Ssbehera 				if (phy_present_now) {
49845572Ssbehera 				/*
49855572Ssbehera 				 * Detect, Initialize phy and do link up
49865572Ssbehera 				 * set xcvr vals, link_init, nxge_init
49875572Ssbehera 				 */
49885572Ssbehera 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
49895572Ssbehera 					    "Hot swappable phy DETECTED!!"));
49905572Ssbehera 					nxgep->phy_absent = B_FALSE;
49915572Ssbehera 					(void) nxge_xcvr_find(nxgep);
49925572Ssbehera 					(void) nxge_link_init(nxgep);
49935572Ssbehera 					if (!(nxgep->drv_state &
49945572Ssbehera 					    STATE_HW_INITIALIZED)) {
49955572Ssbehera 						status = nxge_init(nxgep);
49965572Ssbehera 						if (status != NXGE_OK) {
49975572Ssbehera 							NXGE_ERROR_MSG((nxgep,
49985572Ssbehera 							    NXGE_ERR_CTL,
49995572Ssbehera 							    "Hot swappable "
50005572Ssbehera 							    "phy present, but"
50015572Ssbehera 							    " driver init"
50025572Ssbehera 							    "  failed..."));
50035572Ssbehera 							goto fail;
50045572Ssbehera 						}
50055572Ssbehera 					}
50065572Ssbehera 				}
50075572Ssbehera 
50085572Ssbehera 				goto start_link_check;
50095572Ssbehera 
50105572Ssbehera 			} else if (!phy_present_now) {
50115572Ssbehera 				/*
50125572Ssbehera 				 * Phy gone, bring link down reset xcvr vals
50135572Ssbehera 				 */
50145572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50155572Ssbehera 				    "Hot swappable phy REMOVED!!"));
50165572Ssbehera 				nxgep->phy_absent = B_TRUE;
50175572Ssbehera 				nxgep->statsp->mac_stats.link_up = 0;
50185572Ssbehera 				nxgep->statsp->mac_stats.link_speed = 0;
50195572Ssbehera 				nxgep->statsp->mac_stats.link_duplex = 0;
50205572Ssbehera 				nxge_link_is_down(nxgep);
50215572Ssbehera 				nxgep->link_notify = B_FALSE;
50225572Ssbehera 
50235572Ssbehera 				(void) nxge_xcvr_find(nxgep);
50245572Ssbehera 
50255572Ssbehera 				goto start_link_check;
50265572Ssbehera 
50275572Ssbehera 			}
50285572Ssbehera 		}
50296604Ssbehera 		if (nxgep->chip_id == MRVL88X201X_CHIP_ID) {
50306835Syc148097 			status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
50316604Ssbehera 		} else {
50326604Ssbehera 			status = nxge_check_bcm8704_link(nxgep, &link_up);
50336604Ssbehera 		}
50344977Sraghus 		if (status != NXGE_OK)
50354977Sraghus 			goto fail;
50364977Sraghus 		break;
50374977Sraghus 	case PORT_10G_SERDES:
50384977Sraghus 		rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
50395422Ssbehera 		    XPCS_REG_STATUS, &val);
50404977Sraghus 		if (rs != 0)
50414977Sraghus 			goto fail;
50424977Sraghus 
50434977Sraghus 		link_up = B_FALSE;
50445422Ssbehera 		if (val & XPCS_STATUS_LANE_ALIGN) {
50455422Ssbehera 			link_up = B_TRUE;
50464977Sraghus 		}
50474977Sraghus 
50484977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50494977Sraghus 		    "==> nxge_check_10g_link port<%d> "
50505422Ssbehera 		    "XPCS_REG_STATUS2 0x%x link_up %d",
50515422Ssbehera 		    portn, val, link_up));
50525422Ssbehera 
50534977Sraghus 		break;
50544977Sraghus 	}
50553859Sml29623 
50563859Sml29623 	if (link_up) {
50573859Sml29623 		if (nxgep->link_notify ||
50586929Smisaki 		    nxgep->statsp->mac_stats.link_up == 0) {
50593859Sml29623 			if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
50603859Sml29623 				goto fail;
50613859Sml29623 			nxgep->statsp->mac_stats.link_up = 1;
50623859Sml29623 			nxgep->statsp->mac_stats.link_speed = 10000;
50633859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 2;
50643859Sml29623 
50653859Sml29623 			nxge_link_is_up(nxgep);
50663859Sml29623 			nxgep->link_notify = B_FALSE;
50673859Sml29623 		}
50683859Sml29623 	} else {
50693859Sml29623 		if (nxgep->link_notify ||
50706929Smisaki 		    nxgep->statsp->mac_stats.link_up == 1) {
50713859Sml29623 			if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
50723859Sml29623 				goto fail;
50733859Sml29623 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
50746929Smisaki 			    "Link down cable problem"));
50753859Sml29623 			nxgep->statsp->mac_stats.link_up = 0;
50763859Sml29623 			nxgep->statsp->mac_stats.link_speed = 0;
50773859Sml29623 			nxgep->statsp->mac_stats.link_duplex = 0;
50783859Sml29623 
50793859Sml29623 			nxge_link_is_down(nxgep);
50803859Sml29623 			nxgep->link_notify = B_FALSE;
50813859Sml29623 		}
50823859Sml29623 	}
50833859Sml29623 
50845572Ssbehera start_link_check:
50853859Sml29623 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
50863859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
50874693Stm144005 	    portn));
50883859Sml29623 	return (NXGE_OK);
50893859Sml29623 
50903859Sml29623 fail:
50914693Stm144005 	(void) nxge_check_link_stop(nxgep);
50924693Stm144005 
50933859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
50944693Stm144005 	    "nxge_check_10g_link: Failed to check link port<%d>",
50954693Stm144005 	    portn));
50963859Sml29623 	return (status);
50973859Sml29623 }
50983859Sml29623 
50993859Sml29623 
51003859Sml29623 /* Declare link down */
51013859Sml29623 
51023859Sml29623 void
51033859Sml29623 nxge_link_is_down(p_nxge_t nxgep)
51043859Sml29623 {
51054732Sdavemq 	p_nxge_stats_t statsp;
51064732Sdavemq 	char link_stat_msg[64];
51074732Sdavemq 
51083859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
51093859Sml29623 
51104732Sdavemq 	statsp = nxgep->statsp;
51114732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
51124732Sdavemq 	    statsp->mac_stats.xcvr_portn);
51134732Sdavemq 
51144732Sdavemq 	if (nxge_no_msg == B_FALSE) {
51154732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
51164732Sdavemq 	}
51174732Sdavemq 
51183859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_DOWN);
51193859Sml29623 
51203859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
51213859Sml29623 }
51223859Sml29623 
51233859Sml29623 /* Declare link up */
51243859Sml29623 
51253859Sml29623 void
51263859Sml29623 nxge_link_is_up(p_nxge_t nxgep)
51273859Sml29623 {
51284732Sdavemq 	p_nxge_stats_t statsp;
51294732Sdavemq 	char link_stat_msg[64];
51303859Sml29623 	uint32_t val;
51313859Sml29623 
51323859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
51333859Sml29623 
51344732Sdavemq 	statsp = nxgep->statsp;
51354732Sdavemq 	(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
51364732Sdavemq 	    statsp->mac_stats.xcvr_portn,
51374732Sdavemq 	    statsp->mac_stats.link_speed);
51384732Sdavemq 
51394732Sdavemq 	if (statsp->mac_stats.link_T4)
51404732Sdavemq 		(void) strcat(link_stat_msg, "T4");
51414732Sdavemq 	else if (statsp->mac_stats.link_duplex == 2)
51424732Sdavemq 		(void) strcat(link_stat_msg, "full duplex");
51434732Sdavemq 	else
51444732Sdavemq 		(void) strcat(link_stat_msg, "half duplex");
51454732Sdavemq 
51463859Sml29623 
51473859Sml29623 	/* Clean up symbol errors incurred during link transition */
51484977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
51494977Sraghus 	    (nxgep->mac.portmode == PORT_10G_SERDES)) {
51503859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
51516929Smisaki 		    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
51523859Sml29623 		(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
51536929Smisaki 		    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
51543859Sml29623 	}
51553859Sml29623 
51566835Syc148097 	/*
51576835Syc148097 	 * If the driver was plumbed without a link (therefore auto-negotiation
51586835Syc148097 	 * could not complete), the driver will detect a link up when a cable
51596835Syc148097 	 * conneting to a link partner is plugged into the port. By the time
51606835Syc148097 	 * link-up is detected, auto-negotiation should have completed (The
51616835Syc148097 	 * TN1010 tries to contact a link partner every 8~24ms). Here we re-
51626835Syc148097 	 * configure the Neptune/NIU according to the newly negotiated speed.
51636835Syc148097 	 * This is necessary only for the TN1010 basad device because only the
51646835Syc148097 	 * TN1010 supports dual speeds.
51656835Syc148097 	 */
51666835Syc148097 	if (nxgep->mac.portmode == PORT_1G_TN1010 ||
51676835Syc148097 	    nxgep->mac.portmode == PORT_10G_TN1010) {
51686835Syc148097 
51696835Syc148097 		(void) nxge_set_tn1010_param(nxgep);
51706835Syc148097 
51716835Syc148097 		/*
51726835Syc148097 		 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets
51736835Syc148097 		 * nxgep->portmode) and nxge_setup_xcvr_table (which sets
51746835Syc148097 		 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
51756835Syc148097 		 */
51766835Syc148097 		if (nxge_xcvr_find(nxgep) != NXGE_OK) {
51776835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51786835Syc148097 			    "nxge_link_is_up: nxge_xcvr_find failed"));
51796835Syc148097 		}
51806835Syc148097 
51816835Syc148097 		/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
51826835Syc148097 		if (nxge_link_init(nxgep) != NXGE_OK) {
51836835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51846835Syc148097 			    "nxge_link_is_up: nxge_link_init failed"));
51856835Syc148097 		}
51866835Syc148097 
51876835Syc148097 		/*
51886835Syc148097 		 * nxge_mac_init calls many subroutines including
51896835Syc148097 		 * nxge_xif_init which sets XGMII or GMII mode
51906835Syc148097 		 */
51916835Syc148097 		if (nxge_mac_init(nxgep) != NXGE_OK) {
51926835Syc148097 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
51936835Syc148097 			    "nxge_link_is_up: nxge_mac_init failed"));
51946835Syc148097 		}
51956835Syc148097 	} else {
51966835Syc148097 		(void) nxge_xif_init(nxgep);
51976835Syc148097 	}
51986835Syc148097 
51994732Sdavemq 	if (nxge_no_msg == B_FALSE) {
52004732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
52014732Sdavemq 	}
52024732Sdavemq 
52033859Sml29623 	mac_link_update(nxgep->mach, LINK_STATE_UP);
52043859Sml29623 
52053859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
52063859Sml29623 }
52073859Sml29623 
52086835Syc148097 #ifdef NXGE_DEBUG
52096835Syc148097 /* Dump all TN1010 Status registers */
52106835Syc148097 static void
52116835Syc148097 nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
52126835Syc148097 {
52136835Syc148097 	uint16_t val;
52146835Syc148097 
52156835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52166835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 1, &val);
52176835Syc148097 	cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
52186835Syc148097 
52196835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52206835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 8, &val);
52216835Syc148097 	cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
52226835Syc148097 
52236835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52246835Syc148097 	    TN1010_PMA_PMD_DEV_ADDR, 129, &val);
52256835Syc148097 	cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
52266835Syc148097 
52276835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52286835Syc148097 	    TN1010_PCS_DEV_ADDR, 1, &val);
52296835Syc148097 	cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
52306835Syc148097 
52316835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52326835Syc148097 	    TN1010_PCS_DEV_ADDR, 8, &val);
52336835Syc148097 	cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
52346835Syc148097 
52356835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52366835Syc148097 	    TN1010_PCS_DEV_ADDR, 32, &val);
52376835Syc148097 	cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
52386835Syc148097 
52396835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52406835Syc148097 	    TN1010_PCS_DEV_ADDR, 33, &val);
52416835Syc148097 	cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
52426835Syc148097 
52436835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52446835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 1, &val);
52456835Syc148097 	cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
52466835Syc148097 
52476835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52486835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 8, &val);
52496835Syc148097 	cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
52506835Syc148097 
52516835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52526835Syc148097 	    TN1010_PHYXS_DEV_ADDR, 24, &val);
52536835Syc148097 	cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
52546835Syc148097 
52556835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52566835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 1, &val);
52576835Syc148097 	cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
52586835Syc148097 
52596835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52606835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, 33, &val);
52616835Syc148097 	cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
52626835Syc148097 
52636835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52646835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
52656835Syc148097 	cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
52666835Syc148097 
52676835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52686835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
52696835Syc148097 	cmn_err(CE_NOTE, "Device status = 0x%x", val);
52706835Syc148097 
52716835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52726835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
52736835Syc148097 	cmn_err(CE_NOTE, "DDR status = 0x%x", val);
52746835Syc148097 
52756835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52766835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
52776835Syc148097 	cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
52786835Syc148097 
52796835Syc148097 	nxge_mdio_read(nxgep, nxgep->xcvr_addr,
52806835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
52816835Syc148097 	cmn_err(CE_NOTE, "Firmware Revision = 0x%x  Major = 0x%x Minor = 0x%x",
52826835Syc148097 	    val,  (val & 0xFF00) >> 8, val & 0x00FF);
52836835Syc148097 }
52846835Syc148097 #endif
52856835Syc148097 
52863859Sml29623 /*
52873859Sml29623  * Calculate the bit in the multicast address filter
52883859Sml29623  * that selects the given * address.
52893859Sml29623  * Note: For GEM, the last 8-bits are used.
52903859Sml29623  */
52913859Sml29623 uint32_t
52923859Sml29623 crc32_mchash(p_ether_addr_t addr)
52933859Sml29623 {
52943859Sml29623 	uint8_t *cp;
52953859Sml29623 	uint32_t crc;
52963859Sml29623 	uint32_t c;
52973859Sml29623 	int byte;
52983859Sml29623 	int bit;
52993859Sml29623 
53003859Sml29623 	cp = (uint8_t *)addr;
53013859Sml29623 	crc = (uint32_t)0xffffffff;
53023859Sml29623 	for (byte = 0; byte < 6; byte++) {
53033859Sml29623 		c = (uint32_t)cp[byte];
53043859Sml29623 		for (bit = 0; bit < 8; bit++) {
53053859Sml29623 			if ((c & 0x1) ^ (crc & 0x1))
53063859Sml29623 				crc = (crc >> 1)^0xedb88320;
53073859Sml29623 			else
53083859Sml29623 				crc = (crc >> 1);
53093859Sml29623 			c >>= 1;
53103859Sml29623 		}
53113859Sml29623 	}
53123859Sml29623 	return ((~crc) >> (32 - HASH_BITS));
53133859Sml29623 }
53143859Sml29623 
53153859Sml29623 /* Reset serdes */
53163859Sml29623 
53173859Sml29623 nxge_status_t
53183859Sml29623 nxge_serdes_reset(p_nxge_t nxgep)
53193859Sml29623 {
53203859Sml29623 	npi_handle_t		handle;
53213859Sml29623 
53223859Sml29623 	handle = nxgep->npi_handle;
53233859Sml29623 
53243859Sml29623 	ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
53253859Sml29623 	drv_usecwait(500);
53263859Sml29623 	ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
53273859Sml29623 
53283859Sml29623 	return (NXGE_OK);
53293859Sml29623 }
53303859Sml29623 
53316835Syc148097 /*
53326835Syc148097  * This function monitors link status using interrupt or polling.
53336835Syc148097  * It calls nxgep->xcvr.check_link, a member function of
53346835Syc148097  * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
53356835Syc148097  * function back, that is why the check_link routine is
53366835Syc148097  * executed periodically.
53376835Syc148097  */
53383859Sml29623 nxge_status_t
53393859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
53403859Sml29623 {
53413859Sml29623 	nxge_status_t status = NXGE_OK;
53423859Sml29623 
53436495Sspeer 	/* If we are a guest domain driver, don't bother. */
53446495Sspeer 	if (isLDOMguest(nxgep))
53456495Sspeer 		return (status);
53466495Sspeer 
53473859Sml29623 	/*
53484693Stm144005 	 * Return immediately if this is an imaginary XMAC port.
53494693Stm144005 	 * (At least, we don't have 4-port XMAC cards yet.)
53503859Sml29623 	 */
53514977Sraghus 	if ((nxgep->mac.portmode == PORT_10G_FIBER ||
53524977Sraghus 	    nxgep->mac.portmode == PORT_10G_SERDES) &&
53534977Sraghus 	    (nxgep->mac.portnum > 1))
53543859Sml29623 		return (NXGE_OK);
53553859Sml29623 
53563859Sml29623 	if (nxgep->statsp == NULL) {
53573859Sml29623 		/* stats has not been allocated. */
53583859Sml29623 		return (NXGE_OK);
53593859Sml29623 	}
53606075Ssbehera 	/* Don't check link if we're in internal loopback mode */
53616075Ssbehera 	if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
53623859Sml29623 		return (NXGE_OK);
53633859Sml29623 
53643859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
53654693Stm144005 	    "==> nxge_link_monitor port<%d> enable=%d",
53664693Stm144005 	    nxgep->mac.portnum, enable));
53673859Sml29623 	if (enable == LINK_MONITOR_START) {
53683859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
53693859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
53704693Stm144005 			    != NXGE_OK)
53713859Sml29623 				goto fail;
53723859Sml29623 		} else {
53734693Stm144005 			timeout_id_t timerid;
53746835Syc148097 			/*
53756835Syc148097 			 * check_link_stop means "Stop the link check", so
53766835Syc148097 			 * we return without starting the timer.
53776835Syc148097 			 */
53784693Stm144005 			if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
53794693Stm144005 				return (NXGE_OK);
53804693Stm144005 
53816835Syc148097 			/*
53826835Syc148097 			 * Otherwise fire the timer for the nxge to check
53836835Syc148097 			 * the link using the check_link function
53846835Syc148097 			 * of the nxge_xcvr_table and pass "nxgep" as the
53856835Syc148097 			 * argument to the check_link function.
53866835Syc148097 			 */
53874732Sdavemq 			if (nxgep->xcvr.check_link) {
53884732Sdavemq 				timerid = timeout(
53894732Sdavemq 				    (fptrv_t)(nxgep->xcvr.check_link),
53904693Stm144005 				    nxgep,
53914693Stm144005 				    drv_usectohz(LINK_MONITOR_PERIOD));
53924732Sdavemq 				MUTEX_ENTER(&nxgep->poll_lock);
53934732Sdavemq 				nxgep->nxge_link_poll_timerid = timerid;
53944732Sdavemq 				MUTEX_EXIT(&nxgep->poll_lock);
53954732Sdavemq 			} else {
53964693Stm144005 				return (NXGE_ERROR);
53973859Sml29623 			}
53983859Sml29623 		}
53993859Sml29623 	} else {
54003859Sml29623 		if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
54013859Sml29623 			if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
54024693Stm144005 			    != NXGE_OK)
54033859Sml29623 				goto fail;
54043859Sml29623 		} else {
54054693Stm144005 			clock_t rv;
54064693Stm144005 
54074693Stm144005 			MUTEX_ENTER(&nxgep->poll_lock);
54084693Stm144005 
54094693Stm144005 			/* If <timerid> == 0, the link monitor has */
54104693Stm144005 			/* never been started, or just now stopped. */
54114693Stm144005 			if (nxgep->nxge_link_poll_timerid == 0) {
54124693Stm144005 				MUTEX_EXIT(&nxgep->poll_lock);
54134693Stm144005 				return (NXGE_OK);
54144693Stm144005 			}
54154693Stm144005 
54164693Stm144005 			nxgep->poll_state = LINK_MONITOR_STOPPING;
54174693Stm144005 			rv = cv_timedwait(&nxgep->poll_cv,
54184693Stm144005 			    &nxgep->poll_lock,
54194693Stm144005 			    ddi_get_lbolt() +
54204693Stm144005 			    drv_usectohz(LM_WAIT_MULTIPLIER *
54214693Stm144005 			    LINK_MONITOR_PERIOD));
54224693Stm144005 			if (rv == -1) {
54234693Stm144005 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54244693Stm144005 				    "==> stopping port %d: "
54254693Stm144005 				    "cv_timedwait(%d) timed out",
54264693Stm144005 				    nxgep->mac.portnum, nxgep->poll_state));
54274693Stm144005 				nxgep->poll_state = LINK_MONITOR_STOP;
54283859Sml29623 				nxgep->nxge_link_poll_timerid = 0;
54293859Sml29623 			}
54304693Stm144005 
54314693Stm144005 			MUTEX_EXIT(&nxgep->poll_lock);
54323859Sml29623 		}
54333859Sml29623 	}
54343859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
54354693Stm144005 	    "<== nxge_link_monitor port<%d> enable=%d",
54364693Stm144005 	    nxgep->mac.portnum, enable));
54376495Sspeer 
54383859Sml29623 	return (NXGE_OK);
54393859Sml29623 fail:
54403859Sml29623 	return (status);
54416835Syc148097 
54423859Sml29623 }
54433859Sml29623 
54446835Syc148097 nxge_status_t
54456835Syc148097 nxge_check_tn1010_link(p_nxge_t nxgep)
54466835Syc148097 {
54476835Syc148097 	nxge_status_t	status = NXGE_OK;
54486835Syc148097 	nxge_link_state_t link_up;
54496835Syc148097 
54506835Syc148097 	if (nxgep->nxge_magic != NXGE_MAGIC) {
54516835Syc148097 		/* magic is 0 if driver is not attached */
54526835Syc148097 		return (NXGE_ERROR);
54536835Syc148097 	}
54546835Syc148097 
54556835Syc148097 	/* Link has been stopped, no need to continue */
54566835Syc148097 	if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
54576835Syc148097 		return (NXGE_OK);
54586835Syc148097 	}
54596835Syc148097 
54606835Syc148097 	if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
54616835Syc148097 		goto nxge_check_tn1010_link_exit;
54626835Syc148097 
54636835Syc148097 	if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
54646835Syc148097 		goto fail;
54656835Syc148097 
54666835Syc148097 nxge_check_tn1010_link_exit:
54676835Syc148097 	if (link_up == LINK_IS_UP)
54686835Syc148097 		nxge_link_is_up(nxgep);
54696835Syc148097 	else if (link_up == LINK_IS_DOWN)
54706835Syc148097 		nxge_link_is_down(nxgep);
54716835Syc148097 
54726835Syc148097 	/*
54736835Syc148097 	 * nxge_link_monitor will call (nxgep->xcvr.check_link)
54746835Syc148097 	 * which could be THIS function.
54756835Syc148097 	 */
54766835Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
54776835Syc148097 
54786835Syc148097 	return (NXGE_OK);
54796835Syc148097 
54806835Syc148097 fail:
54816835Syc148097 	(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
54826835Syc148097 
54836835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
54846835Syc148097 	    "nxge_check_tn1010_link: Failed to check link"));
54856835Syc148097 	return (status);
54866835Syc148097 }
54876835Syc148097 
54886835Syc148097 
54896835Syc148097 /*
54906835Syc148097  * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
54916835Syc148097  */
54926835Syc148097 static nxge_status_t
54936835Syc148097 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
54946835Syc148097 {
54956835Syc148097 	nxge_status_t	status = NXGE_OK;
54966835Syc148097 	p_nxge_stats_t	statsp;
54976835Syc148097 	uint8_t		phy_port_addr, portn;
54986835Syc148097 	uint16_t	val;
54996835Syc148097 
55006835Syc148097 	*link_up = LINK_NO_CHANGE;
55016835Syc148097 
55026835Syc148097 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
55036835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
55046835Syc148097 	statsp = nxgep->statsp;
55056835Syc148097 
55066835Syc148097 	/* Check if link is up */
55076835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
55086835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
55096835Syc148097 	    != NXGE_OK) {
55106835Syc148097 		goto fail;
55116835Syc148097 	}
55126835Syc148097 	/*
55136835Syc148097 	 * nxge_link_is_up has called nxge_set_tn1010_param and set
55146835Syc148097 	 * portmode and link_speed
55156835Syc148097 	 */
55166835Syc148097 	if (val & TN1010_AN_LINK_STAT_BIT) {
55176835Syc148097 		if (nxgep->link_notify ||
55186835Syc148097 		    nxgep->statsp->mac_stats.link_up == 0) {
55196835Syc148097 			statsp->mac_stats.link_up = 1;
55206835Syc148097 			statsp->mac_stats.link_duplex = 2;
55216835Syc148097 			*link_up = LINK_IS_UP;
55226835Syc148097 			nxgep->link_notify = B_FALSE;
55236835Syc148097 		}
55246835Syc148097 	} else {
55256835Syc148097 		if (nxgep->link_notify ||
55266835Syc148097 		    nxgep->statsp->mac_stats.link_up == 1) {
55276835Syc148097 			statsp->mac_stats.link_up = 0;
55286835Syc148097 			statsp->mac_stats.link_speed = 0;
55296835Syc148097 			statsp->mac_stats.link_duplex = 0;
55306835Syc148097 			*link_up = LINK_IS_DOWN;
55316835Syc148097 			nxgep->link_notify = B_FALSE;
55326835Syc148097 		}
55336835Syc148097 	}
55346835Syc148097 	return (NXGE_OK);
55356835Syc148097 
55366835Syc148097 fail:
55376835Syc148097 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
55386835Syc148097 	    "nxge_tn1010_check: Unable to check TN1010"));
55396835Syc148097 	return (status);
55406835Syc148097 }
55416835Syc148097 
55426835Syc148097 
55433859Sml29623 /* Set promiscous mode */
55443859Sml29623 
55453859Sml29623 nxge_status_t
55463859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
55473859Sml29623 {
55483859Sml29623 	nxge_status_t status = NXGE_OK;
55493859Sml29623 
55504732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
55513859Sml29623 
55523859Sml29623 	nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
55533859Sml29623 
55543859Sml29623 	RW_ENTER_WRITER(&nxgep->filter_lock);
55553859Sml29623 
55563859Sml29623 	if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
55573859Sml29623 		goto fail;
55583859Sml29623 	}
55593859Sml29623 	if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
55603859Sml29623 		goto fail;
55613859Sml29623 	}
55623859Sml29623 
55633859Sml29623 	RW_EXIT(&nxgep->filter_lock);
55643859Sml29623 
55653859Sml29623 	if (on)
55663859Sml29623 		nxgep->statsp->mac_stats.promisc = B_TRUE;
55673859Sml29623 	else
55683859Sml29623 		nxgep->statsp->mac_stats.promisc = B_FALSE;
55693859Sml29623 
55703859Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
55713859Sml29623 
55723859Sml29623 	return (NXGE_OK);
55733859Sml29623 fail:
55743859Sml29623 	RW_EXIT(&nxgep->filter_lock);
55753859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
55764732Sdavemq 	    "Unable to set promisc (%d)", on));
55773859Sml29623 
55783859Sml29623 	return (status);
55793859Sml29623 }
55803859Sml29623 
55813859Sml29623 /*ARGSUSED*/
55823859Sml29623 uint_t
55833859Sml29623 nxge_mif_intr(void *arg1, void *arg2)
55843859Sml29623 {
55853859Sml29623 #ifdef	NXGE_DEBUG
55863859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
55873859Sml29623 #endif
55883859Sml29623 #if NXGE_MIF
55893859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
55903859Sml29623 	uint32_t		status;
55913859Sml29623 	npi_handle_t		handle;
55923859Sml29623 	uint8_t			portn;
55933859Sml29623 	p_nxge_stats_t		statsp;
55943859Sml29623 #endif
55953859Sml29623 
55963859Sml29623 #ifdef	NXGE_MIF
55973859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
55983859Sml29623 		nxgep = ldvp->nxgep;
55993859Sml29623 	}
56003859Sml29623 	nxgep = ldvp->nxgep;
56013859Sml29623 #endif
56023859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr"));
56033859Sml29623 
56043859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
56053859Sml29623 	return (DDI_INTR_CLAIMED);
56063859Sml29623 
56073859Sml29623 mif_intr_fail:
56083859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
56093859Sml29623 	return (DDI_INTR_UNCLAIMED);
56103859Sml29623 }
56113859Sml29623 
56123859Sml29623 /*ARGSUSED*/
56133859Sml29623 uint_t
56143859Sml29623 nxge_mac_intr(void *arg1, void *arg2)
56153859Sml29623 {
56163859Sml29623 	p_nxge_t		nxgep = (p_nxge_t)arg2;
56173859Sml29623 	p_nxge_ldv_t		ldvp = (p_nxge_ldv_t)arg1;
56183859Sml29623 	p_nxge_ldg_t		ldgp;
56193859Sml29623 	uint32_t		status;
56203859Sml29623 	npi_handle_t		handle;
56213859Sml29623 	uint8_t			portn;
56223859Sml29623 	p_nxge_stats_t		statsp;
56233859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
56243859Sml29623 
56253859Sml29623 	if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
56263859Sml29623 		nxgep = ldvp->nxgep;
56273859Sml29623 	}
56283859Sml29623 
56293859Sml29623 	ldgp = ldvp->ldgp;
56303859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
56314732Sdavemq 	    "group %d", ldgp->ldg));
56323859Sml29623 
56333859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
56343859Sml29623 	/*
56353859Sml29623 	 * This interrupt handler is for a specific
56363859Sml29623 	 * mac port.
56373859Sml29623 	 */
56383859Sml29623 	statsp = (p_nxge_stats_t)nxgep->statsp;
56393859Sml29623 	portn = nxgep->mac.portnum;
56403859Sml29623 
56413859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL,
56424732Sdavemq 	    "==> nxge_mac_intr: reading mac stats: port<%d>", portn));
56433859Sml29623 
56443859Sml29623 	if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
56453859Sml29623 		rs = npi_xmac_tx_get_istatus(handle, portn,
56466929Smisaki 		    (xmac_tx_iconfig_t *)&status);
56473859Sml29623 		if (rs != NPI_SUCCESS)
56483859Sml29623 			goto npi_fail;
56493859Sml29623 		if (status & ICFG_XMAC_TX_ALL) {
56503859Sml29623 			if (status & ICFG_XMAC_TX_UNDERRUN) {
56513859Sml29623 				statsp->xmac_stats.tx_underflow_err++;
56523859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
56536929Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
56543859Sml29623 			}
56553859Sml29623 			if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
56563859Sml29623 				statsp->xmac_stats.tx_maxpktsize_err++;
56575523Syc148097 				/*
56585523Syc148097 				 * Do not send FMA ereport because this
56595523Syc148097 				 * error does not indicate HW failure.
56605523Syc148097 				 */
56613859Sml29623 			}
56623859Sml29623 			if (status & ICFG_XMAC_TX_OVERFLOW) {
56633859Sml29623 				statsp->xmac_stats.tx_overflow_err++;
56643859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
56656929Smisaki 				    NXGE_FM_EREPORT_TXMAC_OVERFLOW);
56663859Sml29623 			}
56673859Sml29623 			if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
56683859Sml29623 				statsp->xmac_stats.tx_fifo_xfr_err++;
56693859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
56706929Smisaki 				    NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
56713859Sml29623 			}
56723859Sml29623 			if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
56733859Sml29623 				statsp->xmac_stats.tx_byte_cnt +=
56746929Smisaki 				    XTXMAC_BYTE_CNT_MASK;
56753859Sml29623 			}
56763859Sml29623 			if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
56773859Sml29623 				statsp->xmac_stats.tx_frame_cnt +=
56786929Smisaki 				    XTXMAC_FRM_CNT_MASK;
56793859Sml29623 			}
56803859Sml29623 		}
56813859Sml29623 
56823859Sml29623 		rs = npi_xmac_rx_get_istatus(handle, portn,
56836929Smisaki 		    (xmac_rx_iconfig_t *)&status);
56843859Sml29623 		if (rs != NPI_SUCCESS)
56853859Sml29623 			goto npi_fail;
56863859Sml29623 		if (status & ICFG_XMAC_RX_ALL) {
56873859Sml29623 			if (status & ICFG_XMAC_RX_OVERFLOW)
56883859Sml29623 				statsp->xmac_stats.rx_overflow_err++;
56893859Sml29623 			if (status & ICFG_XMAC_RX_UNDERFLOW) {
56903859Sml29623 				statsp->xmac_stats.rx_underflow_err++;
56913859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
56926929Smisaki 				    NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
56933859Sml29623 			}
56945523Syc148097 			/*
56955523Syc148097 			 * Do not send FMA ereport for the following 3 errors
56965523Syc148097 			 * because they do not indicate HW failures.
56975523Syc148097 			 */
56983859Sml29623 			if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
56993859Sml29623 				statsp->xmac_stats.rx_crc_err_cnt +=
57006929Smisaki 				    XRXMAC_CRC_ER_CNT_MASK;
57013859Sml29623 			}
57023859Sml29623 			if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
57033859Sml29623 				statsp->xmac_stats.rx_len_err_cnt +=
57046929Smisaki 				    MAC_LEN_ER_CNT_MASK;
57053859Sml29623 			}
57063859Sml29623 			if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
57073859Sml29623 				statsp->xmac_stats.rx_viol_err_cnt +=
57086929Smisaki 				    XRXMAC_CD_VIO_CNT_MASK;
57093859Sml29623 			}
57103859Sml29623 			if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
57113859Sml29623 				statsp->xmac_stats.rx_byte_cnt +=
57126929Smisaki 				    XRXMAC_BT_CNT_MASK;
57133859Sml29623 			}
57143859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
57153859Sml29623 				statsp->xmac_stats.rx_hist1_cnt +=
57166929Smisaki 				    XRXMAC_HIST_CNT1_MASK;
57173859Sml29623 			}
57183859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
57193859Sml29623 				statsp->xmac_stats.rx_hist2_cnt +=
57206929Smisaki 				    XRXMAC_HIST_CNT2_MASK;
57213859Sml29623 			}
57223859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
57233859Sml29623 				statsp->xmac_stats.rx_hist3_cnt +=
57246929Smisaki 				    XRXMAC_HIST_CNT3_MASK;
57253859Sml29623 			}
57263859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
57273859Sml29623 				statsp->xmac_stats.rx_hist4_cnt +=
57286929Smisaki 				    XRXMAC_HIST_CNT4_MASK;
57293859Sml29623 			}
57303859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
57313859Sml29623 				statsp->xmac_stats.rx_hist5_cnt +=
57326929Smisaki 				    XRXMAC_HIST_CNT5_MASK;
57333859Sml29623 			}
57343859Sml29623 			if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
57353859Sml29623 				statsp->xmac_stats.rx_hist6_cnt +=
57366929Smisaki 				    XRXMAC_HIST_CNT6_MASK;
57373859Sml29623 			}
57383859Sml29623 			if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
57393859Sml29623 				statsp->xmac_stats.rx_broadcast_cnt +=
57406929Smisaki 				    XRXMAC_BC_FRM_CNT_MASK;
57413859Sml29623 			}
57423859Sml29623 			if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
57433859Sml29623 				statsp->xmac_stats.rx_mult_cnt +=
57446929Smisaki 				    XRXMAC_MC_FRM_CNT_MASK;
57453859Sml29623 			}
57465523Syc148097 			/*
57475523Syc148097 			 * Do not send FMA ereport for the following 3 errors
57485523Syc148097 			 * because they do not indicate HW failures.
57495523Syc148097 			 */
57503859Sml29623 			if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
57513859Sml29623 				statsp->xmac_stats.rx_frag_cnt +=
57526929Smisaki 				    XRXMAC_FRAG_CNT_MASK;
57533859Sml29623 			}
57543859Sml29623 			if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
57553859Sml29623 				statsp->xmac_stats.rx_frame_align_err_cnt +=
57566929Smisaki 				    XRXMAC_AL_ER_CNT_MASK;
57573859Sml29623 			}
57583859Sml29623 			if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
57593859Sml29623 				statsp->xmac_stats.rx_linkfault_err_cnt +=
57606929Smisaki 				    XMAC_LINK_FLT_CNT_MASK;
57613859Sml29623 			}
57623859Sml29623 			if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
57633859Sml29623 				statsp->xmac_stats.rx_remotefault_err++;
57643859Sml29623 			}
57653859Sml29623 			if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
57663859Sml29623 				statsp->xmac_stats.rx_localfault_err++;
57673859Sml29623 			}
57683859Sml29623 		}
57693859Sml29623 
57703859Sml29623 		rs = npi_xmac_ctl_get_istatus(handle, portn,
57716929Smisaki 		    (xmac_ctl_iconfig_t *)&status);
57723859Sml29623 		if (rs != NPI_SUCCESS)
57733859Sml29623 			goto npi_fail;
57743859Sml29623 		if (status & ICFG_XMAC_CTRL_ALL) {
57753859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
57763859Sml29623 				statsp->xmac_stats.rx_pause_cnt++;
57773859Sml29623 			if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
57783859Sml29623 				statsp->xmac_stats.tx_pause_state++;
57793859Sml29623 			if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
57803859Sml29623 				statsp->xmac_stats.tx_nopause_state++;
57813859Sml29623 		}
57823859Sml29623 	} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
57833859Sml29623 		rs = npi_bmac_tx_get_istatus(handle, portn,
57846929Smisaki 		    (bmac_tx_iconfig_t *)&status);
57853859Sml29623 		if (rs != NPI_SUCCESS)
57863859Sml29623 			goto npi_fail;
57873859Sml29623 		if (status & ICFG_BMAC_TX_ALL) {
57883859Sml29623 			if (status & ICFG_BMAC_TX_UNDERFLOW) {
57893859Sml29623 				statsp->bmac_stats.tx_underrun_err++;
57903859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57916929Smisaki 				    NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
57923859Sml29623 			}
57933859Sml29623 			if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
57943859Sml29623 				statsp->bmac_stats.tx_max_pkt_err++;
57953859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
57966929Smisaki 				    NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
57973859Sml29623 			}
57983859Sml29623 			if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
57993859Sml29623 				statsp->bmac_stats.tx_byte_cnt +=
58006929Smisaki 				    BTXMAC_BYTE_CNT_MASK;
58013859Sml29623 			}
58023859Sml29623 			if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
58033859Sml29623 				statsp->bmac_stats.tx_frame_cnt +=
58046929Smisaki 				    BTXMAC_FRM_CNT_MASK;
58053859Sml29623 			}
58063859Sml29623 		}
58073859Sml29623 
58083859Sml29623 		rs = npi_bmac_rx_get_istatus(handle, portn,
58096929Smisaki 		    (bmac_rx_iconfig_t *)&status);
58103859Sml29623 		if (rs != NPI_SUCCESS)
58113859Sml29623 			goto npi_fail;
58123859Sml29623 		if (status & ICFG_BMAC_RX_ALL) {
58133859Sml29623 			if (status & ICFG_BMAC_RX_OVERFLOW) {
58143859Sml29623 				statsp->bmac_stats.rx_overflow_err++;
58153859Sml29623 			}
58163859Sml29623 			if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
58173859Sml29623 				statsp->bmac_stats.rx_frame_cnt +=
58186929Smisaki 				    RXMAC_FRM_CNT_MASK;
58193859Sml29623 			}
58203859Sml29623 			if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
58213859Sml29623 				statsp->bmac_stats.rx_crc_err_cnt +=
58226929Smisaki 				    BMAC_CRC_ER_CNT_MASK;
58233859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58246929Smisaki 				    NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
58253859Sml29623 			}
58263859Sml29623 			if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
58273859Sml29623 				statsp->bmac_stats.rx_len_err_cnt +=
58286929Smisaki 				    MAC_LEN_ER_CNT_MASK;
58293859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58306929Smisaki 				    NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
58313859Sml29623 			}
58323859Sml29623 			if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP)
58333859Sml29623 				statsp->bmac_stats.rx_viol_err_cnt +=
58346929Smisaki 				    BMAC_CD_VIO_CNT_MASK;
58353859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58366929Smisaki 				    NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
58373859Sml29623 			}
58383859Sml29623 			if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
58393859Sml29623 				statsp->bmac_stats.rx_byte_cnt +=
58406929Smisaki 				    BRXMAC_BYTE_CNT_MASK;
58413859Sml29623 			}
58423859Sml29623 			if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
58433859Sml29623 				statsp->bmac_stats.rx_align_err_cnt +=
58446929Smisaki 				    BMAC_AL_ER_CNT_MASK;
58453859Sml29623 				NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
58466929Smisaki 				    NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
58473859Sml29623 			}
58483859Sml29623 
58493859Sml29623 			rs = npi_bmac_ctl_get_istatus(handle, portn,
58506929Smisaki 			    (bmac_ctl_iconfig_t *)&status);
58513859Sml29623 			if (rs != NPI_SUCCESS)
58523859Sml29623 				goto npi_fail;
58533859Sml29623 
58543859Sml29623 			if (status & ICFG_BMAC_CTL_ALL) {
58553859Sml29623 				if (status & ICFG_BMAC_CTL_RCVPAUSE)
58563859Sml29623 					statsp->bmac_stats.rx_pause_cnt++;
58573859Sml29623 				if (status & ICFG_BMAC_CTL_INPAUSE_ST)
58583859Sml29623 					statsp->bmac_stats.tx_pause_state++;
58593859Sml29623 				if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
58603859Sml29623 					statsp->bmac_stats.tx_nopause_state++;
58613859Sml29623 			}
58623859Sml29623 		}
58633859Sml29623 
58643859Sml29623 	if (ldgp->nldvs == 1) {
58653859Sml29623 		(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
58666929Smisaki 		    B_TRUE, ldgp->ldg_timer);
58673859Sml29623 	}
58683859Sml29623 
58693859Sml29623 	NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
58703859Sml29623 	return (DDI_INTR_CLAIMED);
58713859Sml29623 
58723859Sml29623 npi_fail:
58733859Sml29623 	NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
58743859Sml29623 	return (DDI_INTR_UNCLAIMED);
58753859Sml29623 }
58763859Sml29623 
58773859Sml29623 nxge_status_t
58783859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
58793859Sml29623 {
58803859Sml29623 	uint8_t		phy_port_addr;
58813859Sml29623 	nxge_status_t	status = NXGE_OK;
58823859Sml29623 	boolean_t	rx_sig_ok;
58833859Sml29623 	boolean_t	pcs_blk_lock;
58843859Sml29623 	boolean_t	link_align;
58853859Sml29623 	uint16_t	val1, val2, val3;
58863859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
58873859Sml29623 	uint16_t	val_debug;
58883859Sml29623 	uint16_t	val;
58893859Sml29623 #endif
58903859Sml29623 
58913859Sml29623 	phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
58923859Sml29623 
58933859Sml29623 #ifdef	NXGE_DEBUG_SYMBOL_ERR
58943859Sml29623 	/* Check Device 3 Register Device 3 0xC809 */
58953859Sml29623 	(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
58963859Sml29623 	if ((val_debug & ~0x200) != 0) {
58973859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
58986929Smisaki 		    nxgep->mac.portnum, val_debug);
58993859Sml29623 		(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
59006929Smisaki 		    &val_debug);
59013859Sml29623 		cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
59026929Smisaki 		    nxgep->mac.portnum, val_debug);
59033859Sml29623 	}
59043859Sml29623 
59053859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59066929Smisaki 	    XPCS_REG_DESCWERR_COUNTER, &val);
59073859Sml29623 	if (val != 0)
59083859Sml29623 		cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
59093859Sml29623 
59103859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59116929Smisaki 	    XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
59123859Sml29623 	if (val != 0)
59133859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
59143859Sml29623 
59153859Sml29623 	(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
59166929Smisaki 	    XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
59173859Sml29623 	if (val != 0)
59183859Sml29623 		cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
59193859Sml29623 #endif
59203859Sml29623 
59213859Sml29623 	/* Check from BCM8704 if 10G link is up or down */
59223859Sml29623 
59233859Sml29623 	/* Check Device 1 Register 0xA bit0 */
59246929Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
59256929Smisaki 	    BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
59263859Sml29623 	if (status != NXGE_OK)
59273859Sml29623 		goto fail;
59283859Sml29623 	rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
59293859Sml29623 
59303859Sml29623 	/* Check Device 3 Register 0x20 bit0 */
59316929Smisaki 	if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
59326929Smisaki 	    BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
59333859Sml29623 		goto fail;
59343859Sml29623 	pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
59353859Sml29623 
59363859Sml29623 	/* Check Device 4 Register 0x18 bit12 */
59376929Smisaki 	status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
59386929Smisaki 	    BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
59393859Sml29623 	if (status != NXGE_OK)
59403859Sml29623 		goto fail;
59415572Ssbehera 
59425572Ssbehera 	switch (nxgep->chip_id) {
59435572Ssbehera 	case BCM8704_CHIP_ID:
59445572Ssbehera 		link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
59455572Ssbehera 		    XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
59465572Ssbehera 		    XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
59475572Ssbehera 		break;
59485572Ssbehera 	case BCM8706_CHIP_ID:
59495572Ssbehera 		link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
59505572Ssbehera 		    (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
59515572Ssbehera 		    (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
59525572Ssbehera 		    B_TRUE : B_FALSE;
59535572Ssbehera 		break;
59545572Ssbehera 	default:
59555572Ssbehera 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
59565572Ssbehera 		    "Unknown chip ID [0x%x]", nxgep->chip_id));
59575572Ssbehera 		goto fail;
59585572Ssbehera 	}
59595572Ssbehera 
59603859Sml29623 
59613859Sml29623 #ifdef	NXGE_DEBUG_ALIGN_ERR
59623859Sml29623 	/* Temp workaround for link down issue */
59633859Sml29623 	if (pcs_blk_lock == B_FALSE) {
59643859Sml29623 		if (val2 != 0x4) {
59653859Sml29623 			pcs_blk_lock = B_TRUE;
59666929Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
59676929Smisaki 			    "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
59683859Sml29623 		}
59693859Sml29623 	}
59703859Sml29623 
59713859Sml29623 	if (link_align == B_FALSE) {
59723859Sml29623 		if (val3 != 0x140f) {
59733859Sml29623 			link_align = B_TRUE;
59746929Smisaki 			cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
59756929Smisaki 			    "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
59763859Sml29623 		}
59773859Sml29623 	}
59783859Sml29623 
59793859Sml29623 	if (rx_sig_ok == B_FALSE) {
59803859Sml29623 		if ((val2 == 0) || (val3 == 0)) {
59813859Sml29623 			rx_sig_ok = B_TRUE;
59823859Sml29623 			cmn_err(CE_NOTE,
59836929Smisaki 			    "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
59846929Smisaki 			    nxgep->mac.portnum);
59853859Sml29623 		}
59863859Sml29623 	}
59873859Sml29623 #endif
59883859Sml29623 
59893859Sml29623 	*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
59906929Smisaki 	    (link_align == B_TRUE)) ? B_TRUE : B_FALSE;
59913859Sml29623 
59923859Sml29623 	return (NXGE_OK);
59933859Sml29623 fail:
59943859Sml29623 	return (status);
59953859Sml29623 }
59963859Sml29623 
59976604Ssbehera static nxge_status_t
59986835Syc148097 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
59996604Ssbehera {
60006604Ssbehera 	uint8_t		phy;
60016604Ssbehera 	nxge_status_t   status = NXGE_OK;
60026604Ssbehera 	boolean_t	pma_status;
60036604Ssbehera 	boolean_t	pcs_status;
60046604Ssbehera 	boolean_t	xgxs_status;
60056604Ssbehera 	uint16_t	val;
60066604Ssbehera 
60076604Ssbehera 	phy = nxgep->statsp->mac_stats.xcvr_portn;
60086604Ssbehera 
60096604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
60106604Ssbehera 	    MRVL_88X2011_10G_PMD_STAT_2, &val);
60116604Ssbehera 
60126604Ssbehera 	*link_up = B_FALSE;
60136604Ssbehera 
60146604Ssbehera 	/* Check from Marvell 88X2011 if 10G link is up or down */
60156604Ssbehera 
60166604Ssbehera 	/* Check PMA/PMD Register: 1.0001.2 == 1 */
60176604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
60186604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60196604Ssbehera 
60206604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60216604Ssbehera 	    "nxge_check_mrvl88x2011_link: pmd=0x%x", val));
60226604Ssbehera 
60236604Ssbehera 	pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
60246604Ssbehera 
60256604Ssbehera 	/* Check PMC Register : 3.0001.2 == 1: read twice */
60266604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
60276604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60286604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
60296604Ssbehera 	    MRVL_88X2011_PMA_PMD_STAT_1, &val);
60306604Ssbehera 
60316604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60326604Ssbehera 	    "nxge_check_mrvl88x2011_link: pcs=0x%x", val));
60336604Ssbehera 
60346604Ssbehera 	pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
60356604Ssbehera 
60366604Ssbehera 	/* Check XGXS Register : 4.0018.[0-3,12] */
60376604Ssbehera 	MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
60386604Ssbehera 	    MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
60396604Ssbehera 
60406604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60416604Ssbehera 	    "nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
60426604Ssbehera 
60436604Ssbehera 	xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
60446604Ssbehera 	    XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
60456604Ssbehera 	    XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
60466604Ssbehera 	    XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
60476604Ssbehera 
60486604Ssbehera 	*link_up = (pma_status && pcs_status && xgxs_status) ?
60496604Ssbehera 	    B_TRUE : B_FALSE;
60506604Ssbehera 
60516604Ssbehera fail:
60526604Ssbehera 
60536604Ssbehera 	if (*link_up == B_FALSE) {
60546604Ssbehera 		/* PCS OFF */
60556604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
60566604Ssbehera 	} else {
60576604Ssbehera 		/* PCS Activity */
60586604Ssbehera 		nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
60596604Ssbehera 	}
60606604Ssbehera 
60616604Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60626604Ssbehera 	    " <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
60636604Ssbehera 
60646604Ssbehera 	return (status);
60656604Ssbehera }
60666604Ssbehera 
60673859Sml29623 nxge_status_t
60683859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep)
60693859Sml29623 {
60703859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
60714732Sdavemq 	    != NPI_SUCCESS)
60723859Sml29623 		return (NXGE_ERROR);
60733859Sml29623 	else
60743859Sml29623 		return (NXGE_OK);
60753859Sml29623 }
60763859Sml29623 
60773859Sml29623 nxge_status_t
60783859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep)
60793859Sml29623 {
60803859Sml29623 	if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
60814732Sdavemq 	    != NPI_SUCCESS)
60823859Sml29623 		return (NXGE_ERROR);
60833859Sml29623 	else
60843859Sml29623 		return (NXGE_OK);
60853859Sml29623 }
60864185Sspeer 
60875572Ssbehera static boolean_t
60885572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
60895572Ssbehera {
60905572Ssbehera 	uint32_t pma_pmd_id = 0;
60915572Ssbehera 	uint32_t pcs_id = 0;
60925572Ssbehera 	uint32_t phy_id = 0;
60935572Ssbehera 
60945572Ssbehera 	pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
60955572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
60965572Ssbehera 	    "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
60975572Ssbehera 	if ((pma_pmd_id & mask) == (id & mask))
60985572Ssbehera 		goto found_phy;
60995572Ssbehera 	pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
61005572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61015572Ssbehera 	    "nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
61025572Ssbehera 	if ((pcs_id & mask) == (id & mask))
61035572Ssbehera 		goto found_phy;
61045572Ssbehera 	phy_id = nxge_get_cl22_phy_id(nxgep, addr);
61055572Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
61065572Ssbehera 	    "nxge_is_phy_present: phy_id[0x%x]", phy_id));
61075572Ssbehera 	if ((phy_id & mask) == (id & mask))
61085572Ssbehera 		goto found_phy;
61095572Ssbehera 
61105572Ssbehera 	return (B_FALSE);
61115572Ssbehera 
61125572Ssbehera found_phy:
61135572Ssbehera 	return (B_TRUE);
61145572Ssbehera }
61155572Ssbehera 
61164732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */
61174732Sdavemq 
61184732Sdavemq static boolean_t
61194732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type)
61204732Sdavemq {
61214732Sdavemq 	int		i;
61224732Sdavemq 	boolean_t	found = B_FALSE;
61234732Sdavemq 
61244732Sdavemq 	switch (type) {
61254732Sdavemq 	case CLAUSE_45_TYPE:
61266835Syc148097 		for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
61276835Syc148097 			if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
61286835Syc148097 			    (id & BCM_PHY_ID_MASK)) ||
61296835Syc148097 			    (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) {
61304732Sdavemq 				found = B_TRUE;
61314732Sdavemq 				break;
61324732Sdavemq 			}
61334732Sdavemq 		}
61344732Sdavemq 		break;
61354732Sdavemq 	case CLAUSE_22_TYPE:
61366835Syc148097 		for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
61374782Ssbehera 			if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
61384782Ssbehera 			    (id & BCM_PHY_ID_MASK)) {
61394732Sdavemq 				found = B_TRUE;
61404732Sdavemq 				break;
61414732Sdavemq 			}
61424732Sdavemq 		}
61434732Sdavemq 		break;
61444732Sdavemq 	default:
61454732Sdavemq 		break;
61464732Sdavemq 	}
61474732Sdavemq 
61484732Sdavemq 	return (found);
61494732Sdavemq }
61504732Sdavemq 
61514977Sraghus static uint32_t
61524977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
61534977Sraghus {
61544977Sraghus 	uint16_t	val1 = 0;
61554977Sraghus 	uint16_t	val2 = 0;
61564977Sraghus 	uint32_t	pma_pmd_dev_id = 0;
61574977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
61584977Sraghus 
61595780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
61604977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
61614977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
61624977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
61634977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
61645780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
61654977Sraghus 
61666835Syc148097 	/* Concatenate the Device ID stored in two registers. */
61674977Sraghus 	pma_pmd_dev_id = val1;
61684977Sraghus 	pma_pmd_dev_id = (pma_pmd_dev_id << 16);
61694977Sraghus 	pma_pmd_dev_id |= val2;
61704977Sraghus 
61714977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
61724977Sraghus 	    "devid[0x%llx]", phy_port, pma_pmd_dev_id));
61734977Sraghus 
61744977Sraghus 	return (pma_pmd_dev_id);
61754977Sraghus }
61764977Sraghus 
61774977Sraghus static uint32_t
61784977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
61794977Sraghus {
61804977Sraghus 	uint16_t	val1 = 0;
61814977Sraghus 	uint16_t	val2 = 0;
61824977Sraghus 	uint32_t	pcs_dev_id = 0;
61834977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
61844977Sraghus 
61855780Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
61864977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
61874977Sraghus 	    NXGE_DEV_ID_REG_1, &val1);
61884977Sraghus 	(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
61894977Sraghus 	    NXGE_DEV_ID_REG_2, &val2);
61905780Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
61914977Sraghus 
61924977Sraghus 	pcs_dev_id = val1;
61934977Sraghus 	pcs_dev_id = (pcs_dev_id << 16);
61944977Sraghus 	pcs_dev_id |= val2;
61954977Sraghus 
61964977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
61974977Sraghus 	    "devid[0x%llx]", phy_port, pcs_dev_id));
61984977Sraghus 
61994977Sraghus 	return (pcs_dev_id);
62004977Sraghus }
62014977Sraghus 
62024977Sraghus static uint32_t
62034977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
62044977Sraghus {
62054977Sraghus 	uint16_t	val1 = 0;
62064977Sraghus 	uint16_t	val2 = 0;
62074977Sraghus 	uint32_t	phy_id = 0;
62084977Sraghus 	npi_handle_t	handle = NXGE_DEV_NPI_HANDLE(nxgep);
62094977Sraghus 	npi_status_t	npi_status = NPI_SUCCESS;
62104977Sraghus 
62116075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
62124977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
62134977Sraghus 	    &val1);
62144977Sraghus 	if (npi_status != NPI_SUCCESS) {
62154977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62164977Sraghus 		    "clause 22 read to reg 2 failed!!!"));
62174977Sraghus 		goto exit;
62184977Sraghus 	}
62194977Sraghus 	npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
62204977Sraghus 	    &val2);
62214977Sraghus 	if (npi_status != 0) {
62224977Sraghus 		NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62234977Sraghus 		    "clause 22 read to reg 3 failed!!!"));
62244977Sraghus 		goto exit;
62254977Sraghus 	}
62264977Sraghus 	phy_id = val1;
62274977Sraghus 	phy_id = (phy_id << 16);
62284977Sraghus 	phy_id |= val2;
62294977Sraghus 
62304977Sraghus exit:
62316075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
62324977Sraghus 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
62334977Sraghus 	    phy_port, phy_id));
62344977Sraghus 
62354977Sraghus 	return (phy_id);
62364977Sraghus }
62374977Sraghus 
62384732Sdavemq /*
62394732Sdavemq  * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
62404732Sdavemq  * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO
62414732Sdavemq  * read. Then use the values obtained to determine the phy type of each port
62424732Sdavemq  * and the Neptune type.
62436835Syc148097  *
62446835Syc148097  * This function sets hw_p->xcvr_addr[i] for future MDIO access and set
62456835Syc148097  * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
62466835Syc148097  * in case the portmode information is not available via OBP, nxge.conf,
62476835Syc148097  * VPD or SEEPROM.
62484732Sdavemq  */
62494732Sdavemq nxge_status_t
62504732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
62514732Sdavemq {
62526261Sjoycey 	int		i, j, l;
62534732Sdavemq 	uint32_t	pma_pmd_dev_id = 0;
62544732Sdavemq 	uint32_t	pcs_dev_id = 0;
62554732Sdavemq 	uint32_t	phy_id = 0;
62564782Ssbehera 	uint32_t	port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
62574782Ssbehera 	uint32_t	port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
62584782Ssbehera 	uint32_t	port_phy_id[NXGE_PORTS_NEPTUNE];
62594732Sdavemq 	uint8_t		pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
62604732Sdavemq 	uint8_t		pcs_dev_fd[NXGE_MAX_PHY_PORTS];
62615572Ssbehera 	uint8_t		phy_fd_arr[NXGE_MAX_PHY_PORTS];
62625572Ssbehera 	uint8_t		port_fd_arr[NXGE_MAX_PHY_PORTS];
62634732Sdavemq 	uint8_t		total_port_fd, total_phy_fd;
62646835Syc148097 	uint8_t		num_xaui;
62654732Sdavemq 	nxge_status_t	status = NXGE_OK;
62664732Sdavemq 
62674732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
62684732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
62694732Sdavemq 	    "==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
62704732Sdavemq 	    nxgep->niu_type));
62714732Sdavemq 
62726495Sspeer 	if (isLDOMguest(nxgep)) {
62736495Sspeer 		hw_p->niu_type = NIU_TYPE_NONE;
62746495Sspeer 		hw_p->platform_type = P_NEPTUNE_NONE;
62756495Sspeer 		return (NXGE_OK);
62766495Sspeer 	}
62776495Sspeer 
62786261Sjoycey 	j = l = 0;
62794732Sdavemq 	total_port_fd = total_phy_fd = 0;
62804732Sdavemq 	/*
62817801SSantwona.Behera@Sun.COM 	 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved
62827801SSantwona.Behera@Sun.COM 	 * for on chip serdes usages. "i" in the following for loop starts at 6.
62834732Sdavemq 	 */
62844732Sdavemq 	for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
62854977Sraghus 
62864977Sraghus 		pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
62874732Sdavemq 
62884732Sdavemq 		if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
62894732Sdavemq 			pma_pmd_dev_fd[i] = 1;
62904732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
62916604Ssbehera 			    "PMA/PMD dev %x found", i, pma_pmd_dev_id));
62924782Ssbehera 			if (j < NXGE_PORTS_NEPTUNE) {
62936835Syc148097 				if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
62946835Syc148097 				    == TN1010_DEV_ID) {
62956835Syc148097 					port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
62966835Syc148097 				} else {
62976835Syc148097 					port_pma_pmd_dev_id[j] =
62986929Smisaki 					    pma_pmd_dev_id & BCM_PHY_ID_MASK;
62996835Syc148097 				}
63005572Ssbehera 				port_fd_arr[j] = (uint8_t)i;
63014732Sdavemq 				j++;
63024732Sdavemq 			}
63034732Sdavemq 		} else {
63044732Sdavemq 			pma_pmd_dev_fd[i] = 0;
63054732Sdavemq 		}
63064732Sdavemq 
63074977Sraghus 		pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
63084732Sdavemq 
63094732Sdavemq 		if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
63104732Sdavemq 			pcs_dev_fd[i] = 1;
63114732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
63126604Ssbehera 			    "dev %x found", i, pcs_dev_id));
63136261Sjoycey 			if (pma_pmd_dev_fd[i] == 1) {
63146835Syc148097 				if ((pcs_dev_id & TN1010_DEV_ID_MASK)
63156835Syc148097 				    == TN1010_DEV_ID) {
63166835Syc148097 					port_pcs_dev_id[j - 1] =
63176835Syc148097 					    TN1010_DEV_ID;
63186835Syc148097 				} else {
63196835Syc148097 					port_pcs_dev_id[j - 1] =
63206835Syc148097 					    pcs_dev_id &
63216835Syc148097 					    BCM_PHY_ID_MASK;
63226835Syc148097 				}
63236261Sjoycey 			} else {
63246261Sjoycey 				if (j < NXGE_PORTS_NEPTUNE) {
63256835Syc148097 					if ((pcs_dev_id & TN1010_DEV_ID_MASK)
63266929Smisaki 					    == TN1010_DEV_ID) {
63276835Syc148097 						port_pcs_dev_id[j] =
63286835Syc148097 						    TN1010_DEV_ID;
63296835Syc148097 					} else {
63306835Syc148097 						port_pcs_dev_id[j] =
63316835Syc148097 						    pcs_dev_id &
63326835Syc148097 						    BCM_PHY_ID_MASK;
63336835Syc148097 					}
63346261Sjoycey 					port_fd_arr[j] = (uint8_t)i;
63356261Sjoycey 					j++;
63366261Sjoycey 				}
63374732Sdavemq 			}
63384732Sdavemq 		} else {
63394732Sdavemq 			pcs_dev_fd[i] = 0;
63404732Sdavemq 		}
63414732Sdavemq 
63425572Ssbehera 		if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
63435572Ssbehera 			total_port_fd ++;
63445572Ssbehera 		}
63454732Sdavemq 
63464977Sraghus 		phy_id = nxge_get_cl22_phy_id(nxgep, i);
63474732Sdavemq 		if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
63485572Ssbehera 			total_phy_fd ++;
63494732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
63506604Ssbehera 			    "%x found", i, phy_id));
63514782Ssbehera 			if (l < NXGE_PORTS_NEPTUNE) {
63526835Syc148097 				if ((phy_id & TN1010_DEV_ID_MASK)
63536835Syc148097 				    == TN1010_DEV_ID) {
63546835Syc148097 					port_phy_id[l] = TN1010_DEV_ID;
63556835Syc148097 				} else {
63566835Syc148097 					port_phy_id[l]
63576835Syc148097 					    = phy_id & BCM_PHY_ID_MASK;
63586835Syc148097 				}
63595572Ssbehera 				phy_fd_arr[l] = (uint8_t)i;
63604732Sdavemq 				l++;
63614732Sdavemq 			}
63624732Sdavemq 		}
63634732Sdavemq 	}
63644732Sdavemq 
63654732Sdavemq 	switch (total_port_fd) {
63664732Sdavemq 	case 2:
63674732Sdavemq 		switch (total_phy_fd) {
63684732Sdavemq 		case 2:
63697801SSantwona.Behera@Sun.COM 			/* 2 10G, 2 1G RGMII Fiber / copper */
63706261Sjoycey 			if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
63716261Sjoycey 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
63726261Sjoycey 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
63736261Sjoycey 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
63746261Sjoycey 			    ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
63756261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY))) {
63766261Sjoycey 
63777801SSantwona.Behera@Sun.COM 				switch (hw_p->platform_type) {
63787801SSantwona.Behera@Sun.COM 				case P_NEPTUNE_ROCK:
63797801SSantwona.Behera@Sun.COM 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
63807801SSantwona.Behera@Sun.COM 					/*
63817801SSantwona.Behera@Sun.COM 					 * ROCK platform has assigned a lower
63827801SSantwona.Behera@Sun.COM 					 * addr to port 1. (port 0 = 0x9 and
63837801SSantwona.Behera@Sun.COM 					 * port 1 = 0x8).
63847801SSantwona.Behera@Sun.COM 					 */
63857801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[1] = port_fd_arr[0];
63867801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[0] = port_fd_arr[1];
63877801SSantwona.Behera@Sun.COM 
63887801SSantwona.Behera@Sun.COM 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
63897801SSantwona.Behera@Sun.COM 					    "Rock with 2 10G, 2 1GC"));
63907801SSantwona.Behera@Sun.COM 					break;
63917801SSantwona.Behera@Sun.COM 
63927801SSantwona.Behera@Sun.COM 				case P_NEPTUNE_NONE:
63937801SSantwona.Behera@Sun.COM 				default:
63947801SSantwona.Behera@Sun.COM 					hw_p->platform_type =
63957801SSantwona.Behera@Sun.COM 					    P_NEPTUNE_GENERIC;
63967801SSantwona.Behera@Sun.COM 					hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
63977801SSantwona.Behera@Sun.COM 
63987801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[0] = port_fd_arr[0];
63997801SSantwona.Behera@Sun.COM 					hw_p->xcvr_addr[1] = port_fd_arr[1];
64007801SSantwona.Behera@Sun.COM 
64017801SSantwona.Behera@Sun.COM 					NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64027801SSantwona.Behera@Sun.COM 					    "ARTM card with 2 10G, 2 1GF"));
64037801SSantwona.Behera@Sun.COM 					break;
64047801SSantwona.Behera@Sun.COM 				}
64057801SSantwona.Behera@Sun.COM 
64066261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
64076261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
64086261Sjoycey 
64096261Sjoycey 			} else {
64106261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64116261Sjoycey 				    "Unsupported neptune type 1"));
64126261Sjoycey 				goto error_exit;
64136261Sjoycey 			}
64146261Sjoycey 			break;
64156261Sjoycey 
64164732Sdavemq 		case 1:
64174732Sdavemq 			/* TODO - 2 10G, 1 1G */
64184732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
64194732Sdavemq 			    "Unsupported neptune type 2 10G, 1 1G"));
64204732Sdavemq 			goto error_exit;
64214732Sdavemq 		case 0:
64226835Syc148097 			/*
64236835Syc148097 			 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
64246835Syc148097 			 * cards, etc.
64256835Syc148097 			 */
64264782Ssbehera 			if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
64274782Ssbehera 			    (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
64284782Ssbehera 			    ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
64296604Ssbehera 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
64306604Ssbehera 			    ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
64316604Ssbehera 			    (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
64326604Ssbehera 			    ((port_pma_pmd_dev_id[0] ==
64336604Ssbehera 			    MARVELL_88X201X_PHY_ID) &&
64346604Ssbehera 			    (port_pma_pmd_dev_id[1] ==
64356604Ssbehera 			    MARVELL_88X201X_PHY_ID))) {
64364977Sraghus 
64374977Sraghus 				/*
64384977Sraghus 				 * Check the first phy port address against
64394977Sraghus 				 * the known phy start addresses to determine
64404977Sraghus 				 * the platform type.
64414977Sraghus 				 */
64425572Ssbehera 
64435572Ssbehera 				switch (port_fd_arr[0]) {
64446835Syc148097 				case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
64456604Ssbehera 					/*
64466604Ssbehera 					 * The Marvell case also falls into
64476604Ssbehera 					 * this case as
64486604Ssbehera 					 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
64496835Syc148097 					 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
64506604Ssbehera 					 * This is OK for the 2 10G case.
64516604Ssbehera 					 */
64524977Sraghus 					hw_p->niu_type = NEPTUNE_2_10GF;
64534977Sraghus 					hw_p->platform_type =
64544977Sraghus 					    P_NEPTUNE_ATLAS_2PORT;
64555572Ssbehera 					break;
64566835Syc148097 				case GOA_CLAUSE45_PORT_ADDR_BASE:
64575572Ssbehera 					if (hw_p->platform_type !=
64585572Ssbehera 					    P_NEPTUNE_NIU) {
64595572Ssbehera 						hw_p->platform_type =
64605572Ssbehera 						    P_NEPTUNE_GENERIC;
64615572Ssbehera 						hw_p->niu_type =
64625572Ssbehera 						    NEPTUNE_2_10GF;
64635572Ssbehera 					}
64645572Ssbehera 					break;
64655572Ssbehera 				default:
64665572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64674977Sraghus 					    "Unsupported neptune type 2 - 1"));
64684977Sraghus 					goto error_exit;
64694977Sraghus 				}
64705572Ssbehera 
64715572Ssbehera 				for (i = 0; i < 2; i++) {
64725572Ssbehera 					hw_p->xcvr_addr[i] = port_fd_arr[i];
64735572Ssbehera 				}
64746835Syc148097 
64756835Syc148097 			/* Both XAUI slots have copper XAUI cards */
64766835Syc148097 			} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
64776835Syc148097 			    == TN1010_DEV_ID) &&
64786835Syc148097 			    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
64796835Syc148097 			    == TN1010_DEV_ID)) ||
64806835Syc148097 			    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
64816835Syc148097 			    == TN1010_DEV_ID) &&
64826835Syc148097 			    ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
64836835Syc148097 			    == TN1010_DEV_ID))) {
64846835Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010;
64856835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
64866835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
64876835Syc148097 
64886835Syc148097 			/* Slot0 has fiber XAUI, slot1 has copper XAUI */
64896835Syc148097 			} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
64906835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
64916835Syc148097 			    == TN1010_DEV_ID) ||
64926835Syc148097 			    (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
64936835Syc148097 			    (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
64946835Syc148097 			    TN1010_DEV_ID)) {
64956835Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
64966835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
64976835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
64986835Syc148097 
64996835Syc148097 			/* Slot0 has copper XAUI, slot1 has fiber XAUI */
65006835Syc148097 			} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
65016835Syc148097 			    (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
65026835Syc148097 			    == TN1010_DEV_ID) ||
65036835Syc148097 			    (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
65046835Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
65056835Syc148097 			    == TN1010_DEV_ID)) {
65066835Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
65076835Syc148097 				hw_p->xcvr_addr[0] = port_fd_arr[0];
65086835Syc148097 				hw_p->xcvr_addr[1] = port_fd_arr[1];
65096835Syc148097 
65104732Sdavemq 			} else {
65114732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
65124732Sdavemq 				    "Unsupported neptune type 2"));
65134732Sdavemq 				goto error_exit;
65144732Sdavemq 			}
65154732Sdavemq 			break;
65166835Syc148097 
65174732Sdavemq 		case 4:
65186835Syc148097 			if (nxge_get_num_of_xaui(
65196835Syc148097 			    port_pma_pmd_dev_id, port_pcs_dev_id,
65206835Syc148097 			    port_phy_id, &num_xaui) == NXGE_ERROR) {
65216835Syc148097 				goto error_exit;
65226835Syc148097 			}
65236835Syc148097 			if (num_xaui != 2)
65246835Syc148097 				goto error_exit;
65256835Syc148097 
65266835Syc148097 			/*
65276835Syc148097 			 *  Maramba with 2 XAUIs (either fiber or copper)
65286835Syc148097 			 *
65296835Syc148097 			 * Check the first phy port address against
65306835Syc148097 			 * the known phy start addresses to determine
65316835Syc148097 			 * the platform type.
65326835Syc148097 			 */
65336835Syc148097 			switch (phy_fd_arr[0]) {
65346835Syc148097 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
65356835Syc148097 				hw_p->platform_type =
65366835Syc148097 				    P_NEPTUNE_MARAMBA_P0;
65376835Syc148097 				break;
65386835Syc148097 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
65396835Syc148097 				hw_p->platform_type =
65406835Syc148097 				    P_NEPTUNE_MARAMBA_P1;
65416835Syc148097 				break;
65426835Syc148097 			default:
65436835Syc148097 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
65446835Syc148097 				    "Unknown port %d...Cannot "
65456835Syc148097 				    "determine platform type", i));
65466835Syc148097 				goto error_exit;
65476835Syc148097 			}
65486835Syc148097 
65496835Syc148097 			hw_p->xcvr_addr[0] = port_fd_arr[0];
65506835Syc148097 			hw_p->xcvr_addr[1] = port_fd_arr[1];
65516835Syc148097 			hw_p->xcvr_addr[2] = phy_fd_arr[2];
65526835Syc148097 			hw_p->xcvr_addr[3] = phy_fd_arr[3];
65536835Syc148097 
65546835Syc148097 			/* slot0 has fiber XAUI, slot1 has Cu XAUI */
65556835Syc148097 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
65566835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
65576835Syc148097 			    == TN1010_DEV_ID) {
65586835Syc148097 				hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
65596835Syc148097 
65606835Syc148097 			/* slot0 has Cu XAUI, slot1 has fiber XAUI */
65616835Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
65626835Syc148097 			    == TN1010_DEV_ID) &&
65636835Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
65646835Syc148097 				hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
65656835Syc148097 
65666835Syc148097 			/* Both slots have fiber XAUI */
65676835Syc148097 			} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
65686835Syc148097 			    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
65694977Sraghus 				hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
65704977Sraghus 
65716835Syc148097 			/* Both slots have copper XAUI */
65726835Syc148097 			} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
65736835Syc148097 			    == TN1010_DEV_ID) &&
65746835Syc148097 			    (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
65756835Syc148097 			    == TN1010_DEV_ID) {
65766835Syc148097 				hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
65776835Syc148097 
65784732Sdavemq 			} else {
65794732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
65804732Sdavemq 				    "Unsupported neptune type 3"));
65814732Sdavemq 				goto error_exit;
65824732Sdavemq 			}
65834732Sdavemq 			break;
65844732Sdavemq 		default:
65854732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
65864732Sdavemq 			    "Unsupported neptune type 5"));
65874732Sdavemq 			goto error_exit;
65884732Sdavemq 		}
65894782Ssbehera 		break;
65906835Syc148097 	case 1: 	/* Only one clause45 port */
65916835Syc148097 		switch (total_phy_fd) {	/* Number of clause22 ports */
65924732Sdavemq 		case 3:
65934977Sraghus 			/*
65944977Sraghus 			 * TODO 3 1G, 1 10G mode.
65954977Sraghus 			 * Differentiate between 1_1G_1_10G_2_1G and
65964977Sraghus 			 * 1_10G_3_1G
65974977Sraghus 			 */
65984977Sraghus 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
65994977Sraghus 			    "Unsupported neptune type 7"));
66004977Sraghus 			goto error_exit;
66014732Sdavemq 		case 2:
66024732Sdavemq 			/*
66034732Sdavemq 			 * TODO 2 1G, 1 10G mode.
66044732Sdavemq 			 * Differentiate between 1_1G_1_10G_1_1G and
66054732Sdavemq 			 * 1_10G_2_1G
66064732Sdavemq 			 */
66074732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66084732Sdavemq 			    "Unsupported neptune type 8"));
66094732Sdavemq 			goto error_exit;
66104732Sdavemq 		case 1:
66114732Sdavemq 			/*
66124732Sdavemq 			 * TODO 1 1G, 1 10G mode.
66134732Sdavemq 			 * Differentiate between 1_1G_1_10G and
66144732Sdavemq 			 * 1_10G_1_1G
66154732Sdavemq 			 */
66164732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
66174732Sdavemq 			    "Unsupported neptune type 9"));
66184732Sdavemq 			goto error_exit;
66196835Syc148097 		case 0:	/* N2 with 1 XAUI (fiber or copper) */
66206835Syc148097 			/* Fiber XAUI */
66215572Ssbehera 			if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
66225572Ssbehera 			    port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
66235572Ssbehera 
66245572Ssbehera 				/*
66255572Ssbehera 				 * Check the first phy port address against
66265572Ssbehera 				 * the known phy start addresses to determine
66275572Ssbehera 				 * the platform type.
66285572Ssbehera 				 */
66295572Ssbehera 
66305572Ssbehera 				switch (port_fd_arr[0]) {
66316835Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
66326835Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
66336835Syc148097 				case ALT_GOA_CLAUSE45_PORT1_ADDR:
66346835Syc148097 					/*
66356835Syc148097 					 * If hw_p->platform_type ==
66366835Syc148097 					 * P_NEPTUNE_NIU, then portmode
66376835Syc148097 					 * is already known, so there is
66386835Syc148097 					 * no need to figure out hw_p->
66396835Syc148097 					 * platform_type because
66406835Syc148097 					 * platform_type is only for
66416835Syc148097 					 * figuring out portmode.
66426835Syc148097 					 */
66435572Ssbehera 					if (hw_p->platform_type !=
66445572Ssbehera 					    P_NEPTUNE_NIU) {
66455572Ssbehera 						hw_p->platform_type =
66465572Ssbehera 						    P_NEPTUNE_GENERIC;
66475572Ssbehera 						hw_p->niu_type =
66485572Ssbehera 						    NEPTUNE_2_10GF;
66495572Ssbehera 					}
66505572Ssbehera 					break;
66515572Ssbehera 				default:
66525572Ssbehera 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
66535572Ssbehera 					    "Unsupported neptune type 10"));
66545572Ssbehera 					goto error_exit;
66555572Ssbehera 				}
66566075Ssbehera 				/*
66576075Ssbehera 				 * For GOA, which is a hot swappable PHY, the
66586075Ssbehera 				 * phy address to function number mapping
66596075Ssbehera 				 * should be preserved, i.e., addr 16 is
66606075Ssbehera 				 * assigned to function 0 and 20 to function 1
66616075Ssbehera 				 * But for Huron XAUI, the assignment should
66626075Ssbehera 				 * be by function number, i.e., whichever
66636075Ssbehera 				 * function number attaches should be
66646075Ssbehera 				 * assigned the available PHY (this is required
66656075Ssbehera 				 * primarily to support pre-production Huron
66666075Ssbehera 				 * boards where function 0 is mapped to addr 17
66676075Ssbehera 				 */
66686075Ssbehera 				if (port_fd_arr[0] ==
66696835Syc148097 				    ALT_GOA_CLAUSE45_PORT1_ADDR) {
66706075Ssbehera 					hw_p->xcvr_addr[1] = port_fd_arr[0];
66716075Ssbehera 				} else {
66726075Ssbehera 					hw_p->xcvr_addr[nxgep->function_num] =
66736075Ssbehera 					    port_fd_arr[0];
66746075Ssbehera 				}
66756835Syc148097 
66766835Syc148097 			/* A 10G copper XAUI in either slot0 or slot1 */
66776835Syc148097 			} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
66786835Syc148097 			    == TN1010_DEV_ID ||
66796835Syc148097 			    (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
66806835Syc148097 			    == TN1010_DEV_ID) {
66816835Syc148097 				switch (port_fd_arr[0]) {
66826835Syc148097 				/* The XAUI is in slot0 */
66836835Syc148097 				case N2_CLAUSE45_PORT_ADDR_BASE:
66846835Syc148097 					hw_p->niu_type = NEPTUNE_1_TN1010;
66856835Syc148097 					break;
66866835Syc148097 
66876835Syc148097 				/* The XAUI is in slot1 */
66886835Syc148097 				case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
66896835Syc148097 					hw_p->niu_type
66906835Syc148097 					    = NEPTUNE_1_NONE_1_TN1010;
66916835Syc148097 					break;
66926835Syc148097 				default:
66936835Syc148097 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
66946835Syc148097 					    "Unsupported XAUI port address"));
66956835Syc148097 					goto error_exit;
66966835Syc148097 				}
66976835Syc148097 				hw_p->xcvr_addr[nxgep->function_num]
66986835Syc148097 				    = port_fd_arr[0];
66996835Syc148097 
67005572Ssbehera 			} else {
67015572Ssbehera 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67026835Syc148097 				    "Unsupported PHY type"));
67035572Ssbehera 				goto error_exit;
67045572Ssbehera 			}
67055572Ssbehera 			break;
67066835Syc148097 		case 4: /* Maramba always have 4 clause 45 ports */
67076835Syc148097 
67084732Sdavemq 			/* Maramba with 1 XAUI */
67096929Smisaki 			if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
67106929Smisaki 			    (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
67116835Syc148097 			    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
67126929Smisaki 			    != TN1010_DEV_ID) &&
67136835Syc148097 			    ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
67146929Smisaki 			    != TN1010_DEV_ID)) {
67154732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67164732Sdavemq 				    "Unsupported neptune type 12"));
67174732Sdavemq 				goto error_exit;
67184732Sdavemq 			}
67196929Smisaki 
67206929Smisaki 			/*
67216929Smisaki 			 * Check the first phy port address against
67226929Smisaki 			 * the known phy start addresses to determine
67236929Smisaki 			 * the platform type.
67246929Smisaki 			 */
67256929Smisaki 			switch (phy_fd_arr[0]) {
67266929Smisaki 			case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
67276929Smisaki 				hw_p->platform_type =
67286929Smisaki 				    P_NEPTUNE_MARAMBA_P0;
67296929Smisaki 				break;
67306929Smisaki 			case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
67316929Smisaki 				hw_p->platform_type =
67326929Smisaki 				    P_NEPTUNE_MARAMBA_P1;
67336929Smisaki 				break;
67346929Smisaki 			default:
67356929Smisaki 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
67366929Smisaki 				    "Unknown port %d...Cannot "
67376929Smisaki 				    "determine platform type 10 - 2",
67386929Smisaki 				    i));
67396929Smisaki 				goto error_exit;
67406929Smisaki 			}
67416929Smisaki 
67426929Smisaki 			/*
67436929Smisaki 			 * Check the clause45 address to determine
67446929Smisaki 			 * if XAUI is in port 0 or port 1.
67456929Smisaki 			 */
67466929Smisaki 			switch (port_fd_arr[0]) {
67476929Smisaki 			case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
67486929Smisaki 				if (port_pcs_dev_id[0]
67496929Smisaki 				    == PHY_BCM8704_FAMILY ||
67506929Smisaki 				    port_pma_pmd_dev_id[0]
67516929Smisaki 				    == PHY_BCM8704_FAMILY) {
67526929Smisaki 					hw_p->niu_type
67536929Smisaki 					    = NEPTUNE_1_10GF_3_1GC;
67546929Smisaki 				} else {
67556929Smisaki 					hw_p->niu_type
67566929Smisaki 					    = NEPTUNE_1_TN1010_3_1GC;
67576929Smisaki 				}
67586929Smisaki 				hw_p->xcvr_addr[0] = port_fd_arr[0];
67596929Smisaki 				for (i = 1; i < NXGE_MAX_PORTS; i++) {
67606929Smisaki 					hw_p->xcvr_addr[i] =
67616929Smisaki 					    phy_fd_arr[i];
67626929Smisaki 				}
67636929Smisaki 				break;
67646929Smisaki 			case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
67656929Smisaki 				if (port_pcs_dev_id[0]
67666929Smisaki 				    == PHY_BCM8704_FAMILY ||
67676929Smisaki 				    port_pma_pmd_dev_id[0]
67686929Smisaki 				    == PHY_BCM8704_FAMILY) {
67696929Smisaki 					hw_p->niu_type =
67706929Smisaki 					    NEPTUNE_1_1GC_1_10GF_2_1GC;
67716929Smisaki 				} else {
67726929Smisaki 					hw_p->niu_type =
67736929Smisaki 					    NEPTUNE_1_1GC_1_TN1010_2_1GC;
67746929Smisaki 				}
67756929Smisaki 				hw_p->xcvr_addr[0] = phy_fd_arr[0];
67766929Smisaki 				hw_p->xcvr_addr[1] = port_fd_arr[0];
67776929Smisaki 				hw_p->xcvr_addr[2] = phy_fd_arr[2];
67786929Smisaki 				hw_p->xcvr_addr[3] = phy_fd_arr[3];
67796929Smisaki 				break;
67806929Smisaki 			default:
67816929Smisaki 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67826929Smisaki 				    "Unsupported neptune type 11"));
67836929Smisaki 				goto error_exit;
67846929Smisaki 			}
67856929Smisaki 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67866929Smisaki 			    "Maramba with 1 XAUI (fiber or copper)"));
67874732Sdavemq 			break;
67884732Sdavemq 		default:
67894732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
67904732Sdavemq 			    "Unsupported neptune type 13"));
67914732Sdavemq 			goto error_exit;
67924732Sdavemq 		}
67934732Sdavemq 		break;
67946835Syc148097 	case 0: /* 4 ports Neptune based NIC */
67954732Sdavemq 		switch (total_phy_fd) {
67964732Sdavemq 		case 4:
67974782Ssbehera 			if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
67984782Ssbehera 			    (port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
67994782Ssbehera 			    (port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
68004782Ssbehera 			    (port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
68014732Sdavemq 
68024732Sdavemq 				/*
68034732Sdavemq 				 * Check the first phy port address against
68044732Sdavemq 				 * the known phy start addresses to determine
68054732Sdavemq 				 * the platform type.
68064732Sdavemq 				 */
68075572Ssbehera 				switch (phy_fd_arr[0]) {
68086835Syc148097 				case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
68094732Sdavemq 					hw_p->platform_type =
68104732Sdavemq 					    P_NEPTUNE_MARAMBA_P1;
68115572Ssbehera 					break;
68126835Syc148097 				case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
68134977Sraghus 					hw_p->platform_type =
68144977Sraghus 					    P_NEPTUNE_ATLAS_4PORT;
68155572Ssbehera 					break;
68165572Ssbehera 				default:
68174977Sraghus 					NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68184977Sraghus 					    "Unknown port %d...Cannot "
68194977Sraghus 					    "determine platform type", i));
68204977Sraghus 					goto error_exit;
68214732Sdavemq 				}
68224977Sraghus 				hw_p->niu_type = NEPTUNE_4_1GC;
68235572Ssbehera 				for (i = 0; i < NXGE_MAX_PORTS; i++) {
68245572Ssbehera 					hw_p->xcvr_addr[i] = phy_fd_arr[i];
68255572Ssbehera 				}
68264732Sdavemq 			} else {
68274732Sdavemq 				NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68284732Sdavemq 				    "Unsupported neptune type 14"));
68294732Sdavemq 				goto error_exit;
68304732Sdavemq 			}
68314732Sdavemq 			break;
68324732Sdavemq 		case 3:
68334732Sdavemq 			/* TODO 3 1G mode */
68344732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68354732Sdavemq 			    "Unsupported neptune type 15"));
68364732Sdavemq 			goto error_exit;
68374732Sdavemq 		case 2:
68384732Sdavemq 			/* TODO 2 1G mode */
68396261Sjoycey 			if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
68406261Sjoycey 			    (port_phy_id[1] == PHY_BCM5482_FAMILY)) {
68416261Sjoycey 				hw_p->platform_type = P_NEPTUNE_GENERIC;
68426261Sjoycey 				hw_p->niu_type = NEPTUNE_2_1GRF;
68436261Sjoycey 				hw_p->xcvr_addr[2] = phy_fd_arr[0];
68446261Sjoycey 				hw_p->xcvr_addr[3] = phy_fd_arr[1];
68456261Sjoycey 			} else {
68466261Sjoycey 				NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
68476261Sjoycey 				    "Unsupported neptune type 16"));
68486261Sjoycey 				goto error_exit;
68496261Sjoycey 			}
68504732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68516261Sjoycey 			    "2 RGMII Fiber ports - RTM"));
68526261Sjoycey 			break;
68536261Sjoycey 
68544732Sdavemq 		case 1:
68554732Sdavemq 			/* TODO 1 1G mode */
68564732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68574732Sdavemq 			    "Unsupported neptune type 17"));
68584732Sdavemq 			goto error_exit;
68594732Sdavemq 		default:
68604732Sdavemq 			NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68614732Sdavemq 			    "Unsupported neptune type 18, total phy fd %d",
68624732Sdavemq 			    total_phy_fd));
68634732Sdavemq 			goto error_exit;
68644732Sdavemq 		}
68654732Sdavemq 		break;
68664732Sdavemq 	default:
68674732Sdavemq 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
68684732Sdavemq 		    "Unsupported neptune type 19"));
68694732Sdavemq 		goto error_exit;
68704732Sdavemq 	}
68714732Sdavemq 
68724732Sdavemq scan_exit:
68734732Sdavemq 
68744732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
68754732Sdavemq 	    "niu type [0x%x]\n", hw_p->niu_type));
68764732Sdavemq 	return (status);
68774732Sdavemq 
68784732Sdavemq error_exit:
68794732Sdavemq 	return (NXGE_ERROR);
68804732Sdavemq }
68814732Sdavemq 
68824185Sspeer boolean_t
68834185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr)
68844185Sspeer {
68854185Sspeer 	if ((mac_addr.ether_addr_octet[0] & 0x01) ||
68864185Sspeer 	    (ether_cmp(&mac_addr, &etherbroadcastaddr) == 0) ||
68874185Sspeer 	    (ether_cmp(&mac_addr, &etherzeroaddr) == 0))
68884185Sspeer 		return (B_FALSE);
68894185Sspeer 	else
68904185Sspeer 		return (B_TRUE);
68914185Sspeer }
68924732Sdavemq 
68934732Sdavemq static void
68944732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) {
68954732Sdavemq 
68964732Sdavemq 	npi_status_t rs = NPI_SUCCESS;
68974732Sdavemq 	uint8_t xcvr_portn;
68984732Sdavemq 	uint8_t	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
68994732Sdavemq 
69004732Sdavemq 	NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
69014732Sdavemq 
69024732Sdavemq 	if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) {
69036835Syc148097 		xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
69044732Sdavemq 	} else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) {
69056835Syc148097 		xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
69064732Sdavemq 	}
69074732Sdavemq 	/*
69084732Sdavemq 	 * For Altas 4-1G copper, Xcvr port numbers are
69094732Sdavemq 	 * swapped with ethernet port number. This is
69104732Sdavemq 	 * designed for better signal integrity in routing.
69114732Sdavemq 	 */
69124732Sdavemq 	switch (portn) {
69134732Sdavemq 	case 0:
69144732Sdavemq 		xcvr_portn += 3;
69154732Sdavemq 		break;
69164732Sdavemq 	case 1:
69174732Sdavemq 		xcvr_portn += 2;
69184732Sdavemq 		break;
69194732Sdavemq 	case 2:
69204732Sdavemq 		xcvr_portn += 1;
69214732Sdavemq 		break;
69224732Sdavemq 	case 3:
69234732Sdavemq 	default:
69244732Sdavemq 		break;
69254732Sdavemq 	}
69264732Sdavemq 
69276075Ssbehera 	MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
69284732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
69294732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb4ee);
69304732Sdavemq 	if (rs != NPI_SUCCESS) {
69314732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69324732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
69334732Sdavemq 		    "returned error 0x[%x]", rs));
69346075Ssbehera 		MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
69354732Sdavemq 		return;
69364732Sdavemq 	}
69374732Sdavemq 
69384732Sdavemq 	rs = npi_mac_mif_mii_write(nxgep->npi_handle,
69394732Sdavemq 	    xcvr_portn, BCM5464R_MISC, 0xb8ee);
69404732Sdavemq 	if (rs != NPI_SUCCESS) {
69414732Sdavemq 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
69424732Sdavemq 		    "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
69434732Sdavemq 		    "returned error 0x[%x]", rs));
69444732Sdavemq 	}
69454732Sdavemq 
69466075Ssbehera 	MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
69474732Sdavemq }
69485196Ssbehera 
69495196Ssbehera static nxge_status_t
69505196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep)
69515196Ssbehera {
69525196Ssbehera 	p_nxge_stats_t	statsp;
69535196Ssbehera 	uint8_t		xcvr_portn;
69545196Ssbehera 	p_mii_regs_t	mii_regs;
69555196Ssbehera 	mii_mode_control_stat_t	mode;
69565196Ssbehera 	int		status = NXGE_OK;
69575196Ssbehera 
69585196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
69595196Ssbehera 
69605196Ssbehera 	statsp = nxgep->statsp;
69615196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
69625196Ssbehera 	mii_regs = NULL;
69635196Ssbehera 	mode.value = 0;
69645203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
69655196Ssbehera #if defined(__i386)
69665196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
69675196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
69685196Ssbehera 	    mode.value)) != NXGE_OK) {
69695196Ssbehera 		goto fail;
69705196Ssbehera #else
69715196Ssbehera 	if ((status = nxge_mii_write(nxgep, xcvr_portn,
69725196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
69735196Ssbehera 	    mode.value)) != NXGE_OK) {
69745196Ssbehera 		goto fail;
69755196Ssbehera #endif
69765196Ssbehera 	}
69775196Ssbehera #if defined(__i386)
69785196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
69795196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow),
69805196Ssbehera 	    &mode.value)) != NXGE_OK) {
69815196Ssbehera 		goto fail;
69825196Ssbehera 	}
69835196Ssbehera #else
69845196Ssbehera 	if ((status = nxge_mii_read(nxgep, xcvr_portn,
69855196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow),
69865196Ssbehera 	    &mode.value)) != NXGE_OK) {
69875196Ssbehera 		goto fail;
69885196Ssbehera 	}
69895196Ssbehera #endif
69905196Ssbehera 
69915196Ssbehera 	if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
69925196Ssbehera 		nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
69935196Ssbehera 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69945196Ssbehera 		    "nxge_mii_get_link_mode: fiber mode"));
69955196Ssbehera 	}
69965196Ssbehera 
69975196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
69985196Ssbehera 	    "nxge_mii_get_link_mode: "
69995196Ssbehera 	    "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
70005203Ssbehera 	    NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
70015196Ssbehera 	    mode.value, nxgep->mac.portmode));
70025196Ssbehera 
70035196Ssbehera 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70045196Ssbehera 	    "<== nxge_mii_get_link_mode"));
70055196Ssbehera 	return (status);
70065196Ssbehera fail:
70075196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
70085196Ssbehera 	    "<== nxge_mii_get_link_mode (failed)"));
70095196Ssbehera 	return (NXGE_ERROR);
70105196Ssbehera }
70115196Ssbehera 
70126439Sml29623 nxge_status_t
70136439Sml29623 nxge_mac_set_framesize(p_nxge_t nxgep)
70146439Sml29623 {
70156439Sml29623 	npi_attr_t		ap;
70166439Sml29623 	uint8_t			portn;
70176439Sml29623 	npi_handle_t		handle;
70186439Sml29623 	npi_status_t		rs = NPI_SUCCESS;
70196439Sml29623 
70206439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
70216439Sml29623 
70226439Sml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
70236439Sml29623 	handle = nxgep->npi_handle;
70246439Sml29623 
70256439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70266439Sml29623 	    "==> nxge_mac_sec_framesize: port<%d> "
70276439Sml29623 	    "min framesize %d max framesize %d ",
70286439Sml29623 	    portn,
70296439Sml29623 	    nxgep->mac.minframesize,
70306439Sml29623 	    nxgep->mac.maxframesize));
70316439Sml29623 
70326439Sml29623 	SET_MAC_ATTR2(handle, ap, portn,
70336439Sml29623 	    MAC_PORT_FRAME_SIZE,
70346439Sml29623 	    nxgep->mac.minframesize,
70356439Sml29623 	    nxgep->mac.maxframesize,
70366439Sml29623 	    rs);
70376439Sml29623 	if (rs != NPI_SUCCESS) {
70386439Sml29623 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70396439Sml29623 		    "<== nxge_mac_set_framesize: failed to configure "
70406439Sml29623 		    "max/min frame size port %d", portn));
70416439Sml29623 
70426439Sml29623 		return (NXGE_ERROR | rs);
70436439Sml29623 	}
70446439Sml29623 
70456439Sml29623 	NXGE_DEBUG_MSG((nxgep, MAC_CTL,
70466439Sml29623 	    "<== nxge_mac_set_framesize: port<%d>", portn));
70476439Sml29623 
70486439Sml29623 	return (NXGE_OK);
70496439Sml29623 }
70506439Sml29623 
70516835Syc148097 static nxge_status_t
70526835Syc148097 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
70536835Syc148097     uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
70546835Syc148097 {
70556835Syc148097 	uint8_t i;
70566835Syc148097 
70576835Syc148097 	for (i = 0; i < 4; i++) {
70586835Syc148097 		if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
70596835Syc148097 			return (NXGE_ERROR);
70606835Syc148097 	}
70616835Syc148097 
70626835Syc148097 	*num_xaui = 0;
70636835Syc148097 	if ((port_pma_pmd_dev_id[0]  == PHY_BCM8704_FAMILY &&
70646835Syc148097 	    port_pcs_dev_id[0] 	== PHY_BCM8704_FAMILY) ||
70656835Syc148097 	    (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
70666835Syc148097 	    == TN1010_DEV_ID) &&
70676835Syc148097 	    ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
70686835Syc148097 	    == TN1010_DEV_ID))) {
70696835Syc148097 		(*num_xaui) ++;
70706835Syc148097 	}
70716835Syc148097 	if ((port_pma_pmd_dev_id[1]  == PHY_BCM8704_FAMILY &&
70726835Syc148097 	    port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
70736835Syc148097 	    (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
70746835Syc148097 	    == TN1010_DEV_ID) &&
70756835Syc148097 	    ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
70766835Syc148097 	    == TN1010_DEV_ID))) {
70776835Syc148097 		(*num_xaui) ++;
70786835Syc148097 	}
70796835Syc148097 	return (NXGE_OK);
70806835Syc148097 }
70816835Syc148097 
70826835Syc148097 /*
70836835Syc148097  * Instruction from Teranetics:  Once you detect link is up, go
70846835Syc148097  * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
70856835Syc148097  * may want to qualify it by first checking Register 30.1.7:6 and
70866835Syc148097  * making sure it reads "01" (Auto-Neg Complete).
70876835Syc148097  *
70886835Syc148097  * If this function is called when the link is down or before auto-
70896835Syc148097  * negotiation has completed, then the speed of the PHY is not certain.
70906835Syc148097  * In such cases, this function returns 1G as the default speed with
70916835Syc148097  * NXGE_OK status instead of NXGE_ERROR.  It is OK to initialize the
70926835Syc148097  * driver based on a default speed because this function will be called
70936835Syc148097  * again when the link comes up.  Returning NXGE_ERROR, which may
70946835Syc148097  * cause brutal chain reaction in caller functions, is not necessary.
70956835Syc148097  */
70966835Syc148097 static nxge_status_t
70976835Syc148097 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
70986835Syc148097 {
70996835Syc148097 	uint8_t		phy_port_addr, autoneg_stat, link_up;
71006835Syc148097 	nxge_status_t	status = NXGE_OK;
71016835Syc148097 	uint16_t	val;
71026835Syc148097 	uint8_t		portn = NXGE_GET_PORT_NUM(nxgep->function_num);
71036835Syc148097 
71046835Syc148097 	/* Set default speed to 10G */
71056835Syc148097 	*speed = TN1010_SPEED_10G;
71066835Syc148097 
71076835Syc148097 	/* Set Clause 45 */
71086835Syc148097 	npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
71096835Syc148097 
71106835Syc148097 	phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
71116835Syc148097 
71126835Syc148097 	/* Check Device 1 Register 0xA bit0 for link up status */
71136835Syc148097 	status = nxge_mdio_read(nxgep, phy_port_addr,
71146835Syc148097 	    TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
71156835Syc148097 	if (status != NXGE_OK)
71166835Syc148097 		goto fail;
71176835Syc148097 
71186835Syc148097 	link_up = ((val & TN1010_AN_LINK_STAT_BIT)
71196835Syc148097 	    ? B_TRUE : B_FALSE);
71206835Syc148097 	if (link_up == B_FALSE) {
71216835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71226835Syc148097 		    "nxge_get_tn1010_speed: link is down"));
71236835Syc148097 		goto nxge_get_tn1010_speed_exit;
71246835Syc148097 	}
71256835Syc148097 
71266835Syc148097 	if ((status = nxge_mdio_read(nxgep, phy_port_addr,
71276835Syc148097 	    TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
71286835Syc148097 	    &val)) != NXGE_OK) {
71296835Syc148097 		goto fail;
71306835Syc148097 	}
71316835Syc148097 	autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
71326835Syc148097 	    TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
71336835Syc148097 
71346835Syc148097 	/*
71356835Syc148097 	 * Return NXGE_OK even when we can not get a settled speed. In
71366835Syc148097 	 * such case, the speed reported should not be trusted but that
71376835Syc148097 	 * is OK, we will call this function periodically and will get
71386835Syc148097 	 * the correct speed after the link is up.
71396835Syc148097 	 */
71406835Syc148097 	switch (autoneg_stat) {
71416835Syc148097 	case TN1010_AN_IN_PROG:
71426835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71436835Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation in progress"));
71446835Syc148097 		break;
71456835Syc148097 	case TN1010_AN_COMPLETE:
71466835Syc148097 		if ((status = nxge_mdio_read(nxgep, phy_port_addr,
71476835Syc148097 		    TN1010_VENDOR_MMD1_DEV_ADDR,
71486835Syc148097 		    TN1010_VENDOR_MMD1_STATUS_REG,
71496835Syc148097 		    &val)) != NXGE_OK) {
71506835Syc148097 			goto fail;
71516835Syc148097 		}
71526835Syc148097 		*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
71536835Syc148097 		    TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
71546835Syc148097 		break;
71556835Syc148097 	case TN1010_AN_RSVD:
71566835Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
71576835Syc148097 		    "nxge_get_tn1010_speed: Autoneg status undefined"));
71586835Syc148097 		break;
71596835Syc148097 	case TN1010_AN_FAILED:
71606835Syc148097 		NXGE_DEBUG_MSG((nxgep, MAC_CTL,
71616835Syc148097 		    "nxge_get_tn1010_speed: Auto-negotiation failed"));
71626835Syc148097 		break;
71636835Syc148097 	default:
71646835Syc148097 		break;
71656835Syc148097 	}
71666835Syc148097 nxge_get_tn1010_speed_exit:
71676835Syc148097 	return (NXGE_OK);
71686835Syc148097 fail:
71696835Syc148097 	return (status);
71706835Syc148097 }
71716835Syc148097 
71726835Syc148097 
71736835Syc148097 /*
71746835Syc148097  * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
71756835Syc148097  * figures out the speed of the PHY determined by the autonegotiation
71766835Syc148097  * process and sets the following 3 parameters,
71776835Syc148097  * 	nxgep->mac.portmode
71786835Syc148097  *     	nxgep->statsp->mac_stats.link_speed
71796835Syc148097  *	nxgep->statsp->mac_stats.xcvr_inuse
71806835Syc148097  */
71816835Syc148097 static nxge_status_t
71826835Syc148097 nxge_set_tn1010_param(p_nxge_t nxgep)
71836835Syc148097 {
71846835Syc148097 	uint16_t speed;
71856835Syc148097 
71866835Syc148097 	if (nxge_get_tn1010_speed(nxgep,  &speed) != NXGE_OK) {
71876835Syc148097 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
71886835Syc148097 		    "nxge_set_tn1010_param: "
71896835Syc148097 		    "Failed to get TN1010 speed"));
71906835Syc148097 		return (NXGE_ERROR);
71916835Syc148097 	}
71926835Syc148097 	if (speed == TN1010_SPEED_1G) {
71936835Syc148097 		nxgep->mac.portmode = PORT_1G_TN1010;
71946835Syc148097 		nxgep->statsp->mac_stats.link_speed = 1000;
71956835Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
71966835Syc148097 	} else {
71976835Syc148097 		nxgep->mac.portmode = PORT_10G_TN1010;
71986835Syc148097 		nxgep->statsp->mac_stats.link_speed = 10000;
71996835Syc148097 		nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
72006835Syc148097 	}
72016835Syc148097 	return (NXGE_OK);
72026835Syc148097 }
72036835Syc148097 
72045196Ssbehera #ifdef NXGE_DEBUG
72055196Ssbehera static void
72065196Ssbehera nxge_mii_dump(p_nxge_t nxgep)
72075196Ssbehera {
72085196Ssbehera 	p_nxge_stats_t	statsp;
72095196Ssbehera 	uint8_t		xcvr_portn;
72105196Ssbehera 	p_mii_regs_t	mii_regs;
72115196Ssbehera 	mii_bmcr_t	bmcr;
72125196Ssbehera 	mii_bmsr_t	bmsr;
72135196Ssbehera 	mii_idr1_t	idr1;
72145196Ssbehera 	mii_idr2_t	idr2;
72155196Ssbehera 	mii_mode_control_stat_t	mode;
72166495Sspeer 	p_nxge_param_t	param_arr;
72175196Ssbehera 
72185196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
72195196Ssbehera 
72205196Ssbehera 	statsp = nxgep->statsp;
72215196Ssbehera 	xcvr_portn = statsp->mac_stats.xcvr_portn;
72225196Ssbehera 
72235196Ssbehera 	mii_regs = NULL;
72245196Ssbehera 
72255196Ssbehera #if defined(__i386)
72265196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
72275196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value);
72285196Ssbehera #else
72295196Ssbehera 	(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
72305196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
72315196Ssbehera #endif
72325196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72335196Ssbehera 	    "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
72345196Ssbehera 	    xcvr_portn, bmcr.value));
72355196Ssbehera 
72365196Ssbehera #if defined(__i386)
72375196Ssbehera 	(void) nxge_mii_read(nxgep,
72385196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72395196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value);
72405196Ssbehera #else
72415196Ssbehera 	(void) nxge_mii_read(nxgep,
72425196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72435196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
72445196Ssbehera #endif
72455196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72465196Ssbehera 	    "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
72475196Ssbehera 	    xcvr_portn, bmsr.value));
72485196Ssbehera 
72495196Ssbehera #if defined(__i386)
72505196Ssbehera 	(void) nxge_mii_read(nxgep,
72515196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72525196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value);
72535196Ssbehera #else
72545196Ssbehera 	(void) nxge_mii_read(nxgep,
72555196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72565196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
72575196Ssbehera #endif
72585196Ssbehera 
72595196Ssbehera 
72605196Ssbehera #if defined(__i386)
72615196Ssbehera 	(void) nxge_mii_read(nxgep,
72625196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72635196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value);
72645196Ssbehera #else
72655196Ssbehera 	(void) nxge_mii_read(nxgep,
72665196Ssbehera 	    nxgep->statsp->mac_stats.xcvr_portn,
72675196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
72685196Ssbehera #endif
72695196Ssbehera 
72705196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72715196Ssbehera 	    "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
72725196Ssbehera 	    xcvr_portn, idr1.value));
72735196Ssbehera 
72745196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72755196Ssbehera 	    "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
72765196Ssbehera 	    xcvr_portn, idr2.value));
72775196Ssbehera 
72785196Ssbehera 	mode.value = 0;
72795203Ssbehera 	mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
72805196Ssbehera 
72815196Ssbehera #if defined(__i386)
72825196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
72835196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value);
72845196Ssbehera 
72855196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
72865196Ssbehera 	    (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value);
72875196Ssbehera #else
72885196Ssbehera 	(void) nxge_mii_write(nxgep, xcvr_portn,
72895196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
72905196Ssbehera 
72915196Ssbehera 	(void) nxge_mii_read(nxgep, xcvr_portn,
72925196Ssbehera 	    (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
72935196Ssbehera #endif
72945196Ssbehera 
72955196Ssbehera 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
72965196Ssbehera 	    "nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
72975196Ssbehera 	    xcvr_portn, mode.value));
72985196Ssbehera }
72995196Ssbehera #endif
7300