144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2253560810Ssbehera * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <sys/nxge/nxge_impl.h> 2944961713Sgirish #include <sys/nxge/nxge_mac.h> 30*678453a8Sspeer #include <sys/nxge/nxge_hio.h> 3144961713Sgirish 3298ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3398ecde52Stm #define LM_WAIT_MULTIPLIER 8 3498ecde52Stm 35321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 36321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 37321febdeSsbehera 3844961713Sgirish extern uint32_t nxge_no_link_notify; 3959ac0c16Sdavemq extern boolean_t nxge_no_msg; 4044961713Sgirish extern uint32_t nxge_lb_dbg; 4144961713Sgirish extern boolean_t nxge_jumbo_enable; 424202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 4344961713Sgirish 44*678453a8Sspeer /* The following functions may be found in nxge_main.c */ 45*678453a8Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 46*678453a8Sspeer boolean_t factory); 47*678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 48*678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 49*678453a8Sspeer 5098ecde52Stm typedef enum { 5198ecde52Stm CHECK_LINK_RESCHEDULE, 5298ecde52Stm CHECK_LINK_STOP 5398ecde52Stm } check_link_state_t; 5498ecde52Stm 5598ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 5698ecde52Stm 5744961713Sgirish /* 5844961713Sgirish * Ethernet broadcast address definition. 5944961713Sgirish */ 6044961713Sgirish static ether_addr_st etherbroadcastaddr = 6144961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 6259ac0c16Sdavemq /* 6359ac0c16Sdavemq * Ethernet zero address definition. 6459ac0c16Sdavemq */ 6556d930aeSspeer static ether_addr_st etherzeroaddr = 6656d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 6759ac0c16Sdavemq /* 6859ac0c16Sdavemq * Supported chip types 6959ac0c16Sdavemq */ 702d17280bSsbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID}; 7159a835ddSjoycey static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID, BCM5482_PHY_ID}; 7259ac0c16Sdavemq 7359ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 7459ac0c16Sdavemq sizeof (uint32_t)) 7559ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 7659ac0c16Sdavemq sizeof (uint32_t)) 7759ac0c16Sdavemq /* 7859ac0c16Sdavemq * static functions 7959ac0c16Sdavemq */ 802e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 812e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 822e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 8359ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 842d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 8559ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 8659ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 8759ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 8859ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 8959ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 9059ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 9159ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 9259ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 9359ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 9459ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 9559ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 9659ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 972d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 982d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 9959ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 10059ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 10159ac0c16Sdavemq 10259ac0c16Sdavemq /* 10359ac0c16Sdavemq * xcvr tables for supported transceivers 10459ac0c16Sdavemq */ 10559ac0c16Sdavemq 1062e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 10759ac0c16Sdavemq nxge_n2_serdes_init, 10859ac0c16Sdavemq nxge_10G_xcvr_init, 10959ac0c16Sdavemq nxge_10G_link_intr_stop, 11059ac0c16Sdavemq nxge_10G_link_intr_start, 11159ac0c16Sdavemq nxge_check_10g_link, 1122d17280bSsbehera PCS_XCVR 11359ac0c16Sdavemq }; 11459ac0c16Sdavemq 1152e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1162e59129aSraghus nxge_n2_serdes_init, 1172e59129aSraghus nxge_1G_xcvr_init, 1182e59129aSraghus nxge_1G_fiber_link_intr_stop, 1192e59129aSraghus nxge_1G_fiber_link_intr_start, 1202e59129aSraghus nxge_check_mii_link, 1212d17280bSsbehera PCS_XCVR 1222e59129aSraghus }; 1232e59129aSraghus 12459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 12559ac0c16Sdavemq nxge_neptune_10G_serdes_init, 12659ac0c16Sdavemq nxge_10G_xcvr_init, 12759ac0c16Sdavemq nxge_10G_link_intr_stop, 12859ac0c16Sdavemq nxge_10G_link_intr_start, 12959ac0c16Sdavemq nxge_check_10g_link, 1302d17280bSsbehera PCS_XCVR 13159ac0c16Sdavemq }; 13259ac0c16Sdavemq 13359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 13459ac0c16Sdavemq NULL, 13559ac0c16Sdavemq nxge_1G_xcvr_init, 13659ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 13759ac0c16Sdavemq nxge_1G_copper_link_intr_start, 13859ac0c16Sdavemq nxge_check_mii_link, 1392d17280bSsbehera INT_MII_XCVR 14059ac0c16Sdavemq }; 14159ac0c16Sdavemq 14259ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 14359ac0c16Sdavemq nxge_1G_serdes_init, 14459ac0c16Sdavemq nxge_1G_xcvr_init, 14559ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 14659ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 14759ac0c16Sdavemq nxge_check_mii_link, 1482d17280bSsbehera PCS_XCVR 14959ac0c16Sdavemq }; 15059ac0c16Sdavemq 15159ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 15259ac0c16Sdavemq nxge_neptune_10G_serdes_init, 15359ac0c16Sdavemq NULL, 15459ac0c16Sdavemq NULL, 15559ac0c16Sdavemq NULL, 1562e59129aSraghus NULL, 1572d17280bSsbehera PCS_XCVR 15859ac0c16Sdavemq }; 15944961713Sgirish 16044961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t); 16144961713Sgirish 162d81011f0Ssbehera #ifdef NXGE_DEBUG 163d81011f0Ssbehera static void nxge_mii_dump(p_nxge_t); 164d81011f0Ssbehera #endif 165d81011f0Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 166d81011f0Ssbehera 1672e59129aSraghus nxge_status_t 1682e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 1692e59129aSraghus { 1702e59129aSraghus nxge_status_t status = NXGE_OK; 1712e59129aSraghus char *phy_type; 1722e59129aSraghus char *prop_val; 1732e59129aSraghus 1742e59129aSraghus nxgep->mac.portmode = 0; 1752d17280bSsbehera nxgep->xcvr_addr = 0; 1762e59129aSraghus 1772d17280bSsbehera /* 1782d17280bSsbehera * First check for hot swappable phy property. 1792d17280bSsbehera */ 1802d17280bSsbehera if (nxgep->hot_swappable_phy == B_TRUE) { 1812d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1822d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1832d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 1842d17280bSsbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 1852d17280bSsbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1862d17280bSsbehera "hot-swappable-phy") == 1) { 1872d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1882d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1892d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 1902d17280bSsbehera } else if (nxgep->niu_type == N2_NIU && 1912d17280bSsbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 1922d17280bSsbehera "hot-swappable-phy") == 1) { 1932d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1942d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1952d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 1962d17280bSsbehera } 1972d17280bSsbehera 1982d17280bSsbehera /* 1992d17280bSsbehera * MDIO polling support for Monza RTM card, Goa NEM card 2002d17280bSsbehera */ 2012d17280bSsbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 2022d17280bSsbehera 2032d17280bSsbehera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2042d17280bSsbehera 2052d17280bSsbehera nxgep->hot_swappable_phy = B_TRUE; 2062d17280bSsbehera /* 2072d17280bSsbehera * If this is the 2nd NIU port, then check 2 addresses 2082d17280bSsbehera * to take care of the Goa NEM card. Port 1 can have addr 17 2092d17280bSsbehera * (in the eval board) or 20 (in the P0 board). 2102d17280bSsbehera */ 2112d17280bSsbehera if (portn == 1) { 2122d17280bSsbehera if (nxge_is_phy_present(nxgep, 2132d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID, 2142d17280bSsbehera BCM_PHY_ID_MASK)) { 2152d17280bSsbehera nxgep->xcvr_addr = 2162d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR; 2172d17280bSsbehera goto found_phy; 2182d17280bSsbehera } 2192d17280bSsbehera } 2202d17280bSsbehera if (nxge_is_phy_present(nxgep, 221*678453a8Sspeer BCM8706_GOA_PORT_ADDR_BASE + portn, 2222d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 223*678453a8Sspeer nxgep->xcvr_addr = BCM8706_GOA_PORT_ADDR_BASE + 2242d17280bSsbehera portn; 2252d17280bSsbehera goto found_phy; 2262d17280bSsbehera } 2272d17280bSsbehera 2282d17280bSsbehera nxgep->phy_absent = B_TRUE; 2292d17280bSsbehera goto check_phy_done; 2302d17280bSsbehera found_phy: 2312d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2322d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 2332d17280bSsbehera nxgep->phy_absent = B_FALSE; 2342d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 2352d17280bSsbehera "found for hot swappable phy")); 2362d17280bSsbehera check_phy_done: 2372d17280bSsbehera return (status); 2382d17280bSsbehera } 2392d17280bSsbehera 2402d17280bSsbehera /* Get phy-type property from the driver conf. file */ 2412e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 2422e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2432e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 2442e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2452e59129aSraghus "found conf file: phy-type %s", prop_val)); 2462e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 2472e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2482e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 2492e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2502e59129aSraghus "found: 10G Serdes")); 2512e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 2522e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2532e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 2542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 2552e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 2562e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 2572e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 2582e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 2592e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 2602e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2612e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 2622e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 263321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 264321febdeSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 265321febdeSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 266321febdeSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr")); 2672e59129aSraghus } 2682e59129aSraghus 2692e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 2702e59129aSraghus "phy-type", prop_val); 2712e59129aSraghus ddi_prop_free(prop_val); 2722e59129aSraghus 2732e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 2742e59129aSraghus "Got phy type [0x%x] from conf file", 2752e59129aSraghus nxgep->mac.portmode)); 2762e59129aSraghus 2772e59129aSraghus return (NXGE_OK); 2782e59129aSraghus } 2792d17280bSsbehera 2802d17280bSsbehera /* Get phy-type property from OBP */ 2812e59129aSraghus if (nxgep->niu_type == N2_NIU) { 2822e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 2832e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 2842e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 2852e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 2862e59129aSraghus XPCS_XCVR; 2872e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 2882e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2892e59129aSraghus "10G Fiber Xcvr")); 2902e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 2912e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 2922e59129aSraghus INT_MII_XCVR; 2932e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 2942e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2952e59129aSraghus "1G Copper Xcvr")); 2962e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 2972e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2982e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 2992e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3002e59129aSraghus "1G Fiber Xcvr")); 3012e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 3022e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 3032e59129aSraghus XPCS_XCVR; 3042e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 3052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3062e59129aSraghus "10G Copper Xcvr")); 3072e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 3082e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3092e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3102e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3112e59129aSraghus "OBP: 10G Serdes")); 3122e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3132e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3142e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3152e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3162e59129aSraghus "OBP: 1G Serdes")); 3172e59129aSraghus } else { 3182e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3192e59129aSraghus "Unknown phy-type: %s", prop_val)); 3202e59129aSraghus ddi_prop_free(prop_val); 3212e59129aSraghus return (NXGE_ERROR); 3222e59129aSraghus } 3232e59129aSraghus status = NXGE_OK; 3242e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3252e59129aSraghus nxgep->dip, "phy-type", prop_val); 3262e59129aSraghus ddi_prop_free(prop_val); 3272e59129aSraghus 3282e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3292e59129aSraghus "Got phy type [0x%x] from OBP", 3302e59129aSraghus nxgep->mac.portmode)); 3312e59129aSraghus 3322e59129aSraghus return (status); 3332e59129aSraghus } else { 3342e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3352e59129aSraghus "Exiting...phy-type property not found")); 3362e59129aSraghus return (NXGE_ERROR); 3372e59129aSraghus } 3382e59129aSraghus } 3392e59129aSraghus 3402e59129aSraghus 3412e59129aSraghus if (!nxgep->vpd_info.present) { 3422e59129aSraghus return (NXGE_OK); 3432e59129aSraghus } 3442e59129aSraghus 3452e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 3462e59129aSraghus goto read_seeprom; 3472e59129aSraghus } 3482e59129aSraghus 3492e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3502e59129aSraghus "Reading phy type from expansion ROM")); 3512e59129aSraghus /* 3522e59129aSraghus * Try to read the phy type from the vpd data read off the 3532e59129aSraghus * expansion ROM. 3542e59129aSraghus */ 3552e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 3562e59129aSraghus 357d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 3582e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3592e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 360d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 3612e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 3622e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 363d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 3642e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3652e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 366d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 3672e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 3682e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 369d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 370d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 371d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 372d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 373d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 374d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3752e59129aSraghus } else { 376d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3772e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3782e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 3792e59129aSraghus goto read_seeprom; 3802e59129aSraghus } 3812e59129aSraghus 3822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3832e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 3842e59129aSraghus 3852e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3862e59129aSraghus return (status); 3872e59129aSraghus 3882e59129aSraghus read_seeprom: 3892e59129aSraghus /* 3902e59129aSraghus * read the phy type from the SEEPROM - NCR registers 3912e59129aSraghus */ 3922e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 3932e59129aSraghus if (status != NXGE_OK) { 3942e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3952e59129aSraghus "Failed to get phy type")); 3962e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3972e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 3982e59129aSraghus } 3992e59129aSraghus 4002e59129aSraghus return (status); 4012e59129aSraghus 4022e59129aSraghus } 4032e59129aSraghus 40459ac0c16Sdavemq /* Set up the PHY specific values. */ 40559ac0c16Sdavemq 40659ac0c16Sdavemq nxge_status_t 40759ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 40859ac0c16Sdavemq { 40959ac0c16Sdavemq nxge_status_t status = NXGE_OK; 41059ac0c16Sdavemq uint32_t port_type; 41159ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4122e59129aSraghus uint32_t pcs_id = 0; 4132e59129aSraghus uint32_t pma_pmd_id = 0; 4142e59129aSraghus uint32_t phy_id = 0; 4152d17280bSsbehera uint16_t chip_id = 0; 41659ac0c16Sdavemq 41759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 41859ac0c16Sdavemq portn)); 41959ac0c16Sdavemq 4202e59129aSraghus switch (nxgep->niu_type) { 4212e59129aSraghus case N2_NIU: 4222e59129aSraghus switch (nxgep->mac.portmode) { 4232e59129aSraghus case PORT_1G_FIBER: 4242e59129aSraghus case PORT_1G_SERDES: 4252e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 4262d17280bSsbehera nxgep->xcvr_addr = portn; 4272e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 4282e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 4292e59129aSraghus "Serdes")); 4302e59129aSraghus break; 4312e59129aSraghus case PORT_10G_FIBER: 4322e59129aSraghus case PORT_10G_SERDES: 4332e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 4342d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 4352d17280bSsbehera nxgep->xcvr_addr = 4362d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 4372d17280bSsbehera } 4382e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 4392e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 4402e59129aSraghus "Serdes")); 4412e59129aSraghus break; 4422d17280bSsbehera case PORT_HSP_MODE: 4432d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 4442d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 4452d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 4462d17280bSsbehera "Swappable Xcvr (not present)")); 4472d17280bSsbehera break; 4482e59129aSraghus default: 4492e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4502e59129aSraghus "<== nxge_setup_xcvr_table: " 4512e59129aSraghus "Unable to determine NIU portmode")); 4522e59129aSraghus return (NXGE_ERROR); 4532e59129aSraghus } 4542e59129aSraghus break; 4552e59129aSraghus default: 4562e59129aSraghus if (nxgep->mac.portmode == 0) { 4572e59129aSraghus /* 4582e59129aSraghus * Would be the case for platforms like Maramba 4592e59129aSraghus * in which the phy type could not be got from conf 4602e59129aSraghus * file, OBP, VPD or Serial PROM. 4612e59129aSraghus */ 4622e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 4632e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4642e59129aSraghus "<== nxge_setup_xcvr_table:" 4652e59129aSraghus " Invalid Neptune type [0x%x]", 4662e59129aSraghus nxgep->niu_type)); 4672e59129aSraghus return (NXGE_ERROR); 4682e59129aSraghus } 4692e59129aSraghus 4702e59129aSraghus port_type = nxgep->niu_type >> 4712e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 4722e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 4732e59129aSraghus 4742e59129aSraghus switch (port_type) { 4752e59129aSraghus 4762e59129aSraghus case NXGE_PORT_1G_COPPER: 4772e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4782e59129aSraghus break; 4792e59129aSraghus case NXGE_PORT_10G_COPPER: 4802e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 4812e59129aSraghus break; 4822e59129aSraghus case NXGE_PORT_1G_FIBRE: 4832e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4842e59129aSraghus break; 4852e59129aSraghus case NXGE_PORT_10G_FIBRE: 4862e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 4872e59129aSraghus break; 4882e59129aSraghus case NXGE_PORT_1G_SERDES: 4892e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4902e59129aSraghus break; 4912e59129aSraghus case NXGE_PORT_10G_SERDES: 4922e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4932e59129aSraghus break; 4942e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 4952e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 4962e59129aSraghus break; 4972e59129aSraghus default: 4982e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4992e59129aSraghus "<== nxge_setup_xcvr_table: " 5002e59129aSraghus "Unknown port-type: 0x%x", port_type)); 5012e59129aSraghus return (NXGE_ERROR); 5022e59129aSraghus } 5032e59129aSraghus } 5042e59129aSraghus 5052e59129aSraghus switch (nxgep->mac.portmode) { 5062e59129aSraghus case PORT_1G_COPPER: 5072e59129aSraghus case PORT_1G_RGMII_FIBER: 50859ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 5092d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 51059ac0c16Sdavemq /* 51159ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 51259ac0c16Sdavemq * swapped with ethernet port number. This is 5132e59129aSraghus * designed for better signal integrity in 5142e59129aSraghus * routing. This is also the case for the 5152e59129aSraghus * on-board Neptune copper ports on the Maramba 5162e59129aSraghus * platform. 51759ac0c16Sdavemq */ 5182e59129aSraghus switch (nxgep->platform_type) { 5192e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 5202e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 5212e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 5222e59129aSraghus switch (portn) { 5232e59129aSraghus case 0: 5242d17280bSsbehera nxgep->xcvr_addr += 3; 5252e59129aSraghus break; 5262e59129aSraghus case 1: 5272d17280bSsbehera nxgep->xcvr_addr += 1; 5282e59129aSraghus break; 5292e59129aSraghus case 2: 5302d17280bSsbehera nxgep->xcvr_addr -= 1; 5312e59129aSraghus break; 5322e59129aSraghus case 3: 5332d17280bSsbehera nxgep->xcvr_addr -= 3; 5342e59129aSraghus break; 5352e59129aSraghus default: 5362e59129aSraghus return (NXGE_ERROR); 5372e59129aSraghus } 53859ac0c16Sdavemq break; 53959ac0c16Sdavemq default: 5402e59129aSraghus break; 54159ac0c16Sdavemq } 542d81011f0Ssbehera 5432e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5442e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 5452e59129aSraghus "Copper" : "RGMII Fiber")); 54659ac0c16Sdavemq break; 5472e59129aSraghus case PORT_10G_COPPER: 54859ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 54959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 55059ac0c16Sdavemq break; 5512e59129aSraghus case PORT_1G_FIBER: 5522e59129aSraghus case PORT_1G_SERDES: 55359ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 5542d17280bSsbehera nxgep->xcvr_addr = portn; 5552e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5562e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 5572e59129aSraghus "Fiber" : "Serdes")); 55859ac0c16Sdavemq break; 5592e59129aSraghus case PORT_10G_FIBER: 5602e59129aSraghus case PORT_10G_SERDES: 56159ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 5622d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 5632d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 5642d17280bSsbehera "nxgep->xcvr_addr = [%d]", 5652d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 5662d17280bSsbehera nxgep->xcvr_addr)); 5672d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5682d17280bSsbehera nxgep->xcvr_addr = 5692d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 5702d17280bSsbehera } 5712e59129aSraghus switch (nxgep->platform_type) { 5722e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 5732e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 57459ac0c16Sdavemq /* 57559ac0c16Sdavemq * Switch off LED for corresponding copper 57659ac0c16Sdavemq * port 57759ac0c16Sdavemq */ 57859ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 5792e59129aSraghus break; 5802e59129aSraghus default: 5812e59129aSraghus break; 58259ac0c16Sdavemq } 5832e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 5842e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 5852e59129aSraghus "Fiber" : "Serdes")); 58659ac0c16Sdavemq break; 5872d17280bSsbehera 5882d17280bSsbehera case PORT_HSP_MODE: 5892d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 5902d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 5912d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 5922d17280bSsbehera "Swappable Xcvr (not present)")); 5932d17280bSsbehera break; 59459ac0c16Sdavemq default: 59559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59659ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 59759ac0c16Sdavemq return (NXGE_ERROR); 59859ac0c16Sdavemq } 59959ac0c16Sdavemq } 60059ac0c16Sdavemq 6012d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 6022d17280bSsbehera if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6032d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 6042d17280bSsbehera &chip_id)) == NXGE_OK) { 6052d17280bSsbehera 6062d17280bSsbehera switch (chip_id) { 6072d17280bSsbehera case BCM8704_CHIP_ID: 6082d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6092d17280bSsbehera "nxge_setup_xcvr_table: " 6102d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 6112d17280bSsbehera chip_id)); 6122d17280bSsbehera break; 6132d17280bSsbehera case BCM8706_CHIP_ID: 6142d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6152d17280bSsbehera "nxge_setup_xcvr_table: " 6162d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 6172d17280bSsbehera chip_id)); 6182d17280bSsbehera break; 6192d17280bSsbehera default: 6202d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6212d17280bSsbehera "nxge_setup_xcvr_table: " 6222d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 6232d17280bSsbehera chip_id)); 6242d17280bSsbehera break; 6252d17280bSsbehera } 6262d17280bSsbehera } 6272d17280bSsbehera } 6282d17280bSsbehera 62959ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 6302d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 6312d17280bSsbehera nxgep->chip_id = chip_id; 6322e59129aSraghus 6332e59129aSraghus /* 6342e59129aSraghus * Get the actual device ID value returned by MDIO read. 6352e59129aSraghus */ 6362e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 6372e59129aSraghus 6382d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 6392e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 6402e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 6412e59129aSraghus } else { 6422d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 6432e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 6442e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 6452e59129aSraghus } else { 6462e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 6472d17280bSsbehera nxgep->xcvr_addr); 6482e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6492e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 6502e59129aSraghus } 6512e59129aSraghus } 6522e59129aSraghus } 6532e59129aSraghus 65459ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 65559ac0c16Sdavemq 6562e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 6572d17280bSsbehera "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type, 6582d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 6592e59129aSraghus 66059ac0c16Sdavemq return (status); 66159ac0c16Sdavemq } 66259ac0c16Sdavemq 66344961713Sgirish /* Initialize the entire MAC and physical layer */ 66444961713Sgirish 66544961713Sgirish nxge_status_t 66644961713Sgirish nxge_mac_init(p_nxge_t nxgep) 66744961713Sgirish { 66844961713Sgirish uint8_t portn; 66944961713Sgirish nxge_status_t status = NXGE_OK; 67044961713Sgirish 67144961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 67244961713Sgirish 67344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 67444961713Sgirish 67544961713Sgirish nxgep->mac.portnum = portn; 67644961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 67744961713Sgirish 67844961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 67944961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 68044961713Sgirish 68144961713Sgirish /* Initialize XIF to configure a network mode */ 68244961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 68344961713Sgirish goto fail; 68444961713Sgirish } 68544961713Sgirish 68644961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 68744961713Sgirish goto fail; 68844961713Sgirish } 68944961713Sgirish 69044961713Sgirish /* Initialize TX and RX MACs */ 69144961713Sgirish /* 69244961713Sgirish * Always perform XIF init first, before TX and RX MAC init 69344961713Sgirish */ 69444961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 69544961713Sgirish goto fail; 69644961713Sgirish 69744961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 69844961713Sgirish goto fail; 69944961713Sgirish 70044961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 70144961713Sgirish goto fail; 70244961713Sgirish 70344961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 70444961713Sgirish goto fail; 70544961713Sgirish 70644961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 70744961713Sgirish goto fail; 70844961713Sgirish 70944961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 71044961713Sgirish goto fail; 71144961713Sgirish 712cb9d3ae6Smisaki /* Initialize MAC control configuration */ 713cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 714cb9d3ae6Smisaki goto fail; 715cb9d3ae6Smisaki } 716cb9d3ae6Smisaki 71744961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 71844961713Sgirish 719d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 720d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 721d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 722d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 723d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 724d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 725d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 726d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 727d81011f0Ssbehera goto fail; 728d81011f0Ssbehera } 729d81011f0Ssbehera } 730d81011f0Ssbehera 7312e59129aSraghus 73244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 73344961713Sgirish 73444961713Sgirish return (NXGE_OK); 73544961713Sgirish fail: 73644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 73744961713Sgirish "nxge_mac_init: failed to initialize MAC port<%d>", 73844961713Sgirish portn)); 73944961713Sgirish return (status); 74044961713Sgirish } 74144961713Sgirish 74244961713Sgirish /* Initialize the Ethernet Link */ 74344961713Sgirish 74444961713Sgirish nxge_status_t 74544961713Sgirish nxge_link_init(p_nxge_t nxgep) 74644961713Sgirish { 74744961713Sgirish nxge_status_t status = NXGE_OK; 7482e59129aSraghus nxge_port_mode_t portmode; 74944961713Sgirish #ifdef NXGE_DEBUG 75044961713Sgirish uint8_t portn; 75144961713Sgirish 75244961713Sgirish portn = nxgep->mac.portnum; 75344961713Sgirish 75444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 75544961713Sgirish #endif 7562d17280bSsbehera if (nxgep->hot_swappable_phy && nxgep->phy_absent) { 7572d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: " 7582d17280bSsbehera "Phy not present, cannot initialize link")); 7592d17280bSsbehera return (status); 7602d17280bSsbehera } 76144961713Sgirish 7622e59129aSraghus portmode = nxgep->mac.portmode; 7632d17280bSsbehera 7642e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 7652e59129aSraghus (portmode != PORT_1G_SERDES)) { 76644961713Sgirish /* Workaround to get link up in both NIU ports */ 7672e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 76844961713Sgirish goto fail; 7692e59129aSraghus } 77044961713Sgirish } 77144961713Sgirish NXGE_DELAY(200000); 77244961713Sgirish /* Initialize internal serdes */ 77344961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 77444961713Sgirish goto fail; 77544961713Sgirish NXGE_DELAY(200000); 77644961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 77744961713Sgirish goto fail; 77844961713Sgirish 77944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 78044961713Sgirish 78144961713Sgirish return (NXGE_OK); 78244961713Sgirish 78344961713Sgirish fail: 78444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 78544961713Sgirish "nxge_link_init: ", 78644961713Sgirish "failed to initialize Ethernet link on port<%d>", 78744961713Sgirish portn)); 78844961713Sgirish 78944961713Sgirish return (status); 79044961713Sgirish } 79144961713Sgirish 79244961713Sgirish 79344961713Sgirish /* Initialize the XIF sub-block within the MAC */ 79444961713Sgirish 79544961713Sgirish nxge_status_t 79644961713Sgirish nxge_xif_init(p_nxge_t nxgep) 79744961713Sgirish { 79844961713Sgirish uint32_t xif_cfg = 0; 79944961713Sgirish npi_attr_t ap; 80044961713Sgirish uint8_t portn; 80144961713Sgirish nxge_port_t portt; 80244961713Sgirish nxge_port_mode_t portmode; 80344961713Sgirish p_nxge_stats_t statsp; 80444961713Sgirish npi_status_t rs = NPI_SUCCESS; 80544961713Sgirish npi_handle_t handle; 80644961713Sgirish 80744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 80844961713Sgirish 80944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 81044961713Sgirish 81144961713Sgirish handle = nxgep->npi_handle; 81244961713Sgirish portmode = nxgep->mac.portmode; 81344961713Sgirish portt = nxgep->mac.porttype; 81444961713Sgirish statsp = nxgep->statsp; 81544961713Sgirish 816d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 817d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 818d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 819d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 820d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 821d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 822d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 823d81011f0Ssbehera } 824d81011f0Ssbehera 82544961713Sgirish if (portt == PORT_TYPE_XMAC) { 82644961713Sgirish 82744961713Sgirish /* Setup XIF Configuration for XMAC */ 82844961713Sgirish 82944961713Sgirish if ((portmode == PORT_10G_FIBER) || 8302e59129aSraghus (portmode == PORT_10G_COPPER) || 8312e59129aSraghus (portmode == PORT_10G_SERDES)) 83244961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 83344961713Sgirish 83444961713Sgirish if (portmode == PORT_1G_COPPER) { 83544961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 83644961713Sgirish } 83744961713Sgirish 83844961713Sgirish /* Set MAC Internal Loopback if necessary */ 83944961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 84044961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 84144961713Sgirish 84244961713Sgirish if (statsp->mac_stats.link_speed == 100) 84344961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 84444961713Sgirish 84544961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 84644961713Sgirish 8472e59129aSraghus if ((portmode == PORT_10G_FIBER) || 8482e59129aSraghus (portmode == PORT_10G_SERDES)) { 84944961713Sgirish if (statsp->mac_stats.link_up) { 85044961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 85144961713Sgirish } else { 85244961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 85344961713Sgirish } 85444961713Sgirish } 85544961713Sgirish 85644961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 85744961713Sgirish if (rs != NPI_SUCCESS) 85844961713Sgirish goto fail; 85944961713Sgirish 86044961713Sgirish nxgep->mac.xif_config = xif_cfg; 86144961713Sgirish 86244961713Sgirish /* Set Port Mode */ 86344961713Sgirish if ((portmode == PORT_10G_FIBER) || 8642e59129aSraghus (portmode == PORT_10G_COPPER) || 8652e59129aSraghus (portmode == PORT_10G_SERDES)) { 86644961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 86744961713Sgirish MAC_XGMII_MODE, rs); 86844961713Sgirish if (rs != NPI_SUCCESS) 86944961713Sgirish goto fail; 87044961713Sgirish if (statsp->mac_stats.link_up) { 87144961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 87244961713Sgirish goto fail; 87344961713Sgirish } else { 87444961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 87544961713Sgirish goto fail; 87644961713Sgirish } 87744961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 8782e59129aSraghus (portmode == PORT_1G_COPPER) || 879d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 880d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 881d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 882d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 883d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 88444961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 88544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 88644961713Sgirish MAC_GMII_MODE, rs); 88744961713Sgirish } else { 88844961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 88944961713Sgirish MAC_MII_MODE, rs); 89044961713Sgirish } 89144961713Sgirish if (rs != NPI_SUCCESS) 89244961713Sgirish goto fail; 89344961713Sgirish } else { 89444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 89544961713Sgirish "nxge_xif_init: Unknown port mode (%d)" 89644961713Sgirish " for port<%d>", portmode, portn)); 89744961713Sgirish goto fail; 89844961713Sgirish } 89944961713Sgirish 900d81011f0Ssbehera /* Enable ATCA mode */ 901d81011f0Ssbehera 90244961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 90344961713Sgirish 90444961713Sgirish /* Setup XIF Configuration for BMAC */ 90544961713Sgirish 906d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 907d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 90844961713Sgirish if (statsp->mac_stats.link_speed == 100) 90944961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 91044961713Sgirish } 91144961713Sgirish 91244961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 91344961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 91444961713Sgirish 91544961713Sgirish if (statsp->mac_stats.link_speed == 1000) 91644961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 91744961713Sgirish 91844961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 91944961713Sgirish 92044961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 92144961713Sgirish if (rs != NPI_SUCCESS) 92244961713Sgirish goto fail; 92344961713Sgirish nxgep->mac.xif_config = xif_cfg; 92444961713Sgirish } 92544961713Sgirish 92644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 92744961713Sgirish return (NXGE_OK); 92844961713Sgirish fail: 92944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 93044961713Sgirish "nxge_xif_init: Failed to initialize XIF port<%d>", 93144961713Sgirish portn)); 93244961713Sgirish return (NXGE_ERROR | rs); 93344961713Sgirish } 93444961713Sgirish 93544961713Sgirish /* Initialize the PCS sub-block in the MAC */ 93644961713Sgirish 93744961713Sgirish nxge_status_t 93844961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 93944961713Sgirish { 94044961713Sgirish pcs_cfg_t pcs_cfg; 94144961713Sgirish uint32_t val; 94244961713Sgirish uint8_t portn; 94344961713Sgirish nxge_port_mode_t portmode; 94444961713Sgirish npi_handle_t handle; 94544961713Sgirish p_nxge_stats_t statsp; 94644961713Sgirish npi_status_t rs = NPI_SUCCESS; 94744961713Sgirish 94844961713Sgirish handle = nxgep->npi_handle; 94944961713Sgirish portmode = nxgep->mac.portmode; 95044961713Sgirish portn = nxgep->mac.portnum; 95144961713Sgirish statsp = nxgep->statsp; 95244961713Sgirish 95344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 95444961713Sgirish 9552e59129aSraghus if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 9562e59129aSraghus if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 9572e59129aSraghus goto fail; 9582e59129aSraghus } 9592e59129aSraghus 96044961713Sgirish /* Initialize port's PCS */ 96144961713Sgirish pcs_cfg.value = 0; 96244961713Sgirish pcs_cfg.bits.w0.enable = 1; 96344961713Sgirish pcs_cfg.bits.w0.mask = 1; 96444961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 96544961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 96644961713Sgirish 9672e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9682e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 9692e59129aSraghus portn, pcs_cfg.value)); 97044961713Sgirish } else if ((portmode == PORT_10G_FIBER) || 9712e59129aSraghus (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 97244961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 97344961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 97444961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 97544961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 97644961713Sgirish 97744961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 97844961713Sgirish goto fail; 97944961713Sgirish 98044961713Sgirish /* Set XPCS Internal Loopback if necessary */ 98144961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 98244961713Sgirish XPCS_REG_CONTROL1, &val)) 98344961713Sgirish != NPI_SUCCESS) 98444961713Sgirish goto fail; 98544961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 98644961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 98744961713Sgirish val |= XPCS_CTRL1_LOOPBK; 98844961713Sgirish else 98944961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 99044961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 99144961713Sgirish XPCS_REG_CONTROL1, val)) 99244961713Sgirish != NPI_SUCCESS) 99344961713Sgirish goto fail; 99444961713Sgirish 99544961713Sgirish /* Clear descw errors */ 99644961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 99744961713Sgirish XPCS_REG_DESCWERR_COUNTER, 0)) 99844961713Sgirish != NPI_SUCCESS) 99944961713Sgirish goto fail; 100044961713Sgirish /* Clear symbol errors */ 100144961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 100244961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 100344961713Sgirish != NPI_SUCCESS) 100444961713Sgirish goto fail; 100544961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 100644961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 100744961713Sgirish != NPI_SUCCESS) 100844961713Sgirish goto fail; 100944961713Sgirish 1010d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1011d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1012d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1013d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 101444961713Sgirish if (portn < 4) { 101544961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 101644961713Sgirish PCS_DATAPATH_MODE_MII); 101744961713Sgirish } 101844961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 101944961713Sgirish goto fail; 102044961713Sgirish 102144961713Sgirish } else { 102244961713Sgirish goto fail; 102344961713Sgirish } 102444961713Sgirish pass: 102544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 102644961713Sgirish return (NXGE_OK); 102744961713Sgirish fail: 102844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 102944961713Sgirish "nxge_pcs_init: Failed to initialize PCS port<%d>", 103044961713Sgirish portn)); 103144961713Sgirish return (NXGE_ERROR | rs); 103244961713Sgirish } 103344961713Sgirish 1034cb9d3ae6Smisaki /* 1035cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1036cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1037cb9d3ae6Smisaki */ 1038cb9d3ae6Smisaki nxge_status_t 1039cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1040cb9d3ae6Smisaki { 1041cb9d3ae6Smisaki uint8_t portn; 1042cb9d3ae6Smisaki nxge_port_t portt; 1043cb9d3ae6Smisaki p_nxge_stats_t statsp; 1044cb9d3ae6Smisaki npi_handle_t handle; 1045cb9d3ae6Smisaki uint32_t val; 1046cb9d3ae6Smisaki 1047cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1048cb9d3ae6Smisaki 1049cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1050cb9d3ae6Smisaki portn)); 1051cb9d3ae6Smisaki 1052cb9d3ae6Smisaki handle = nxgep->npi_handle; 1053cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1054cb9d3ae6Smisaki statsp = nxgep->statsp; 1055cb9d3ae6Smisaki 1056cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 1057cb9d3ae6Smisaki /* Readin the current XMAC Config Register for XMAC */ 1058cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1059cb9d3ae6Smisaki 1060cb9d3ae6Smisaki /* 1061cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1062cb9d3ae6Smisaki * XMAC only supports receive-pause 1063cb9d3ae6Smisaki */ 1064cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1065cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1066cb9d3ae6Smisaki /* 1067cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1068cb9d3ae6Smisaki * is 0, enable receive pause. 1069cb9d3ae6Smisaki */ 1070cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1071cb9d3ae6Smisaki } else { 1072cb9d3ae6Smisaki /* 1073cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1074cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1075cb9d3ae6Smisaki * not supported. 1076cb9d3ae6Smisaki */ 1077cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1078cb9d3ae6Smisaki } 1079cb9d3ae6Smisaki } else { 10801bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10811bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: pause", 10821bd6825cSml portn)); 1083cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 10841bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10851bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 10861bd6825cSml "enable pause", portn)); 1087cb9d3ae6Smisaki /* 1088cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1089cb9d3ae6Smisaki * is 1, enable receive pause. 1090cb9d3ae6Smisaki */ 1091cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1092cb9d3ae6Smisaki } else { 1093cb9d3ae6Smisaki /* 1094cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1095cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1096cb9d3ae6Smisaki * not supported 1097cb9d3ae6Smisaki */ 10981bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10991bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 11001bd6825cSml "disable pause", portn)); 1101cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1102cb9d3ae6Smisaki } 1103cb9d3ae6Smisaki } 1104cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1105cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 1106cb9d3ae6Smisaki /* Readin the current MAC CTRL Config Register for BMAC */ 1107cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1108cb9d3ae6Smisaki 1109cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1110cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1111cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1112cb9d3ae6Smisaki /* 1113cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1114cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1115cb9d3ae6Smisaki * is not supported 1116cb9d3ae6Smisaki */ 1117cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1118cb9d3ae6Smisaki } else { 1119cb9d3ae6Smisaki /* 1120cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1121cb9d3ae6Smisaki * is 0, enable receive pause and disable 1122cb9d3ae6Smisaki * send pause. 1123cb9d3ae6Smisaki */ 1124cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1125cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1126cb9d3ae6Smisaki } 1127cb9d3ae6Smisaki } else { 1128cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1129cb9d3ae6Smisaki /* 1130cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1131cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1132cb9d3ae6Smisaki * not supported. 1133cb9d3ae6Smisaki */ 1134cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1135cb9d3ae6Smisaki } else { 1136cb9d3ae6Smisaki /* 1137cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1138cb9d3ae6Smisaki * is 0, pause capability is not available in 1139cb9d3ae6Smisaki * either direction. 1140cb9d3ae6Smisaki */ 1141cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 1142cb9d3ae6Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1143cb9d3ae6Smisaki } 1144cb9d3ae6Smisaki } 1145cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1146cb9d3ae6Smisaki } 1147cb9d3ae6Smisaki 1148cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1149cb9d3ae6Smisaki portn)); 1150cb9d3ae6Smisaki 1151cb9d3ae6Smisaki return (NXGE_OK); 1152cb9d3ae6Smisaki } 1153cb9d3ae6Smisaki 115444961713Sgirish /* Initialize the Internal Serdes */ 115544961713Sgirish 115644961713Sgirish nxge_status_t 115744961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 115844961713Sgirish { 115944961713Sgirish p_nxge_stats_t statsp; 116044961713Sgirish #ifdef NXGE_DEBUG 116144961713Sgirish uint8_t portn; 116244961713Sgirish #endif 116344961713Sgirish nxge_status_t status = NXGE_OK; 116444961713Sgirish 116544961713Sgirish #ifdef NXGE_DEBUG 116644961713Sgirish portn = nxgep->mac.portnum; 116744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 116859ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 116944961713Sgirish #endif 117044961713Sgirish 117159ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 117259ac0c16Sdavemq statsp = nxgep->statsp; 117359ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 117459ac0c16Sdavemq if (status != NXGE_OK) 117544961713Sgirish goto fail; 117659ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 117744961713Sgirish } 117844961713Sgirish 117944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 118059ac0c16Sdavemq portn)); 118144961713Sgirish 118244961713Sgirish return (NXGE_OK); 118344961713Sgirish 118444961713Sgirish fail: 118544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 118659ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 118759ac0c16Sdavemq portn)); 118844961713Sgirish 118944961713Sgirish return (status); 119044961713Sgirish } 119144961713Sgirish 119244961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 119344961713Sgirish 119459ac0c16Sdavemq static nxge_status_t 119544961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 119644961713Sgirish { 119744961713Sgirish uint8_t portn; 119844961713Sgirish int chan; 119944961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 12002e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 120144961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 120244961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 120344961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 120444961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 12052e59129aSraghus #ifdef NXGE_DEBUG 12062e59129aSraghus esr_ti_testcfg_t cfg; 12072e59129aSraghus #endif 120844961713Sgirish esr_ti_testcfg_t test_cfg; 120944961713Sgirish nxge_status_t status = NXGE_OK; 121044961713Sgirish 121144961713Sgirish portn = nxgep->mac.portnum; 121244961713Sgirish 121344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 121444961713Sgirish portn)); 121544961713Sgirish 121644961713Sgirish tx_cfg_l.value = 0; 121744961713Sgirish tx_cfg_h.value = 0; 121844961713Sgirish rx_cfg_l.value = 0; 121944961713Sgirish rx_cfg_h.value = 0; 122044961713Sgirish pll_cfg_l.value = 0; 12212e59129aSraghus pll_sts_l.value = 0; 122244961713Sgirish test_cfg.value = 0; 122344961713Sgirish 12242e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 12252e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 122644961713Sgirish /* 0x0E01 */ 122744961713Sgirish tx_cfg_l.bits.entx = 1; 122844961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 122944961713Sgirish 123044961713Sgirish /* 0x9101 */ 123144961713Sgirish rx_cfg_l.bits.enrx = 1; 123244961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 123344961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 123444961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 123544961713Sgirish 123644961713Sgirish /* 0x0008 */ 123744961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 123844961713Sgirish 123944961713Sgirish /* Set loopback mode if necessary */ 124044961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 124144961713Sgirish tx_cfg_l.bits.entest = 1; 124244961713Sgirish rx_cfg_l.bits.entest = 1; 124344961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 124444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 124544961713Sgirish ESR_N2_DEV_ADDR, 124644961713Sgirish ESR_N2_TEST_CFG_REG, test_cfg.value)) 124744961713Sgirish != NXGE_OK) 124844961713Sgirish goto fail; 124944961713Sgirish } 125044961713Sgirish 125144961713Sgirish /* Use default PLL value */ 125244961713Sgirish 12532e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 12542e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 125544961713Sgirish 125644961713Sgirish /* 0x0E21 */ 125744961713Sgirish tx_cfg_l.bits.entx = 1; 125844961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 125944961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 126044961713Sgirish 126144961713Sgirish /* 0x9121 */ 126244961713Sgirish rx_cfg_l.bits.enrx = 1; 126344961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 126444961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 126544961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 126644961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 126744961713Sgirish 12682e59129aSraghus if (portn == 0) { 12692e59129aSraghus /* 0x8 */ 12702e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12712e59129aSraghus } 127244961713Sgirish 127344961713Sgirish /* MPY = 0x100 */ 127444961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 127544961713Sgirish 127644961713Sgirish /* Set PLL */ 127744961713Sgirish pll_cfg_l.bits.enpll = 1; 12782e59129aSraghus pll_sts_l.bits.enpll = 1; 127944961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 128044961713Sgirish ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 128144961713Sgirish != NXGE_OK) 128244961713Sgirish goto fail; 12832e59129aSraghus 12842e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 12852e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 12862e59129aSraghus goto fail; 12872e59129aSraghus 12882e59129aSraghus #ifdef NXGE_DEBUG 12892e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12902e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 12912e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12922e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 12932e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 12942e59129aSraghus 12952e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12962e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 12972e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12982e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 12992e59129aSraghus portn, pll_sts_l.value, cfg.value)); 13002e59129aSraghus #endif 13012e59129aSraghus 13022e59129aSraghus /* Set loopback mode if necessary */ 13032e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 13042e59129aSraghus tx_cfg_l.bits.entest = 1; 13052e59129aSraghus rx_cfg_l.bits.entest = 1; 13062e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 13072e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13082e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 13092e59129aSraghus portn, test_cfg.value)); 13102e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 13112e59129aSraghus ESR_N2_DEV_ADDR, 13122e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 13132e59129aSraghus goto fail; 13142e59129aSraghus } 13152e59129aSraghus } 131644961713Sgirish } else { 131744961713Sgirish goto fail; 131844961713Sgirish } 131944961713Sgirish 132044961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 132144961713Sgirish 132244961713Sgirish NXGE_DELAY(20); 132344961713Sgirish 132444961713Sgirish /* init TX channels */ 132544961713Sgirish for (chan = 0; chan < 4; chan++) { 132644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 132744961713Sgirish ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 132844961713Sgirish != NXGE_OK) 132944961713Sgirish goto fail; 133044961713Sgirish 133144961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 133244961713Sgirish ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 133344961713Sgirish != NXGE_OK) 133444961713Sgirish goto fail; 13352e59129aSraghus 13362e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13372e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 13382e59129aSraghus portn, chan, tx_cfg_l.value)); 13392e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13402e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 13412e59129aSraghus portn, chan, tx_cfg_h.value)); 134244961713Sgirish } 134344961713Sgirish 134444961713Sgirish /* init RX channels */ 134544961713Sgirish for (chan = 0; chan < 4; chan++) { 134644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 134744961713Sgirish ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 134844961713Sgirish != NXGE_OK) 134944961713Sgirish goto fail; 135044961713Sgirish 135144961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 135244961713Sgirish ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 135344961713Sgirish != NXGE_OK) 135444961713Sgirish goto fail; 13552e59129aSraghus 13562e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13572e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 13582e59129aSraghus portn, chan, rx_cfg_l.value)); 13592e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13602e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 13612e59129aSraghus portn, chan, rx_cfg_h.value)); 136244961713Sgirish } 136344961713Sgirish 136444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 136544961713Sgirish portn)); 136644961713Sgirish 136744961713Sgirish return (NXGE_OK); 136844961713Sgirish fail: 13692d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13702d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 13712d17280bSsbehera portn)); 137244961713Sgirish 137344961713Sgirish return (status); 137444961713Sgirish } 137544961713Sgirish 137659ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 137744961713Sgirish 137859ac0c16Sdavemq static nxge_status_t 137959ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 138044961713Sgirish { 138144961713Sgirish npi_handle_t handle; 138244961713Sgirish uint8_t portn; 1383321febdeSsbehera int chan, i; 138444961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 138544961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 138644961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 138744961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 138844961713Sgirish uint64_t val; 138944961713Sgirish uint16_t val16l; 139044961713Sgirish uint16_t val16h; 139144961713Sgirish nxge_status_t status = NXGE_OK; 139244961713Sgirish 139344961713Sgirish portn = nxgep->mac.portnum; 139444961713Sgirish 139544961713Sgirish if ((portn != 0) && (portn != 1)) 139644961713Sgirish return (NXGE_OK); 139744961713Sgirish 139859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 139959ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 140044961713Sgirish 140144961713Sgirish handle = nxgep->npi_handle; 140259ac0c16Sdavemq switch (portn) { 140359ac0c16Sdavemq case 0: 14044202ea4bSsbehera /* Reset Serdes */ 14054202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 14064202ea4bSsbehera NXGE_DELAY(20); 14074202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14084202ea4bSsbehera NXGE_DELAY(2000); 14094202ea4bSsbehera 14104202ea4bSsbehera /* Configure Serdes to 10G mode */ 14114202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 14124202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 14134202ea4bSsbehera 141459ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 141559ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 141659ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 141759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 141859ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 141959ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 142059ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 142159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 142259ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 142359ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 142459ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 142559ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 142659ac0c16Sdavemq 142759ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 142859ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 142959ac0c16Sdavemq ESR_REG_WR(handle, 143059ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 143159ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 143259ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 143359ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 143459ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 143559ac0c16Sdavemq } else { 143659ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 143744961713Sgirish } 143859ac0c16Sdavemq break; 143959ac0c16Sdavemq case 1: 14404202ea4bSsbehera /* Reset Serdes */ 14414202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 14424202ea4bSsbehera NXGE_DELAY(20); 14434202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14444202ea4bSsbehera NXGE_DELAY(2000); 14454202ea4bSsbehera 14464202ea4bSsbehera /* Configure Serdes to 10G mode */ 14474202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 14484202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 14494202ea4bSsbehera 145059ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 145159ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 145259ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 145359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 145459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 145559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 145659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 145759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 145859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 145959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 146059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 146159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 146259ac0c16Sdavemq 146359ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 146459ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 146559ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 146659ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 146759ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 146859ac0c16Sdavemq } else { 146959ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 147044961713Sgirish } 147159ac0c16Sdavemq break; 147259ac0c16Sdavemq default: 147359ac0c16Sdavemq /* Nothing to do here */ 147459ac0c16Sdavemq goto done; 147559ac0c16Sdavemq } 147644961713Sgirish 147759ac0c16Sdavemq /* init TX RX channels */ 147859ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 147959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 148159ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 148244961713Sgirish goto fail; 148359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 148559ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 148644961713Sgirish goto fail; 148759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 148959ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 149059ac0c16Sdavemq goto fail; 149159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 149259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 149359ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 149459ac0c16Sdavemq goto fail; 149559ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 149659ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 149759ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 149859ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 149959ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 150059ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 150159ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 150244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 150359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 150459ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 150544961713Sgirish goto fail; 150644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 150759ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 150859ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 150944961713Sgirish goto fail; 151059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 151159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 151259ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 151344961713Sgirish goto fail; 151459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 151559ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 151659ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 151744961713Sgirish goto fail; 151844961713Sgirish } 151944961713Sgirish 152059ac0c16Sdavemq /* Apply Tx core reset */ 152159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 152259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 152359ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 152459ac0c16Sdavemq goto fail; 152559ac0c16Sdavemq 152659ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 152759ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 152859ac0c16Sdavemq NXGE_OK) 152959ac0c16Sdavemq goto fail; 153059ac0c16Sdavemq 153159ac0c16Sdavemq NXGE_DELAY(200); 153259ac0c16Sdavemq 153359ac0c16Sdavemq /* Apply Rx core reset */ 153459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 153559ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 153659ac0c16Sdavemq NXGE_OK) 153759ac0c16Sdavemq goto fail; 153859ac0c16Sdavemq 153959ac0c16Sdavemq NXGE_DELAY(200); 154059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 154159ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 154259ac0c16Sdavemq goto fail; 154359ac0c16Sdavemq 154459ac0c16Sdavemq NXGE_DELAY(200); 154559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 154659ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 154759ac0c16Sdavemq &val16l)) != NXGE_OK) 154859ac0c16Sdavemq goto fail; 154959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 155059ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 155159ac0c16Sdavemq goto fail; 155259ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 155359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1554d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1555d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 1556d81011f0Ssbehera portn, val16l, val16h)); 155759ac0c16Sdavemq } 155859ac0c16Sdavemq 155959ac0c16Sdavemq if (portn == 0) { 1560321febdeSsbehera /* Wait for serdes to be ready */ 1561321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1562321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1563321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 1564321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1565321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 1566321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 1567321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 1568321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 1569321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 1570321febdeSsbehera 1571321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1572321febdeSsbehera else 1573321febdeSsbehera break; 1574321febdeSsbehera } 1575321febdeSsbehera 1576321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1577321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1578321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1579321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 1580321febdeSsbehera goto fail; 158159ac0c16Sdavemq } 158259ac0c16Sdavemq } else if (portn == 1) { 1583321febdeSsbehera /* Wait for serdes to be ready */ 1584321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1585321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1586321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 1587321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1588321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 1589321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 1590321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 1591321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 1592321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 1593321febdeSsbehera 1594321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1595321febdeSsbehera else 1596321febdeSsbehera break; 1597321febdeSsbehera } 1598321febdeSsbehera 1599321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1600321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1601321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1602321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 1603321febdeSsbehera goto fail; 160444961713Sgirish } 160544961713Sgirish } 160644961713Sgirish 160744961713Sgirish done: 160859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 160959ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 161059ac0c16Sdavemq 161144961713Sgirish return (NXGE_OK); 161244961713Sgirish fail: 16132d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 161459ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 161559ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 161644961713Sgirish 161744961713Sgirish return (status); 161844961713Sgirish } 161944961713Sgirish 162059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 162144961713Sgirish 162259ac0c16Sdavemq static nxge_status_t 162359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 162444961713Sgirish { 162559ac0c16Sdavemq npi_handle_t handle; 162659ac0c16Sdavemq uint8_t portn; 1627d81011f0Ssbehera int chan; 1628d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1629d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1630d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 1631d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 163259ac0c16Sdavemq uint64_t val; 1633d81011f0Ssbehera uint16_t val16l; 1634d81011f0Ssbehera uint16_t val16h; 1635d81011f0Ssbehera nxge_status_t status = NXGE_OK; 163644961713Sgirish 163744961713Sgirish portn = nxgep->mac.portnum; 163844961713Sgirish 163959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 164059ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 164144961713Sgirish 164259ac0c16Sdavemq handle = nxgep->npi_handle; 164344961713Sgirish 164459ac0c16Sdavemq switch (portn) { 164559ac0c16Sdavemq case 0: 1646d81011f0Ssbehera /* Assert the reset register */ 1647d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1648d81011f0Ssbehera val |= ESR_RESET_0; 1649d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1650d81011f0Ssbehera 1651d81011f0Ssbehera /* Set the PLL register to 0x79 */ 1652d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1653d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1654d81011f0Ssbehera 1655d81011f0Ssbehera /* Set the control register to 0x249249f */ 1656d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1657d81011f0Ssbehera 1658d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 1659d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1660d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 1661d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1662d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1663d81011f0Ssbehera } else { 1664d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1665d81011f0Ssbehera } 1666d81011f0Ssbehera 1667d81011f0Ssbehera /* Deassert the reset register */ 1668d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1669d81011f0Ssbehera val &= ~ESR_RESET_0; 1670d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 167159ac0c16Sdavemq break; 1672d81011f0Ssbehera 167359ac0c16Sdavemq case 1: 1674d81011f0Ssbehera /* Assert the reset register */ 1675d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1676d81011f0Ssbehera val |= ESR_RESET_1; 1677d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1678d81011f0Ssbehera 1679d81011f0Ssbehera /* Set PLL register to 0x79 */ 1680d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1681d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1682d81011f0Ssbehera 1683d81011f0Ssbehera /* Set the control register to 0x249249f */ 1684d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1685d81011f0Ssbehera 1686d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 1687d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1688d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 1689d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1690d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1691d81011f0Ssbehera } else { 1692d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 1693d81011f0Ssbehera } 1694d81011f0Ssbehera 1695d81011f0Ssbehera /* Deassert the reset register */ 1696d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1697d81011f0Ssbehera val &= ~ESR_RESET_1; 1698d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 169959ac0c16Sdavemq break; 1700d81011f0Ssbehera 170159ac0c16Sdavemq default: 1702d81011f0Ssbehera /* Nothing to do here */ 1703d81011f0Ssbehera goto done; 1704d81011f0Ssbehera } 1705d81011f0Ssbehera 1706d81011f0Ssbehera /* init TX RX channels */ 1707d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 1708d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1709d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1710d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 1711d81011f0Ssbehera goto fail; 1712d81011f0Ssbehera } 1713d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1714d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1715d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 1716d81011f0Ssbehera goto fail; 1717d81011f0Ssbehera } 1718d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1719d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1720d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 1721d81011f0Ssbehera goto fail; 1722d81011f0Ssbehera } 1723d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1724d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1725d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 1726d81011f0Ssbehera goto fail; 1727d81011f0Ssbehera } 1728d81011f0Ssbehera 1729d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 1730d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 1731d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 1732d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 1733d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 1734d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 1735d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 1736d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1737d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1738d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 1739d81011f0Ssbehera goto fail; 1740d81011f0Ssbehera } 1741d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1742d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1743d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 1744d81011f0Ssbehera goto fail; 1745d81011f0Ssbehera } 1746d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1747d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1748d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 1749d81011f0Ssbehera goto fail; 1750d81011f0Ssbehera } 1751d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1752d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1753d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 1754d81011f0Ssbehera goto fail; 1755d81011f0Ssbehera } 1756d81011f0Ssbehera } 1757d81011f0Ssbehera 1758d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1759d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 1760d81011f0Ssbehera goto fail; 1761d81011f0Ssbehera } 1762d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1763d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1764d81011f0Ssbehera goto fail; 1765d81011f0Ssbehera } 1766d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1767d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 1768d81011f0Ssbehera goto fail; 1769d81011f0Ssbehera } 1770d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1771d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 177259ac0c16Sdavemq goto fail; 177344961713Sgirish } 177444961713Sgirish 1775d81011f0Ssbehera /* Apply Tx core reset */ 1776d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1777d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 1778d81011f0Ssbehera goto fail; 1779d81011f0Ssbehera } 1780d81011f0Ssbehera 1781d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1782d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 1783d81011f0Ssbehera NXGE_OK) { 1784d81011f0Ssbehera goto fail; 1785d81011f0Ssbehera } 1786d81011f0Ssbehera 1787d81011f0Ssbehera NXGE_DELAY(200); 1788d81011f0Ssbehera 1789d81011f0Ssbehera /* Apply Rx core reset */ 1790d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1791d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 1792d81011f0Ssbehera NXGE_OK) { 1793d81011f0Ssbehera goto fail; 1794d81011f0Ssbehera } 1795d81011f0Ssbehera 1796d81011f0Ssbehera NXGE_DELAY(200); 1797d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1798d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 1799d81011f0Ssbehera goto fail; 1800d81011f0Ssbehera } 1801d81011f0Ssbehera 1802d81011f0Ssbehera NXGE_DELAY(200); 1803d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1804d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 1805d81011f0Ssbehera goto fail; 1806d81011f0Ssbehera } 1807d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1808d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 1809d81011f0Ssbehera goto fail; 1810d81011f0Ssbehera } 1811d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 1812d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1813d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1814d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 1815d81011f0Ssbehera status = NXGE_ERROR; 1816d81011f0Ssbehera goto fail; 1817d81011f0Ssbehera } 1818d81011f0Ssbehera 1819d81011f0Ssbehera NXGE_DELAY(200); 1820d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1821d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1822d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 1823d81011f0Ssbehera "val 0x%x", portn, val)); 1824d81011f0Ssbehera if (portn == 0) { 1825d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 1826d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 1827d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1828d81011f0Ssbehera "nxge_neptune_serdes_init: " 1829d81011f0Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 1830d81011f0Ssbehera portn, (val & ESR_SIG_P0_BITS_MASK))); 1831d81011f0Ssbehera status = NXGE_ERROR; 1832d81011f0Ssbehera goto fail; 1833d81011f0Ssbehera } 1834d81011f0Ssbehera } else if (portn == 1) { 1835d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 1836d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 1837d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1838d81011f0Ssbehera "nxge_neptune_serdes_init: " 1839d81011f0Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 1840d81011f0Ssbehera portn, (val & ESR_SIG_P1_BITS_MASK))); 1841d81011f0Ssbehera status = NXGE_ERROR; 1842d81011f0Ssbehera goto fail; 1843d81011f0Ssbehera } 1844d81011f0Ssbehera } 1845d81011f0Ssbehera done: 184659ac0c16Sdavemq 184759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 184859ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 184944961713Sgirish return (NXGE_OK); 185059ac0c16Sdavemq fail: 1851d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 185259ac0c16Sdavemq "nxge_1G_serdes_init: " 185359ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 185459ac0c16Sdavemq portn)); 185559ac0c16Sdavemq 1856d81011f0Ssbehera return (status); 185744961713Sgirish } 185844961713Sgirish 18592d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 186044961713Sgirish 186159ac0c16Sdavemq static nxge_status_t 18622d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 186344961713Sgirish { 186444961713Sgirish uint16_t val; 186544961713Sgirish #ifdef NXGE_DEBUG 186614ea4bb7Ssd uint8_t portn; 186744961713Sgirish uint16_t val1; 186844961713Sgirish #endif 186944961713Sgirish uint8_t phy_port_addr; 187044961713Sgirish pmd_tx_control_t tx_ctl; 187144961713Sgirish control_t ctl; 187244961713Sgirish phyxs_control_t phyxs_ctl; 187344961713Sgirish pcs_control_t pcs_ctl; 187444961713Sgirish uint32_t delay = 0; 187544961713Sgirish optics_dcntr_t op_ctr; 187644961713Sgirish nxge_status_t status = NXGE_OK; 187714ea4bb7Ssd #ifdef NXGE_DEBUG 187844961713Sgirish portn = nxgep->mac.portnum; 187914ea4bb7Ssd #endif 18802d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 188159ac0c16Sdavemq portn)); 188244961713Sgirish 188359ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 188459ac0c16Sdavemq 188559ac0c16Sdavemq /* Reset the transceiver */ 188659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 188759ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 188859ac0c16Sdavemq goto fail; 188959ac0c16Sdavemq 189059ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 189159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 189259ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 189359ac0c16Sdavemq goto fail; 189459ac0c16Sdavemq 189559ac0c16Sdavemq do { 189659ac0c16Sdavemq drv_usecwait(500); 189759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 189859ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 189959ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 190059ac0c16Sdavemq goto fail; 190159ac0c16Sdavemq delay++; 190259ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 190359ac0c16Sdavemq if (delay == 100) { 190459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 190559ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 190659ac0c16Sdavemq status = NXGE_ERROR; 190759ac0c16Sdavemq goto fail; 190859ac0c16Sdavemq } 190944961713Sgirish 191059ac0c16Sdavemq /* Set to 0x7FBF */ 191159ac0c16Sdavemq ctl.value = 0; 191259ac0c16Sdavemq ctl.bits.res1 = 0x3F; 191359ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 191459ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 191559ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 191659ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 191759ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 191859ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 191959ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 192059ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 192159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 192259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 192359ac0c16Sdavemq != NXGE_OK) 192459ac0c16Sdavemq goto fail; 192559ac0c16Sdavemq 192659ac0c16Sdavemq /* Set to 0x164 */ 192759ac0c16Sdavemq tx_ctl.value = 0; 192859ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 192959ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 193059ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 193159ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 193259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 193359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 193459ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 193559ac0c16Sdavemq goto fail; 193644961713Sgirish /* 193759ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 193859ac0c16Sdavemq * back these registers twice after written. 193944961713Sgirish */ 194059ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 194159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 194259ac0c16Sdavemq != NXGE_OK) 194359ac0c16Sdavemq goto fail; 194444961713Sgirish 194559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 194659ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 194759ac0c16Sdavemq != NXGE_OK) 194859ac0c16Sdavemq goto fail; 194944961713Sgirish 195059ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 195159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 195259ac0c16Sdavemq != NXGE_OK) 195359ac0c16Sdavemq goto fail; 195444961713Sgirish 195559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 195659ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 195759ac0c16Sdavemq != NXGE_OK) 195859ac0c16Sdavemq goto fail; 195944961713Sgirish 196059ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 196159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 196259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 196359ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 196459ac0c16Sdavemq goto fail; 1965cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 1966cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 1967cb9d3ae6Smisaki } else { 1968cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 1969cb9d3ae6Smisaki } 197059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 197159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 197259ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 197359ac0c16Sdavemq goto fail; 197444961713Sgirish 197559ac0c16Sdavemq NXGE_DELAY(1000000); 197644961713Sgirish 197759ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 197859ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 197959ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 198059ac0c16Sdavemq != NXGE_OK) 198159ac0c16Sdavemq goto fail; 198259ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 198359ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 198459ac0c16Sdavemq else 198559ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 198659ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 198759ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 198859ac0c16Sdavemq != NXGE_OK) 198959ac0c16Sdavemq goto fail; 199044961713Sgirish 199159ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 199259ac0c16Sdavemq if (status != NXGE_OK) 199359ac0c16Sdavemq goto fail; 199459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 199559ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 199659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 199759ac0c16Sdavemq if (status != NXGE_OK) 199859ac0c16Sdavemq goto fail; 199959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 200059ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 200159ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 200259ac0c16Sdavemq if (status != NXGE_OK) 200359ac0c16Sdavemq goto fail; 200459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 200559ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 200644961713Sgirish 200759ac0c16Sdavemq #ifdef NXGE_DEBUG 200859ac0c16Sdavemq /* Diagnose link issue if link is not up */ 200959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 201059ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 201159ac0c16Sdavemq &val); 201259ac0c16Sdavemq if (status != NXGE_OK) 201359ac0c16Sdavemq goto fail; 201444961713Sgirish 201559ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 201644961713Sgirish BCM8704_USER_DEV3_ADDR, 201759ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 201859ac0c16Sdavemq &val); 201959ac0c16Sdavemq if (status != NXGE_OK) 202059ac0c16Sdavemq goto fail; 202144961713Sgirish 202259ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 202344961713Sgirish BCM8704_USER_DEV3_ADDR, 202459ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 202559ac0c16Sdavemq &val1); 202659ac0c16Sdavemq if (status != NXGE_OK) 202759ac0c16Sdavemq goto fail; 202844961713Sgirish 202959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 203044961713Sgirish BCM8704_USER_DEV3_ADDR, 203159ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 203259ac0c16Sdavemq &val1); 203359ac0c16Sdavemq if (status != NXGE_OK) 203459ac0c16Sdavemq goto fail; 203544961713Sgirish 203659ac0c16Sdavemq if (val != 0x3FC) { 203759ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 203859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 203959ac0c16Sdavemq "Cable not connected to peer or bad" 204059ac0c16Sdavemq " cable on port<%d>\n", portn)); 204159ac0c16Sdavemq } else if (val == 0x639C) { 204259ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 204359ac0c16Sdavemq "Optical module (XFP) is bad or absent" 204459ac0c16Sdavemq " on port<%d>\n", portn)); 204559ac0c16Sdavemq } 204659ac0c16Sdavemq } 204759ac0c16Sdavemq #endif 204844961713Sgirish 20492d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 20502d17280bSsbehera portn)); 20512d17280bSsbehera return (NXGE_OK); 20522d17280bSsbehera 20532d17280bSsbehera fail: 20542d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20552d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 20562d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 20572d17280bSsbehera return (NXGE_ERROR); 20582d17280bSsbehera } 20592d17280bSsbehera 20602d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 20612d17280bSsbehera 20622d17280bSsbehera static nxge_status_t 20632d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 20642d17280bSsbehera { 20652d17280bSsbehera uint8_t phy_port_addr; 20662d17280bSsbehera phyxs_control_t phyxs_ctl; 20672d17280bSsbehera pcs_control_t pcs_ctl; 20682d17280bSsbehera uint32_t delay = 0; 20692d17280bSsbehera optics_dcntr_t op_ctr; 20702d17280bSsbehera nxge_status_t status = NXGE_OK; 20712d17280bSsbehera #ifdef NXGE_DEBUG 20722d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 20732d17280bSsbehera #endif 20742d17280bSsbehera 20752d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 20762d17280bSsbehera portn)); 20772d17280bSsbehera 20782d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 20792d17280bSsbehera 20802d17280bSsbehera /* Reset the transceiver */ 20812d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20822d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 20832d17280bSsbehera goto fail; 20842d17280bSsbehera 20852d17280bSsbehera phyxs_ctl.bits.reset = 1; 20862d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20872d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 20882d17280bSsbehera goto fail; 20892d17280bSsbehera do { 20902d17280bSsbehera drv_usecwait(500); 20912d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20922d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 20932d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 20942d17280bSsbehera goto fail; 20952d17280bSsbehera delay++; 20962d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 20972d17280bSsbehera 20982d17280bSsbehera if (delay == 100) { 20992d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21002d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 21012d17280bSsbehera status = NXGE_ERROR; 21022d17280bSsbehera goto fail; 21032d17280bSsbehera } 21042d17280bSsbehera 21052d17280bSsbehera NXGE_DELAY(1000000); 21062d17280bSsbehera 21072d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 21082d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21092d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 21102d17280bSsbehera != NXGE_OK) 21112d17280bSsbehera goto fail; 21122d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 21132d17280bSsbehera pcs_ctl.bits.loopback = 1; 21142d17280bSsbehera else 21152d17280bSsbehera pcs_ctl.bits.loopback = 0; 21162d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21172d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 21182d17280bSsbehera != NXGE_OK) 21192d17280bSsbehera goto fail; 21202d17280bSsbehera 21212d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 21222d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21232d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21242d17280bSsbehera &op_ctr.value)) != NXGE_OK) 21252d17280bSsbehera goto fail; 21262d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 21272d17280bSsbehera op_ctr.bits.res2 = 0x1; 21282d17280bSsbehera 21292d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21302d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21312d17280bSsbehera op_ctr.value)) != NXGE_OK) 21322d17280bSsbehera goto fail; 21332d17280bSsbehera 21342d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 21352d17280bSsbehera portn)); 21362d17280bSsbehera return (NXGE_OK); 21372d17280bSsbehera 21382d17280bSsbehera fail: 21392d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21402d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 21412d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 21422d17280bSsbehera return (status); 21432d17280bSsbehera } 21442d17280bSsbehera 21452d17280bSsbehera /* Initialize the 10G Transceiver */ 21462d17280bSsbehera 21472d17280bSsbehera static nxge_status_t 21482d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 21492d17280bSsbehera { 21502d17280bSsbehera p_nxge_stats_t statsp; 21511bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 21522d17280bSsbehera nxge_status_t status = NXGE_OK; 21532d17280bSsbehera #ifdef NXGE_DEBUG 21542d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 21552d17280bSsbehera #endif 21562d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 21572d17280bSsbehera portn)); 21582d17280bSsbehera 21592d17280bSsbehera statsp = nxgep->statsp; 21602d17280bSsbehera 21612d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_SERDES) { 21622d17280bSsbehera goto done; 21632d17280bSsbehera } 21642d17280bSsbehera 21652d17280bSsbehera /* Disable Link LEDs */ 21662d17280bSsbehera if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 21672d17280bSsbehera goto fail; 21682d17280bSsbehera 21692d17280bSsbehera /* Set Clause 45 */ 21702d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 21712d17280bSsbehera 21722d17280bSsbehera switch (nxgep->chip_id) { 21732d17280bSsbehera case BCM8704_CHIP_ID: 21742d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21752d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 21762d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 21772d17280bSsbehera break; 21782d17280bSsbehera case BCM8706_CHIP_ID: 21792d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21802d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 21812d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 21822d17280bSsbehera break; 21832d17280bSsbehera default: 21842d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 21852d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 21862d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 21872d17280bSsbehera goto fail; 21882d17280bSsbehera } 21892d17280bSsbehera 21902d17280bSsbehera if (status != NXGE_OK) { 21912d17280bSsbehera goto fail; 21922d17280bSsbehera } 21932e59129aSraghus done: 219459ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 219559ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 21961bd6825cSml statsp->mac_stats.adv_cap_asmpause = 21971bd6825cSml param_arr[param_anar_asmpause].value; 21981bd6825cSml statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 219944961713Sgirish 220059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 220159ac0c16Sdavemq portn)); 220259ac0c16Sdavemq return (NXGE_OK); 220344961713Sgirish 220459ac0c16Sdavemq fail: 22052d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 220659ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 22072d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 22082d17280bSsbehera return (NXGE_ERROR); 220959ac0c16Sdavemq } 221044961713Sgirish 221159ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 221244961713Sgirish 221359ac0c16Sdavemq static nxge_status_t 221459ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 221559ac0c16Sdavemq { 221659ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 221759ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 221859ac0c16Sdavemq nxge_status_t status = NXGE_OK; 221944961713Sgirish 22202e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 22212e59129aSraghus statsp->mac_stats.cap_1000fdx = 22222e59129aSraghus param_arr[param_anar_1000fdx].value; 22232e59129aSraghus goto done; 22242e59129aSraghus } 22252e59129aSraghus 222659ac0c16Sdavemq /* Set Clause 22 */ 222759ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 222844961713Sgirish 222959ac0c16Sdavemq /* Set capability flags */ 223059ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 22312e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 22322e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 22332e59129aSraghus statsp->mac_stats.cap_100fdx = 22342e59129aSraghus param_arr[param_anar_100fdx].value; 22352e59129aSraghus statsp->mac_stats.cap_10fdx = 22362e59129aSraghus param_arr[param_anar_10fdx].value; 22372e59129aSraghus } 223844961713Sgirish 223959ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 22402e59129aSraghus done: 224159ac0c16Sdavemq return (status); 224259ac0c16Sdavemq } 224359ac0c16Sdavemq 224459ac0c16Sdavemq /* Initialize transceiver */ 224559ac0c16Sdavemq 224659ac0c16Sdavemq nxge_status_t 224759ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 224859ac0c16Sdavemq { 224959ac0c16Sdavemq p_nxge_stats_t statsp; 225059ac0c16Sdavemq #ifdef NXGE_DEBUG 225159ac0c16Sdavemq uint8_t portn; 225244961713Sgirish #endif 225344961713Sgirish 225459ac0c16Sdavemq nxge_status_t status = NXGE_OK; 225559ac0c16Sdavemq #ifdef NXGE_DEBUG 225659ac0c16Sdavemq portn = nxgep->mac.portnum; 225759ac0c16Sdavemq #endif 225859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 225959ac0c16Sdavemq statsp = nxgep->statsp; 226044961713Sgirish 226159ac0c16Sdavemq /* 226259ac0c16Sdavemq * Initialize the xcvr statistics. 226359ac0c16Sdavemq */ 226459ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 226559ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 226659ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 226759ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 226859ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 226959ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 227059ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 227159ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 227259ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 227359ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 227459ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 227559ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 227659ac0c16Sdavemq 227759ac0c16Sdavemq /* 227859ac0c16Sdavemq * Initialize the link statistics. 227959ac0c16Sdavemq */ 228059ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 228159ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 228259ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 228344961713Sgirish 228459ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 228559ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 228659ac0c16Sdavemq if (status != NXGE_OK) 228744961713Sgirish goto fail; 228859ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 228944961713Sgirish } 229044961713Sgirish 229159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 229259ac0c16Sdavemq portn)); 229344961713Sgirish return (NXGE_OK); 229444961713Sgirish 229544961713Sgirish fail: 229644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 229759ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 229859ac0c16Sdavemq portn)); 229944961713Sgirish return (status); 230044961713Sgirish } 230144961713Sgirish 23022e59129aSraghus /* Look for transceiver type */ 23032e59129aSraghus 23042e59129aSraghus nxge_status_t 23052e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 23062e59129aSraghus { 2307d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 2308d81011f0Ssbehera nxgep->mac.portnum)); 23092e59129aSraghus 23102e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 23112e59129aSraghus return (NXGE_ERROR); 23122e59129aSraghus 23132e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 23142e59129aSraghus return (NXGE_ERROR); 23152e59129aSraghus 23162e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 23172e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 23182e59129aSraghus return (NXGE_OK); 23192e59129aSraghus } 232044961713Sgirish 232144961713Sgirish /* Initialize the TxMAC sub-block */ 232244961713Sgirish 232344961713Sgirish nxge_status_t 232444961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 232544961713Sgirish { 232644961713Sgirish npi_attr_t ap; 232744961713Sgirish uint8_t portn; 232844961713Sgirish nxge_port_mode_t portmode; 232944961713Sgirish nxge_port_t portt; 233044961713Sgirish npi_handle_t handle; 233144961713Sgirish npi_status_t rs = NPI_SUCCESS; 233244961713Sgirish 233344961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 233444961713Sgirish portt = nxgep->mac.porttype; 233544961713Sgirish handle = nxgep->npi_handle; 233644961713Sgirish portmode = nxgep->mac.portmode; 233744961713Sgirish 233844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 233944961713Sgirish portn)); 234044961713Sgirish /* Set Max and Min Frame Size */ 23411bd6825cSml /* 23421bd6825cSml * Use maxframesize to configure the hardware maxframe size 23431bd6825cSml * and minframesize to configure the hardwae minframe size. 23441bd6825cSml */ 23451bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 23461bd6825cSml "==> nxge_tx_mac_init: port<%d> " 23471bd6825cSml "min framesize %d max framesize %d ", 23481bd6825cSml nxgep->mac.minframesize, 23491bd6825cSml nxgep->mac.maxframesize, 23501bd6825cSml portn)); 235144961713Sgirish 23521bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 23531bd6825cSml MAC_PORT_FRAME_SIZE, 23541bd6825cSml nxgep->mac.minframesize, 23551bd6825cSml nxgep->mac.maxframesize, 23561bd6825cSml rs); 235744961713Sgirish if (rs != NPI_SUCCESS) 235844961713Sgirish goto fail; 235944961713Sgirish 236044961713Sgirish if (portt == PORT_TYPE_XMAC) { 236144961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 236244961713Sgirish 0)) != NPI_SUCCESS) 236344961713Sgirish goto fail; 236444961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 236544961713Sgirish if ((portmode == PORT_10G_FIBER) || 23662e59129aSraghus (portmode == PORT_10G_COPPER) || 23672e59129aSraghus (portmode == PORT_10G_SERDES)) { 236844961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 236944961713Sgirish XGMII_IPG_12_15, rs); 237044961713Sgirish if (rs != NPI_SUCCESS) 237144961713Sgirish goto fail; 237244961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 237344961713Sgirish } else { 237444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 237544961713Sgirish MII_GMII_IPG_12, rs); 237644961713Sgirish if (rs != NPI_SUCCESS) 237744961713Sgirish goto fail; 237844961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 237944961713Sgirish } 238044961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 238144961713Sgirish CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 238244961713Sgirish goto fail; 238344961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 238444961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 238544961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 238644961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 238744961713Sgirish 238844961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 238944961713Sgirish != NPI_SUCCESS) 239044961713Sgirish goto fail; 239144961713Sgirish 239244961713Sgirish } else { 239344961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 239444961713Sgirish 0)) != NPI_SUCCESS) 239544961713Sgirish goto fail; 239644961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 239744961713Sgirish 239844961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 239944961713Sgirish rs); 240044961713Sgirish if (rs != NPI_SUCCESS) 240144961713Sgirish goto fail; 240244961713Sgirish nxgep->mac.ctrltype = 0x8808; 240344961713Sgirish 240444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 240544961713Sgirish if (rs != NPI_SUCCESS) 240644961713Sgirish goto fail; 240744961713Sgirish nxgep->mac.pa_size = 0x7; 240844961713Sgirish 240944961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 241044961713Sgirish CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 241144961713Sgirish goto fail; 241244961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 241344961713Sgirish } 241444961713Sgirish 241544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 241644961713Sgirish portn)); 241744961713Sgirish 241844961713Sgirish return (NXGE_OK); 241944961713Sgirish fail: 242044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 242144961713Sgirish "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 242244961713Sgirish portn)); 242344961713Sgirish 242444961713Sgirish return (NXGE_ERROR | rs); 242544961713Sgirish } 242644961713Sgirish 2427*678453a8Sspeer int 2428*678453a8Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep) 2429*678453a8Sspeer { 2430*678453a8Sspeer int rdc_tbl; 2431*678453a8Sspeer 2432*678453a8Sspeer /* 2433*678453a8Sspeer * Get an RDC table (version 0). 2434*678453a8Sspeer */ 2435*678453a8Sspeer if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) { 2436*678453a8Sspeer NXGE_ERROR_MSG((nxgep, OBP_CTL, 2437*678453a8Sspeer "nxge_hio_hostinfo_get_rdc_table: " 2438*678453a8Sspeer "there are no free RDC tables!")); 2439*678453a8Sspeer return (EBUSY); 2440*678453a8Sspeer } 2441*678453a8Sspeer 2442*678453a8Sspeer return (rdc_tbl); 2443*678453a8Sspeer } 2444*678453a8Sspeer 2445*678453a8Sspeer /* 2446*678453a8Sspeer * nxge_hio_hostinfo_init 2447*678453a8Sspeer * 2448*678453a8Sspeer * Initialize an alternate MAC address, and bind a macrdctbln to it. 2449*678453a8Sspeer * 2450*678453a8Sspeer * Arguments: 2451*678453a8Sspeer * nxge 2452*678453a8Sspeer * vr The Virtualization Region 2453*678453a8Sspeer * macaddr The alternate MAC address 2454*678453a8Sspeer * 2455*678453a8Sspeer * Notes: 2456*678453a8Sspeer * 1. Find & bind an RDC table to <nxge>. 2457*678453a8Sspeer * 2. Program an alternate MAC address (<macaddr>). 2458*678453a8Sspeer * 3. Bind the RDC table to <macaddr>. 2459*678453a8Sspeer * 2460*678453a8Sspeer * Context: 2461*678453a8Sspeer * Service domain 2462*678453a8Sspeer * 2463*678453a8Sspeer * Side Effects: 2464*678453a8Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 2465*678453a8Sspeer * vr->slot & vr->altmac 2466*678453a8Sspeer * 2467*678453a8Sspeer */ 2468*678453a8Sspeer int 2469*678453a8Sspeer nxge_hio_hostinfo_init( 2470*678453a8Sspeer nxge_t *nxge, 2471*678453a8Sspeer nxge_hio_vr_t *vr, /* Virtualization Region */ 2472*678453a8Sspeer ether_addr_t *macaddr) /* The alternate MAC address */ 2473*678453a8Sspeer { 2474*678453a8Sspeer int rdc_tbl, slot; 2475*678453a8Sspeer 2476*678453a8Sspeer nxge_class_pt_cfg_t *class; 2477*678453a8Sspeer hostinfo_t mac_rdc; 2478*678453a8Sspeer npi_mac_addr_t altmac; 2479*678453a8Sspeer nxge_mmac_t *mmac_info; 2480*678453a8Sspeer nxge_rdc_grp_t *group; 2481*678453a8Sspeer uint8_t *addr = (uint8_t *)macaddr; 2482*678453a8Sspeer 2483*678453a8Sspeer mutex_enter(nxge->genlock); 2484*678453a8Sspeer 2485*678453a8Sspeer rdc_tbl = vr->rdc_tbl; 2486*678453a8Sspeer 2487*678453a8Sspeer /* Initialize the NXGE RDC table data structure. */ 2488*678453a8Sspeer group = &nxge->pt_config.rdc_grps[rdc_tbl]; 2489*678453a8Sspeer group->port = NXGE_GET_PORT_NUM(nxge->function_num); 2490*678453a8Sspeer group->config_method = RDC_TABLE_ENTRY_METHOD_REP; 2491*678453a8Sspeer group->flag = 1; /* This group has been configured. */ 2492*678453a8Sspeer 2493*678453a8Sspeer mmac_info = &nxge->nxge_mmac_info; 2494*678453a8Sspeer 2495*678453a8Sspeer /* 2496*678453a8Sspeer * Are there free slots. 2497*678453a8Sspeer */ 2498*678453a8Sspeer if (mmac_info->naddrfree == 0) { 2499*678453a8Sspeer mutex_exit(nxge->genlock); 2500*678453a8Sspeer return (ENOSPC); 2501*678453a8Sspeer } 2502*678453a8Sspeer 2503*678453a8Sspeer /* 2504*678453a8Sspeer * The vswitch has already added this MAC address. 2505*678453a8Sspeer * Find its assigned slot. 2506*678453a8Sspeer */ 2507*678453a8Sspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 2508*678453a8Sspeer for (slot = mmac_info->num_factory_mmac + 1; 2509*678453a8Sspeer slot <= mmac_info->num_mmac; slot++) { 2510*678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 2511*678453a8Sspeer break; 2512*678453a8Sspeer } 2513*678453a8Sspeer if (slot > mmac_info->num_mmac) { 2514*678453a8Sspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 2515*678453a8Sspeer slot++) { 2516*678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags 2517*678453a8Sspeer & MMAC_SLOT_USED)) 2518*678453a8Sspeer break; 2519*678453a8Sspeer } 2520*678453a8Sspeer } 2521*678453a8Sspeer } else { 2522*678453a8Sspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 2523*678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 2524*678453a8Sspeer break; 2525*678453a8Sspeer } 2526*678453a8Sspeer } 2527*678453a8Sspeer 2528*678453a8Sspeer ASSERT(slot <= mmac_info->num_mmac); 2529*678453a8Sspeer vr->slot = slot; 2530*678453a8Sspeer slot = vr->slot - 1; 2531*678453a8Sspeer 2532*678453a8Sspeer /* 2533*678453a8Sspeer * Programm the mac address. 2534*678453a8Sspeer */ 2535*678453a8Sspeer altmac.w2 = (((uint16_t)addr[0]) << 8) | 2536*678453a8Sspeer (((uint16_t)addr[1]) & 0x0ff); 2537*678453a8Sspeer altmac.w1 = (((uint16_t)addr[2]) << 8) | 2538*678453a8Sspeer (((uint16_t)addr[3]) & 0x0ff); 2539*678453a8Sspeer altmac.w0 = (((uint16_t)addr[4]) << 8) | 2540*678453a8Sspeer (((uint16_t)addr[5]) & 0x0ff); 2541*678453a8Sspeer 2542*678453a8Sspeer if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET, 2543*678453a8Sspeer nxge->function_num, slot, &altmac) != NPI_SUCCESS) { 2544*678453a8Sspeer mutex_exit(nxge->genlock); 2545*678453a8Sspeer return (EIO); 2546*678453a8Sspeer } 2547*678453a8Sspeer 2548*678453a8Sspeer /* 2549*678453a8Sspeer * Associate <rdc_tbl> with this MAC address slot. 2550*678453a8Sspeer */ 2551*678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2552*678453a8Sspeer 2553*678453a8Sspeer /* Update this variable. */ 2554*678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2555*678453a8Sspeer class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl; 2556*678453a8Sspeer 2557*678453a8Sspeer mac_rdc.value = 0; 2558*678453a8Sspeer mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl; 2559*678453a8Sspeer mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr; 2560*678453a8Sspeer /* <mpr_npr> had better be 1! */ 2561*678453a8Sspeer 2562*678453a8Sspeer /* Program the RDC table. */ 2563*678453a8Sspeer if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET, 2564*678453a8Sspeer nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) { 2565*678453a8Sspeer mutex_exit(nxge->genlock); 2566*678453a8Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 2567*678453a8Sspeer return (EIO); 2568*678453a8Sspeer } 2569*678453a8Sspeer 2570*678453a8Sspeer if (nxge->mac.portnum != XMAC_PORT_0 && 2571*678453a8Sspeer nxge->mac.portnum != XMAC_PORT_1) 2572*678453a8Sspeer slot++; 2573*678453a8Sspeer 2574*678453a8Sspeer /* (Re-)enable the MAC address. */ 2575*678453a8Sspeer (void) npi_mac_altaddr_enable( 2576*678453a8Sspeer nxge->npi_handle, nxge->mac.portnum, slot); 2577*678453a8Sspeer 2578*678453a8Sspeer bcopy(macaddr, vr->altmac, sizeof (vr->altmac)); 2579*678453a8Sspeer 2580*678453a8Sspeer /* 2581*678453a8Sspeer * Update mmac 2582*678453a8Sspeer */ 2583*678453a8Sspeer bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL); 2584*678453a8Sspeer mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED; 2585*678453a8Sspeer mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR; 2586*678453a8Sspeer mmac_info->naddrfree--; 2587*678453a8Sspeer nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE); 2588*678453a8Sspeer 2589*678453a8Sspeer mutex_exit(nxge->genlock); 2590*678453a8Sspeer return (0); 2591*678453a8Sspeer } 2592*678453a8Sspeer 2593*678453a8Sspeer /* 2594*678453a8Sspeer * nxge_hio_hostinfo_uninit 2595*678453a8Sspeer * 2596*678453a8Sspeer * Uninitialize an alternate MAC address. 2597*678453a8Sspeer * 2598*678453a8Sspeer * Arguments: 2599*678453a8Sspeer * nxge 2600*678453a8Sspeer * vr The Virtualization Region 2601*678453a8Sspeer * 2602*678453a8Sspeer * Notes: 2603*678453a8Sspeer * 1. Remove the VR's alternate MAC address. 2604*678453a8Sspeer * 1. Free (unbind) the RDC table allocated to this VR. 2605*678453a8Sspeer * 2606*678453a8Sspeer * Context: 2607*678453a8Sspeer * Service domain 2608*678453a8Sspeer * 2609*678453a8Sspeer * Side Effects: 2610*678453a8Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 2611*678453a8Sspeer * 2612*678453a8Sspeer */ 2613*678453a8Sspeer void 2614*678453a8Sspeer nxge_hio_hostinfo_uninit( 2615*678453a8Sspeer nxge_t *nxge, 2616*678453a8Sspeer nxge_hio_vr_t *vr) 2617*678453a8Sspeer { 2618*678453a8Sspeer nxge_class_pt_cfg_t *class; 2619*678453a8Sspeer 2620*678453a8Sspeer (void) npi_mac_altaddr_disable( 2621*678453a8Sspeer nxge->npi_handle, nxge->mac.portnum, vr->slot); 2622*678453a8Sspeer 2623*678453a8Sspeer /* Set this variable to its default. */ 2624*678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2625*678453a8Sspeer class->mac_host_info[vr->slot].rdctbl = 2626*678453a8Sspeer nxge->pt_config.hw_config.def_mac_rxdma_grpid; 2627*678453a8Sspeer 2628*678453a8Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 2629*678453a8Sspeer vr->slot = -1; 2630*678453a8Sspeer 2631*678453a8Sspeer (void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl); 2632*678453a8Sspeer vr->rdc_tbl = -1; 2633*678453a8Sspeer } 2634*678453a8Sspeer 263544961713Sgirish /* Initialize the RxMAC sub-block */ 263644961713Sgirish 263744961713Sgirish nxge_status_t 263844961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 263944961713Sgirish { 264044961713Sgirish npi_attr_t ap; 264144961713Sgirish uint32_t i; 264244961713Sgirish uint16_t hashtab_e; 264344961713Sgirish p_hash_filter_t hash_filter; 264444961713Sgirish nxge_port_t portt; 264544961713Sgirish uint8_t portn; 264644961713Sgirish npi_handle_t handle; 264744961713Sgirish npi_status_t rs = NPI_SUCCESS; 264844961713Sgirish uint16_t *addr16p; 264944961713Sgirish uint16_t addr0, addr1, addr2; 265044961713Sgirish xmac_rx_config_t xconfig; 265144961713Sgirish bmac_rx_config_t bconfig; 265244961713Sgirish 265344961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 265444961713Sgirish 265544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 265644961713Sgirish portn)); 265744961713Sgirish handle = nxgep->npi_handle; 265844961713Sgirish portt = nxgep->mac.porttype; 265944961713Sgirish 266044961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 266144961713Sgirish addr0 = ntohs(addr16p[2]); 266244961713Sgirish addr1 = ntohs(addr16p[1]); 266344961713Sgirish addr2 = ntohs(addr16p[0]); 266444961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 266544961713Sgirish rs); 266644961713Sgirish 266744961713Sgirish if (rs != NPI_SUCCESS) 266844961713Sgirish goto fail; 266944961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 267044961713Sgirish if (rs != NPI_SUCCESS) 267144961713Sgirish goto fail; 267244961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 267344961713Sgirish if (rs != NPI_SUCCESS) 267444961713Sgirish goto fail; 267544961713Sgirish 267644961713Sgirish /* 267744961713Sgirish * Load the multicast hash filter bits. 267844961713Sgirish */ 267944961713Sgirish hash_filter = nxgep->hash_filter; 268044961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 268144961713Sgirish if (hash_filter != NULL) { 268244961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 268344961713Sgirish (NMCFILTER_REGS - 1) - i]; 268444961713Sgirish } else { 268544961713Sgirish hashtab_e = 0; 268644961713Sgirish } 268744961713Sgirish 268844961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 268944961713Sgirish (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 269044961713Sgirish goto fail; 269144961713Sgirish } 269244961713Sgirish 269344961713Sgirish if (portt == PORT_TYPE_XMAC) { 269444961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 269544961713Sgirish 0)) != NPI_SUCCESS) 269644961713Sgirish goto fail; 269744961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 269844961713Sgirish 269944961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 270044961713Sgirish 270144961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 2702a3c5bd6dSspeer CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 2703a3c5bd6dSspeer ~CFG_XMAC_RX_STRIP_CRC; 270444961713Sgirish 270544961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 270644961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 270744961713Sgirish 270844961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 270944961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 271044961713Sgirish 271144961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 271244961713Sgirish 271344961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 271444961713Sgirish xconfig)) != NPI_SUCCESS) 271544961713Sgirish goto fail; 271644961713Sgirish nxgep->mac.rx_config = xconfig; 271744961713Sgirish 271844961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 271944961713Sgirish 272044961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 272144961713Sgirish != NPI_SUCCESS) 272244961713Sgirish goto fail; 272344961713Sgirish } else { 272444961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 272544961713Sgirish 272644961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 272744961713Sgirish 0) != NPI_SUCCESS) 272844961713Sgirish goto fail; 272944961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 273044961713Sgirish 2731a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 2732a3c5bd6dSspeer ~CFG_BMAC_RX_STRIP_CRC; 273344961713Sgirish 273444961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 273544961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 273644961713Sgirish 273744961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 273844961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 273944961713Sgirish 274044961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 274144961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 274244961713Sgirish bconfig)) != NPI_SUCCESS) 274344961713Sgirish goto fail; 274444961713Sgirish nxgep->mac.rx_config = bconfig; 274544961713Sgirish 274644961713Sgirish /* Always enable comparison of mac unique address */ 274744961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 274844961713Sgirish != NPI_SUCCESS) 274944961713Sgirish goto fail; 275044961713Sgirish } 275144961713Sgirish 275244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 275344961713Sgirish portn)); 275444961713Sgirish 275544961713Sgirish return (NXGE_OK); 275644961713Sgirish 275744961713Sgirish fail: 275844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 275944961713Sgirish "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 276044961713Sgirish portn)); 276144961713Sgirish 276244961713Sgirish return (NXGE_ERROR | rs); 276344961713Sgirish } 276444961713Sgirish 276544961713Sgirish /* Enable TXMAC */ 276644961713Sgirish 276744961713Sgirish nxge_status_t 276844961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 276944961713Sgirish { 277044961713Sgirish npi_handle_t handle; 277144961713Sgirish npi_status_t rs = NPI_SUCCESS; 277244961713Sgirish nxge_status_t status = NXGE_OK; 277344961713Sgirish 277444961713Sgirish handle = nxgep->npi_handle; 277544961713Sgirish 277644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 277744961713Sgirish nxgep->mac.portnum)); 277844961713Sgirish 277944961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 278044961713Sgirish goto fail; 278144961713Sgirish 278244961713Sgirish /* based on speed */ 278344961713Sgirish nxgep->msg_min = ETHERMIN; 278444961713Sgirish 278544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 278644961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 278744961713Sgirish CFG_XMAC_TX)) != NPI_SUCCESS) 278844961713Sgirish goto fail; 278944961713Sgirish } else { 279044961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 279144961713Sgirish CFG_BMAC_TX)) != NPI_SUCCESS) 279244961713Sgirish goto fail; 279344961713Sgirish } 279444961713Sgirish 279544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 279644961713Sgirish nxgep->mac.portnum)); 279744961713Sgirish 279844961713Sgirish return (NXGE_OK); 279944961713Sgirish fail: 280044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280144961713Sgirish "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 280244961713Sgirish nxgep->mac.portnum)); 280344961713Sgirish if (rs != NPI_SUCCESS) 280444961713Sgirish return (NXGE_ERROR | rs); 280544961713Sgirish else 280644961713Sgirish return (status); 280744961713Sgirish } 280844961713Sgirish 280944961713Sgirish /* Disable TXMAC */ 281044961713Sgirish 281144961713Sgirish nxge_status_t 281244961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 281344961713Sgirish { 281444961713Sgirish npi_handle_t handle; 281544961713Sgirish npi_status_t rs = NPI_SUCCESS; 281644961713Sgirish 2817*678453a8Sspeer if (isLDOMguest(nxgep)) 2818*678453a8Sspeer return (NXGE_OK); 2819*678453a8Sspeer 282044961713Sgirish handle = nxgep->npi_handle; 282144961713Sgirish 282244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 282344961713Sgirish nxgep->mac.portnum)); 282444961713Sgirish 282544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 282644961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 282744961713Sgirish nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 282844961713Sgirish goto fail; 282944961713Sgirish } else { 283044961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 283144961713Sgirish nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 283244961713Sgirish goto fail; 283344961713Sgirish } 283444961713Sgirish 283544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 283644961713Sgirish nxgep->mac.portnum)); 283744961713Sgirish return (NXGE_OK); 283844961713Sgirish fail: 283944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 284044961713Sgirish "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 284144961713Sgirish nxgep->mac.portnum)); 284244961713Sgirish return (NXGE_ERROR | rs); 284344961713Sgirish } 284444961713Sgirish 284544961713Sgirish /* Enable RXMAC */ 284644961713Sgirish 284744961713Sgirish nxge_status_t 284844961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 284944961713Sgirish { 285044961713Sgirish npi_handle_t handle; 285144961713Sgirish uint8_t portn; 285244961713Sgirish npi_status_t rs = NPI_SUCCESS; 285344961713Sgirish nxge_status_t status = NXGE_OK; 285444961713Sgirish 2855*678453a8Sspeer /* This is a service-domain-only activity. */ 2856*678453a8Sspeer if (isLDOMguest(nxgep)) 2857*678453a8Sspeer return (status); 2858*678453a8Sspeer 285944961713Sgirish handle = nxgep->npi_handle; 286044961713Sgirish portn = nxgep->mac.portnum; 286144961713Sgirish 286244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 286344961713Sgirish portn)); 286444961713Sgirish 286544961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 286644961713Sgirish goto fail; 286744961713Sgirish 286844961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 286944961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 2870*678453a8Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 287144961713Sgirish goto fail; 287244961713Sgirish } else { 287344961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 2874*678453a8Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 287544961713Sgirish goto fail; 287644961713Sgirish } 287744961713Sgirish 2878*678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2879*678453a8Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 288044961713Sgirish 288144961713Sgirish return (NXGE_OK); 288244961713Sgirish fail: 288344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2884*678453a8Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 288544961713Sgirish 288644961713Sgirish if (rs != NPI_SUCCESS) 288744961713Sgirish return (NXGE_ERROR | rs); 288844961713Sgirish else 288944961713Sgirish return (status); 289044961713Sgirish } 289144961713Sgirish 289244961713Sgirish /* Disable RXMAC */ 289344961713Sgirish 289444961713Sgirish nxge_status_t 289544961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 289644961713Sgirish { 289744961713Sgirish npi_handle_t handle; 289844961713Sgirish uint8_t portn; 289944961713Sgirish npi_status_t rs = NPI_SUCCESS; 290044961713Sgirish 2901*678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 2902*678453a8Sspeer if (isLDOMguest(nxgep)) 2903*678453a8Sspeer return (NXGE_OK); 2904*678453a8Sspeer 290544961713Sgirish handle = nxgep->npi_handle; 290644961713Sgirish portn = nxgep->mac.portnum; 290744961713Sgirish 290844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 290944961713Sgirish portn)); 291044961713Sgirish 291144961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 291244961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 291344961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 291444961713Sgirish goto fail; 291544961713Sgirish } else { 291644961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 291744961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 291844961713Sgirish goto fail; 291944961713Sgirish } 292044961713Sgirish 292144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 292244961713Sgirish portn)); 292344961713Sgirish return (NXGE_OK); 292444961713Sgirish fail: 292544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 292644961713Sgirish "nxgep_rx_mac_disable: ", 292744961713Sgirish "Failed to disable port<%d> RxMAC", 292844961713Sgirish portn)); 292944961713Sgirish 293044961713Sgirish return (NXGE_ERROR | rs); 293144961713Sgirish } 293244961713Sgirish 293344961713Sgirish /* Reset TXMAC */ 293444961713Sgirish 293544961713Sgirish nxge_status_t 293644961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 293744961713Sgirish { 293844961713Sgirish npi_handle_t handle; 293944961713Sgirish uint8_t portn; 294044961713Sgirish npi_status_t rs = NPI_SUCCESS; 294144961713Sgirish 294244961713Sgirish handle = nxgep->npi_handle; 294344961713Sgirish portn = nxgep->mac.portnum; 294444961713Sgirish 294544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 294644961713Sgirish portn)); 294744961713Sgirish 294844961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 294944961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 295044961713Sgirish != NPI_SUCCESS) 295144961713Sgirish goto fail; 295244961713Sgirish } else { 295344961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 295444961713Sgirish != NPI_SUCCESS) 295544961713Sgirish goto fail; 295644961713Sgirish } 295744961713Sgirish 295844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 295944961713Sgirish portn)); 296044961713Sgirish 296144961713Sgirish return (NXGE_OK); 296244961713Sgirish fail: 296344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 296444961713Sgirish "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 296544961713Sgirish portn)); 296644961713Sgirish 296744961713Sgirish return (NXGE_ERROR | rs); 296844961713Sgirish } 296944961713Sgirish 297044961713Sgirish /* Reset RXMAC */ 297144961713Sgirish 297244961713Sgirish nxge_status_t 297344961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 297444961713Sgirish { 297544961713Sgirish npi_handle_t handle; 297644961713Sgirish uint8_t portn; 297744961713Sgirish npi_status_t rs = NPI_SUCCESS; 297844961713Sgirish 297944961713Sgirish handle = nxgep->npi_handle; 298044961713Sgirish portn = nxgep->mac.portnum; 298144961713Sgirish 298244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 298344961713Sgirish portn)); 298444961713Sgirish 298544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 298644961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 298744961713Sgirish != NPI_SUCCESS) 298844961713Sgirish goto fail; 298944961713Sgirish } else { 299044961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 299144961713Sgirish != NPI_SUCCESS) 299244961713Sgirish goto fail; 299344961713Sgirish } 299444961713Sgirish 299544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 299644961713Sgirish portn)); 299744961713Sgirish 299859ac0c16Sdavemq return (NXGE_OK); 299959ac0c16Sdavemq fail: 300059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 300159ac0c16Sdavemq "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 300259ac0c16Sdavemq portn)); 300359ac0c16Sdavemq return (NXGE_ERROR | rs); 300459ac0c16Sdavemq } 300559ac0c16Sdavemq 300659ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 300759ac0c16Sdavemq 300859ac0c16Sdavemq static nxge_status_t 300959ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 301059ac0c16Sdavemq { 301159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 301259ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 301359ac0c16Sdavemq 301459ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 301559ac0c16Sdavemq 301659ac0c16Sdavemq if (rs != NPI_SUCCESS) 301759ac0c16Sdavemq return (NXGE_ERROR | rs); 301859ac0c16Sdavemq else 301959ac0c16Sdavemq return (NXGE_OK); 302059ac0c16Sdavemq } 302159ac0c16Sdavemq 302259ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 302359ac0c16Sdavemq 302459ac0c16Sdavemq static nxge_status_t 302559ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 302659ac0c16Sdavemq { 302759ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 302859ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 302959ac0c16Sdavemq 303059ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 303159ac0c16Sdavemq 303259ac0c16Sdavemq if (rs != NPI_SUCCESS) 303359ac0c16Sdavemq return (NXGE_ERROR | rs); 303459ac0c16Sdavemq else 303559ac0c16Sdavemq return (NXGE_OK); 303659ac0c16Sdavemq } 303759ac0c16Sdavemq 303859ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 303959ac0c16Sdavemq 304059ac0c16Sdavemq static nxge_status_t 304159ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 304259ac0c16Sdavemq { 304359ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 304459ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 304559ac0c16Sdavemq 304659ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 304759ac0c16Sdavemq if (rs != NPI_SUCCESS) 304859ac0c16Sdavemq return (NXGE_ERROR | rs); 304959ac0c16Sdavemq else 305059ac0c16Sdavemq return (NXGE_OK); 305159ac0c16Sdavemq } 305259ac0c16Sdavemq 305359ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 305459ac0c16Sdavemq 305559ac0c16Sdavemq static nxge_status_t 305659ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 305759ac0c16Sdavemq { 305859ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 305959ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 306059ac0c16Sdavemq 306159ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 306259ac0c16Sdavemq 306359ac0c16Sdavemq if (rs != NPI_SUCCESS) 306459ac0c16Sdavemq return (NXGE_ERROR | rs); 306559ac0c16Sdavemq else 306659ac0c16Sdavemq return (NXGE_OK); 306759ac0c16Sdavemq } 306859ac0c16Sdavemq 306959ac0c16Sdavemq /* 1G copper link interrupt start routine */ 307059ac0c16Sdavemq 307159ac0c16Sdavemq static nxge_status_t 307259ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 307359ac0c16Sdavemq { 307459ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 307559ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 307659ac0c16Sdavemq 307759ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 30786b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 307959ac0c16Sdavemq 308059ac0c16Sdavemq if (rs != NPI_SUCCESS) 308159ac0c16Sdavemq return (NXGE_ERROR | rs); 308259ac0c16Sdavemq else 308359ac0c16Sdavemq return (NXGE_OK); 308444961713Sgirish } 308544961713Sgirish 308659ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 308759ac0c16Sdavemq 308859ac0c16Sdavemq static nxge_status_t 308959ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 309059ac0c16Sdavemq { 309159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 309259ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 309359ac0c16Sdavemq 309459ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 309559ac0c16Sdavemq 309659ac0c16Sdavemq if (rs != NPI_SUCCESS) 309759ac0c16Sdavemq return (NXGE_ERROR | rs); 309859ac0c16Sdavemq else 309959ac0c16Sdavemq return (NXGE_OK); 310059ac0c16Sdavemq } 310144961713Sgirish 310259ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 310344961713Sgirish 310444961713Sgirish nxge_status_t 310544961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 310644961713Sgirish { 310759ac0c16Sdavemq uint8_t portn; 310859ac0c16Sdavemq nxge_status_t status = NXGE_OK; 310944961713Sgirish 311044961713Sgirish portn = nxgep->mac.portnum; 311144961713Sgirish 311244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 311359ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 311459ac0c16Sdavemq return (NXGE_OK); 311544961713Sgirish 311659ac0c16Sdavemq if (enable == LINK_INTR_START) 311759ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 311859ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 311959ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 312059ac0c16Sdavemq if (status != NXGE_OK) 312159ac0c16Sdavemq goto fail; 312244961713Sgirish 312344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 312444961713Sgirish 312544961713Sgirish return (NXGE_OK); 312644961713Sgirish fail: 312744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 312844961713Sgirish "nxge_link_intr: Failed to set port<%d> mif intr mode", 312944961713Sgirish portn)); 313044961713Sgirish 313159ac0c16Sdavemq return (status); 313244961713Sgirish } 313344961713Sgirish 313444961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 313544961713Sgirish 313644961713Sgirish nxge_status_t 313744961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 313844961713Sgirish { 313944961713Sgirish p_nxge_param_t param_arr; 314044961713Sgirish p_nxge_stats_t statsp; 314144961713Sgirish uint8_t xcvr_portn; 314244961713Sgirish p_mii_regs_t mii_regs; 314344961713Sgirish mii_bmcr_t bmcr; 314444961713Sgirish mii_bmsr_t bmsr; 314544961713Sgirish mii_anar_t anar; 314644961713Sgirish mii_gcr_t gcr; 314744961713Sgirish mii_esr_t esr; 314844961713Sgirish mii_aux_ctl_t bcm5464r_aux; 314944961713Sgirish int status = NXGE_OK; 315044961713Sgirish 315144961713Sgirish uint_t delay; 315244961713Sgirish 315344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 315444961713Sgirish 315544961713Sgirish param_arr = nxgep->param_arr; 315644961713Sgirish statsp = nxgep->statsp; 315744961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 315844961713Sgirish 315944961713Sgirish mii_regs = NULL; 316044961713Sgirish 316144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 316244961713Sgirish "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 316344961713Sgirish 3164d81011f0Ssbehera /* 3165d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 3166d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 3167d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 3168d81011f0Ssbehera */ 3169d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 3170d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3171d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 3172d81011f0Ssbehera } 3173d81011f0Ssbehera 317444961713Sgirish /* 317544961713Sgirish * Reset the transceiver. 317644961713Sgirish */ 317744961713Sgirish delay = 0; 317844961713Sgirish bmcr.value = 0; 317944961713Sgirish bmcr.bits.reset = 1; 318044961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3181adfcba55Sjoycey #if defined(__i386) 3182adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3183adfcba55Sjoycey #else 318444961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3185adfcba55Sjoycey #endif 318644961713Sgirish goto fail; 318744961713Sgirish do { 318844961713Sgirish drv_usecwait(500); 318944961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3190adfcba55Sjoycey #if defined(__i386) 3191adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 3192adfcba55Sjoycey #else 319344961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 3194adfcba55Sjoycey #endif 319544961713Sgirish != NXGE_OK) 319644961713Sgirish goto fail; 319744961713Sgirish delay++; 319844961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 319944961713Sgirish if (delay == 1000) { 320044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 320144961713Sgirish goto fail; 320244961713Sgirish } 320344961713Sgirish 320444961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3205adfcba55Sjoycey #if defined(__i386) 3206adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 3207adfcba55Sjoycey #else 320844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 3209adfcba55Sjoycey #endif 321044961713Sgirish &bmsr.value)) != NXGE_OK) 321144961713Sgirish goto fail; 321244961713Sgirish 321344961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 321444961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 321544961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 321644961713Sgirish param_arr[param_anar_100hdx].value = 0; 321744961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 321844961713Sgirish param_arr[param_anar_10hdx].value = 0; 321944961713Sgirish 322044961713Sgirish /* 322158324dfcSspeer * Initialize the xcvr statistics. 322244961713Sgirish */ 322344961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 322444961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 322544961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 322644961713Sgirish statsp->mac_stats.cap_100hdx = 0; 322744961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 322844961713Sgirish statsp->mac_stats.cap_10hdx = 0; 322944961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 323044961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 323144961713Sgirish 323244961713Sgirish /* 323344961713Sgirish * Initialise the xcvr advertised capability statistics. 323444961713Sgirish */ 323544961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 323644961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 323744961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 323844961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 323944961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 324044961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 324144961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 324244961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 324344961713Sgirish statsp->mac_stats.adv_cap_asmpause = 324444961713Sgirish param_arr[param_anar_asmpause].value; 324544961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 324644961713Sgirish 324744961713Sgirish 324844961713Sgirish /* 324944961713Sgirish * Check for extended status just in case we're 325044961713Sgirish * running a Gigibit phy. 325144961713Sgirish */ 325244961713Sgirish if (bmsr.bits.extend_status) { 325344961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3254adfcba55Sjoycey #if defined(__i386) 3255adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 3256adfcba55Sjoycey #else 325744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 3258adfcba55Sjoycey #endif 325944961713Sgirish != NXGE_OK) 326044961713Sgirish goto fail; 326144961713Sgirish param_arr[param_anar_1000fdx].value &= 326244961713Sgirish esr.bits.link_1000fdx; 326344961713Sgirish param_arr[param_anar_1000hdx].value = 0; 326444961713Sgirish 326544961713Sgirish statsp->mac_stats.cap_1000fdx = 326644961713Sgirish (esr.bits.link_1000Xfdx || 326744961713Sgirish esr.bits.link_1000fdx); 326844961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 326944961713Sgirish } else { 327044961713Sgirish param_arr[param_anar_1000fdx].value = 0; 327144961713Sgirish param_arr[param_anar_1000hdx].value = 0; 327244961713Sgirish } 327344961713Sgirish 327444961713Sgirish /* 327544961713Sgirish * Initialize 1G Statistics once the capability is established. 327644961713Sgirish */ 327744961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 327844961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 327944961713Sgirish 328044961713Sgirish /* 328144961713Sgirish * Initialise the link statistics. 328244961713Sgirish */ 328344961713Sgirish statsp->mac_stats.link_T4 = 0; 328444961713Sgirish statsp->mac_stats.link_asmpause = 0; 328544961713Sgirish statsp->mac_stats.link_pause = 0; 328644961713Sgirish statsp->mac_stats.link_speed = 0; 328744961713Sgirish statsp->mac_stats.link_duplex = 0; 328844961713Sgirish statsp->mac_stats.link_up = 0; 328944961713Sgirish 329044961713Sgirish /* 329144961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 329244961713Sgirish */ 329344961713Sgirish bmcr.value = 0; 329444961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3295adfcba55Sjoycey #if defined(__i386) 3296adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3297adfcba55Sjoycey #else 329844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3299adfcba55Sjoycey #endif 330044961713Sgirish goto fail; 330144961713Sgirish 330244961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 330344961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 330444961713Sgirish bmcr.bits.loopback = 1; 330544961713Sgirish bmcr.bits.enable_autoneg = 0; 330644961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 330744961713Sgirish bmcr.bits.speed_1000_sel = 1; 330844961713Sgirish bmcr.bits.duplex_mode = 1; 330944961713Sgirish param_arr[param_autoneg].value = 0; 331044961713Sgirish } else { 331144961713Sgirish bmcr.bits.loopback = 0; 331244961713Sgirish } 331344961713Sgirish 331444961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 331544961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 331644961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 331744961713Sgirish param_arr[param_autoneg].value = 0; 331844961713Sgirish bcm5464r_aux.value = 0; 331944961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 332044961713Sgirish bcm5464r_aux.bits.write_1 = 1; 332144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 332244961713Sgirish BCM5464R_AUX_CTL, bcm5464r_aux.value)) 332344961713Sgirish != NXGE_OK) 332444961713Sgirish goto fail; 332544961713Sgirish } 332644961713Sgirish 332744961713Sgirish if (param_arr[param_autoneg].value) { 332844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 332944961713Sgirish "Restarting Auto-negotiation.")); 333044961713Sgirish /* 333144961713Sgirish * Setup our Auto-negotiation advertisement register. 333244961713Sgirish */ 333344961713Sgirish anar.value = 0; 333444961713Sgirish anar.bits.selector = 1; 333544961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 333644961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 333744961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 333844961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 333944961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 334044961713Sgirish anar.bits.cap_asmpause = 0; 334144961713Sgirish anar.bits.cap_pause = 0; 334244961713Sgirish if (param_arr[param_anar_1000fdx].value || 334344961713Sgirish param_arr[param_anar_100fdx].value || 334444961713Sgirish param_arr[param_anar_10fdx].value) { 334544961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 334644961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 334744961713Sgirish } 334844961713Sgirish 334944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3350adfcba55Sjoycey #if defined(__i386) 3351adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 3352adfcba55Sjoycey #else 335344961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 3354adfcba55Sjoycey #endif 335544961713Sgirish != NXGE_OK) 335644961713Sgirish goto fail; 335744961713Sgirish if (bmsr.bits.extend_status) { 335844961713Sgirish gcr.value = 0; 335944961713Sgirish gcr.bits.ms_mode_en = 336044961713Sgirish param_arr[param_master_cfg_enable].value; 336144961713Sgirish gcr.bits.master = 336244961713Sgirish param_arr[param_master_cfg_value].value; 336344961713Sgirish gcr.bits.link_1000fdx = 336444961713Sgirish param_arr[param_anar_1000fdx].value; 336544961713Sgirish gcr.bits.link_1000hdx = 336644961713Sgirish param_arr[param_anar_1000hdx].value; 336744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3368adfcba55Sjoycey #if defined(__i386) 3369adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 3370adfcba55Sjoycey #else 337144961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 3372adfcba55Sjoycey #endif 337344961713Sgirish != NXGE_OK) 337444961713Sgirish goto fail; 337544961713Sgirish } 337644961713Sgirish 337744961713Sgirish bmcr.bits.enable_autoneg = 1; 337844961713Sgirish bmcr.bits.restart_autoneg = 1; 337944961713Sgirish 338044961713Sgirish } else { 338144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 338244961713Sgirish bmcr.bits.speed_1000_sel = 338344961713Sgirish param_arr[param_anar_1000fdx].value | 338444961713Sgirish param_arr[param_anar_1000hdx].value; 338544961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 338644961713Sgirish (param_arr[param_anar_100fdx].value | 338744961713Sgirish param_arr[param_anar_100hdx].value); 338844961713Sgirish if (bmcr.bits.speed_1000_sel) { 338944961713Sgirish statsp->mac_stats.link_speed = 1000; 339044961713Sgirish gcr.value = 0; 339144961713Sgirish gcr.bits.ms_mode_en = 339244961713Sgirish param_arr[param_master_cfg_enable].value; 339344961713Sgirish gcr.bits.master = 339444961713Sgirish param_arr[param_master_cfg_value].value; 339544961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3396adfcba55Sjoycey #if defined(__i386) 3397adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 3398adfcba55Sjoycey #else 339944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 3400adfcba55Sjoycey #endif 340144961713Sgirish gcr.value)) 340244961713Sgirish != NXGE_OK) 340344961713Sgirish goto fail; 340444961713Sgirish if (param_arr[param_anar_1000fdx].value) { 340544961713Sgirish bmcr.bits.duplex_mode = 1; 340644961713Sgirish statsp->mac_stats.link_duplex = 2; 340744961713Sgirish } else 340844961713Sgirish statsp->mac_stats.link_duplex = 1; 340944961713Sgirish } else if (bmcr.bits.speed_sel) { 341044961713Sgirish statsp->mac_stats.link_speed = 100; 341144961713Sgirish if (param_arr[param_anar_100fdx].value) { 341244961713Sgirish bmcr.bits.duplex_mode = 1; 341344961713Sgirish statsp->mac_stats.link_duplex = 2; 341444961713Sgirish } else 341544961713Sgirish statsp->mac_stats.link_duplex = 1; 341644961713Sgirish } else { 341744961713Sgirish statsp->mac_stats.link_speed = 10; 341844961713Sgirish if (param_arr[param_anar_10fdx].value) { 341944961713Sgirish bmcr.bits.duplex_mode = 1; 342044961713Sgirish statsp->mac_stats.link_duplex = 2; 342144961713Sgirish } else 342244961713Sgirish statsp->mac_stats.link_duplex = 1; 342344961713Sgirish } 342444961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 342544961713Sgirish statsp->mac_stats.link_asmpause = 342644961713Sgirish statsp->mac_stats.cap_asmpause; 342744961713Sgirish statsp->mac_stats.link_pause = 342844961713Sgirish statsp->mac_stats.cap_pause; 342944961713Sgirish } 343044961713Sgirish 343144961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 343244961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 343344961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 343444961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 343544961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 343644961713Sgirish gcr.value = 0; 343744961713Sgirish gcr.bits.ms_mode_en = 1; 343844961713Sgirish gcr.bits.master = 1; 343944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3440adfcba55Sjoycey #if defined(__i386) 3441adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 3442adfcba55Sjoycey #else 344344961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 3444adfcba55Sjoycey #endif 344544961713Sgirish gcr.value)) 344644961713Sgirish != NXGE_OK) 344744961713Sgirish goto fail; 344844961713Sgirish bmcr.value = 0; 344944961713Sgirish bmcr.bits.speed_1000_sel = 1; 345044961713Sgirish statsp->mac_stats.link_speed = 1000; 345144961713Sgirish } else if (statsp->port_stats.lb_mode 345244961713Sgirish == nxge_lb_ext100) { 345344961713Sgirish /* BCM5464R 100mbps external loopback mode */ 345444961713Sgirish bmcr.value = 0; 345544961713Sgirish bmcr.bits.speed_sel = 1; 345644961713Sgirish bmcr.bits.duplex_mode = 1; 345744961713Sgirish statsp->mac_stats.link_speed = 100; 345844961713Sgirish } else if (statsp->port_stats.lb_mode 345944961713Sgirish == nxge_lb_ext10) { 346044961713Sgirish /* BCM5464R 10mbps external loopback mode */ 346144961713Sgirish bmcr.value = 0; 346244961713Sgirish bmcr.bits.duplex_mode = 1; 346344961713Sgirish statsp->mac_stats.link_speed = 10; 346444961713Sgirish } 346544961713Sgirish } 346644961713Sgirish } 346744961713Sgirish 346844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3469adfcba55Sjoycey #if defined(__i386) 3470adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 3471adfcba55Sjoycey #else 347244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), 3473adfcba55Sjoycey #endif 347444961713Sgirish bmcr.value)) != NXGE_OK) 347544961713Sgirish goto fail; 347644961713Sgirish 347744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3478adfcba55Sjoycey #if defined(__i386) 3479adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3480adfcba55Sjoycey #else 348144961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3482adfcba55Sjoycey #endif 348344961713Sgirish goto fail; 348444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 348544961713Sgirish 348644961713Sgirish /* 348744961713Sgirish * Initialize the xcvr status kept in the context structure. 348844961713Sgirish */ 348944961713Sgirish nxgep->soft_bmsr.value = 0; 349044961713Sgirish 349144961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3492adfcba55Sjoycey #if defined(__i386) 3493adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 3494adfcba55Sjoycey #else 349544961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 3496adfcba55Sjoycey #endif 349744961713Sgirish &nxgep->bmsr.value)) != NXGE_OK) 349844961713Sgirish goto fail; 349944961713Sgirish 350044961713Sgirish statsp->mac_stats.xcvr_inits++; 350144961713Sgirish nxgep->bmsr.value = 0; 350244961713Sgirish 350344961713Sgirish fail: 350444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 350544961713Sgirish "<== nxge_mii_xcvr_init status 0x%x", status)); 350644961713Sgirish return (status); 350744961713Sgirish } 350844961713Sgirish 3509d81011f0Ssbehera nxge_status_t 3510d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 3511d81011f0Ssbehera { 3512d81011f0Ssbehera p_nxge_param_t param_arr; 3513d81011f0Ssbehera p_nxge_stats_t statsp; 3514d81011f0Ssbehera uint8_t xcvr_portn; 3515d81011f0Ssbehera p_mii_regs_t mii_regs; 3516d81011f0Ssbehera mii_bmcr_t bmcr; 3517d81011f0Ssbehera mii_bmsr_t bmsr; 3518d81011f0Ssbehera mii_gcr_t gcr; 3519d81011f0Ssbehera mii_esr_t esr; 3520d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 3521d81011f0Ssbehera int status = NXGE_OK; 3522d81011f0Ssbehera 3523d81011f0Ssbehera uint_t delay; 3524d81011f0Ssbehera 3525d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 3526d81011f0Ssbehera 3527d81011f0Ssbehera param_arr = nxgep->param_arr; 3528d81011f0Ssbehera statsp = nxgep->statsp; 3529d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 3530d81011f0Ssbehera 3531d81011f0Ssbehera mii_regs = NULL; 3532d81011f0Ssbehera 3533d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3534d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 3535d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3536d81011f0Ssbehera 3537d81011f0Ssbehera /* 3538d81011f0Ssbehera * Reset the transceiver. 3539d81011f0Ssbehera */ 3540d81011f0Ssbehera delay = 0; 3541d81011f0Ssbehera bmcr.value = 0; 3542d81011f0Ssbehera bmcr.bits.reset = 1; 3543d81011f0Ssbehera 3544d81011f0Ssbehera #if defined(__i386) 3545d81011f0Ssbehera 3546d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3547d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3548d81011f0Ssbehera goto fail; 3549d81011f0Ssbehera #else 3550d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3551d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3552d81011f0Ssbehera goto fail; 3553d81011f0Ssbehera #endif 3554d81011f0Ssbehera do { 3555d81011f0Ssbehera drv_usecwait(500); 3556d81011f0Ssbehera #if defined(__i386) 3557d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3558d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 3559d81011f0Ssbehera != NXGE_OK) 3560d81011f0Ssbehera goto fail; 3561d81011f0Ssbehera #else 3562d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3563d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 3564d81011f0Ssbehera != NXGE_OK) 3565d81011f0Ssbehera goto fail; 3566d81011f0Ssbehera #endif 3567d81011f0Ssbehera delay++; 3568d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 3569d81011f0Ssbehera if (delay == 1000) { 3570d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 3571d81011f0Ssbehera goto fail; 3572d81011f0Ssbehera } 3573d81011f0Ssbehera 3574d81011f0Ssbehera #if defined(__i386) 3575d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3576d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3577d81011f0Ssbehera goto fail; 3578d81011f0Ssbehera #else 3579d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3580d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3581d81011f0Ssbehera goto fail; 3582d81011f0Ssbehera #endif 3583d81011f0Ssbehera 3584d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 3585d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 3586d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 3587d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 3588d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 3589d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 3590d81011f0Ssbehera 3591d81011f0Ssbehera /* 3592d81011f0Ssbehera * Initialize the xcvr statistics. 3593d81011f0Ssbehera */ 3594d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 3595d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 3596d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 3597d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 3598d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 3599d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 3600d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 3601d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3602d81011f0Ssbehera 3603d81011f0Ssbehera /* 3604d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 3605d81011f0Ssbehera */ 3606d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 3607d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3608d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3609d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 3610d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 3611d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 3612d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 3613d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 3614d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 3615d81011f0Ssbehera param_arr[param_anar_asmpause].value; 3616d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3617d81011f0Ssbehera 3618d81011f0Ssbehera /* 3619d81011f0Ssbehera * Check for extended status just in case we're 3620d81011f0Ssbehera * running a Gigibit phy. 3621d81011f0Ssbehera */ 3622d81011f0Ssbehera if (bmsr.bits.extend_status) { 3623d81011f0Ssbehera #if defined(__i386) 3624d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3625d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 3626d81011f0Ssbehera NXGE_OK) 3627d81011f0Ssbehera goto fail; 3628d81011f0Ssbehera #else 3629d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3630d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 3631d81011f0Ssbehera NXGE_OK) 3632d81011f0Ssbehera goto fail; 3633d81011f0Ssbehera #endif 3634d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 3635d81011f0Ssbehera esr.bits.link_1000fdx; 3636d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 3637d81011f0Ssbehera 3638d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 3639d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 3640d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 3641d81011f0Ssbehera } else { 3642d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 3643d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 3644d81011f0Ssbehera } 3645d81011f0Ssbehera 3646d81011f0Ssbehera /* 3647d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 3648d81011f0Ssbehera */ 3649d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3650d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3651d81011f0Ssbehera 3652d81011f0Ssbehera /* 3653d81011f0Ssbehera * Initialize the link statistics. 3654d81011f0Ssbehera */ 3655d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 3656d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 3657d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 3658d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 3659d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 3660d81011f0Ssbehera statsp->mac_stats.link_up = 0; 3661d81011f0Ssbehera 3662d81011f0Ssbehera /* 3663d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 3664d81011f0Ssbehera */ 3665d81011f0Ssbehera bmcr.value = 0; 3666d81011f0Ssbehera #if defined(__i386) 3667d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3668d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3669d81011f0Ssbehera goto fail; 3670d81011f0Ssbehera #else 3671d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3672d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3673d81011f0Ssbehera goto fail; 3674d81011f0Ssbehera #endif 3675d81011f0Ssbehera 3676d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 3677d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 3678d81011f0Ssbehera bmcr.bits.loopback = 1; 3679d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 3680d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 3681d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3682d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 3683d81011f0Ssbehera param_arr[param_autoneg].value = 0; 3684d81011f0Ssbehera } else { 3685d81011f0Ssbehera bmcr.bits.loopback = 0; 3686d81011f0Ssbehera } 3687d81011f0Ssbehera 3688d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 3689d81011f0Ssbehera param_arr[param_autoneg].value = 0; 3690d81011f0Ssbehera bcm5464r_aux.value = 0; 3691d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 3692d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 3693d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3694d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 3695d81011f0Ssbehera goto fail; 3696d81011f0Ssbehera } 3697d81011f0Ssbehera 3698d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 3699d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3700d81011f0Ssbehera bmcr.bits.speed_sel = 0; 3701d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 3702d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 3703d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 3704d81011f0Ssbehera 3705d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 3706d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 3707d81011f0Ssbehera gcr.value = 0; 3708d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 3709d81011f0Ssbehera gcr.bits.master = 1; 3710d81011f0Ssbehera #if defined(__i386) 3711d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3712d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 3713d81011f0Ssbehera gcr.value)) != NXGE_OK) 3714d81011f0Ssbehera goto fail; 3715d81011f0Ssbehera #else 3716d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3717d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 3718d81011f0Ssbehera gcr.value)) != NXGE_OK) 3719d81011f0Ssbehera goto fail; 3720d81011f0Ssbehera #endif 3721d81011f0Ssbehera bmcr.value = 0; 3722d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3723d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 3724d81011f0Ssbehera } 3725d81011f0Ssbehera 3726d81011f0Ssbehera #if defined(__i386) 3727d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3728d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 3729d81011f0Ssbehera bmcr.value)) != NXGE_OK) 3730d81011f0Ssbehera goto fail; 3731d81011f0Ssbehera #else 3732d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3733d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 3734d81011f0Ssbehera bmcr.value)) != NXGE_OK) 3735d81011f0Ssbehera goto fail; 3736d81011f0Ssbehera #endif 3737d81011f0Ssbehera 3738d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3739d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 3740d81011f0Ssbehera bmcr.value)); 3741d81011f0Ssbehera 3742d81011f0Ssbehera #if defined(__i386) 3743d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3744d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3745d81011f0Ssbehera goto fail; 3746d81011f0Ssbehera #else 3747d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3748d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3749d81011f0Ssbehera goto fail; 3750d81011f0Ssbehera #endif 3751d81011f0Ssbehera 3752d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3753d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 3754d81011f0Ssbehera 3755d81011f0Ssbehera /* 3756d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 3757d81011f0Ssbehera */ 3758d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 3759d81011f0Ssbehera #if defined(__i386) 3760d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3761d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 3762d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 3763d81011f0Ssbehera goto fail; 3764d81011f0Ssbehera #else 3765d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3766d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 3767d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 3768d81011f0Ssbehera goto fail; 3769d81011f0Ssbehera #endif 3770d81011f0Ssbehera 3771d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 3772d81011f0Ssbehera nxgep->bmsr.value = 0; 3773d81011f0Ssbehera 3774d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3775d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3776d81011f0Ssbehera return (status); 3777d81011f0Ssbehera 3778d81011f0Ssbehera fail: 3779d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3780d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3781d81011f0Ssbehera return (status); 3782d81011f0Ssbehera } 3783d81011f0Ssbehera 378444961713Sgirish /* Read from a MII compliant register */ 378544961713Sgirish 378644961713Sgirish nxge_status_t 378744961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 378844961713Sgirish uint16_t *value) 378944961713Sgirish { 379044961713Sgirish npi_status_t rs = NPI_SUCCESS; 379144961713Sgirish 379244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 379344961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 379444961713Sgirish 3795321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 379644961713Sgirish 3797d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3798d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 379944961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 380044961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 380144961713Sgirish goto fail; 38022e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 38032e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 380444961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 380544961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 380644961713Sgirish goto fail; 380744961713Sgirish } else 380844961713Sgirish goto fail; 380944961713Sgirish 3810321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 381144961713Sgirish 381244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 381344961713Sgirish "xcvr_reg<%d> value=0x%x", 381444961713Sgirish xcvr_portn, xcvr_reg, *value)); 381544961713Sgirish return (NXGE_OK); 381644961713Sgirish fail: 3817321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 381844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 381944961713Sgirish "nxge_mii_read: Failed to read mii on xcvr %d", 382044961713Sgirish xcvr_portn)); 382144961713Sgirish 382244961713Sgirish return (NXGE_ERROR | rs); 382344961713Sgirish } 382444961713Sgirish 382544961713Sgirish /* Write to a MII compliant Register */ 382644961713Sgirish 382744961713Sgirish nxge_status_t 382844961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 382944961713Sgirish uint16_t value) 383044961713Sgirish { 383144961713Sgirish npi_status_t rs = NPI_SUCCESS; 383244961713Sgirish 383344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 383444961713Sgirish "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 383544961713Sgirish value)); 383644961713Sgirish 3837321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 383844961713Sgirish 3839d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3840d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 384144961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 384244961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 384344961713Sgirish goto fail; 38442e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 38452e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 384644961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 384744961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 384844961713Sgirish goto fail; 384944961713Sgirish } else 385044961713Sgirish goto fail; 385144961713Sgirish 3852321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 385344961713Sgirish 385444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 385544961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 385644961713Sgirish return (NXGE_OK); 385744961713Sgirish fail: 3858321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 385944961713Sgirish 386044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 386144961713Sgirish "nxge_mii_write: Failed to write mii on xcvr %d", 386244961713Sgirish xcvr_portn)); 386344961713Sgirish 386444961713Sgirish return (NXGE_ERROR | rs); 386544961713Sgirish } 386644961713Sgirish 386744961713Sgirish /* Perform read from Clause45 serdes / transceiver device */ 386844961713Sgirish 386944961713Sgirish nxge_status_t 387044961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 387144961713Sgirish uint16_t xcvr_reg, uint16_t *value) 387244961713Sgirish { 387344961713Sgirish npi_status_t rs = NPI_SUCCESS; 387444961713Sgirish 387544961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 387644961713Sgirish xcvr_portn)); 387744961713Sgirish 387853560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 387944961713Sgirish 388044961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 388144961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 388244961713Sgirish goto fail; 388344961713Sgirish 388453560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 388544961713Sgirish 388644961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 388744961713Sgirish xcvr_portn)); 388844961713Sgirish return (NXGE_OK); 388944961713Sgirish fail: 389053560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 389144961713Sgirish 389244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 389344961713Sgirish "nxge_mdio_read: Failed to read mdio on xcvr %d", 389444961713Sgirish xcvr_portn)); 389544961713Sgirish 389644961713Sgirish return (NXGE_ERROR | rs); 389744961713Sgirish } 389844961713Sgirish 389944961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 390044961713Sgirish 390144961713Sgirish nxge_status_t 390244961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 390344961713Sgirish uint16_t xcvr_reg, uint16_t value) 390444961713Sgirish { 390544961713Sgirish npi_status_t rs = NPI_SUCCESS; 390644961713Sgirish 390744961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 390844961713Sgirish xcvr_portn)); 390944961713Sgirish 391053560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 391144961713Sgirish 391244961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 391344961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 391444961713Sgirish goto fail; 391544961713Sgirish 391653560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 391744961713Sgirish 391844961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 391944961713Sgirish xcvr_portn)); 392044961713Sgirish return (NXGE_OK); 392144961713Sgirish fail: 392253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 392344961713Sgirish 392444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 392544961713Sgirish "nxge_mdio_write: Failed to write mdio on xcvr %d", 392644961713Sgirish xcvr_portn)); 392744961713Sgirish 392844961713Sgirish return (NXGE_ERROR | rs); 392944961713Sgirish } 393044961713Sgirish 393144961713Sgirish 393244961713Sgirish /* Check MII to see if there is any link status change */ 393344961713Sgirish 393444961713Sgirish nxge_status_t 3935a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 3936a3c5bd6dSspeer nxge_link_state_t *link_up) 393744961713Sgirish { 393844961713Sgirish p_nxge_param_t param_arr; 393944961713Sgirish p_nxge_stats_t statsp; 394044961713Sgirish p_mii_regs_t mii_regs; 394144961713Sgirish p_mii_bmsr_t soft_bmsr; 394244961713Sgirish mii_anar_t anar; 394344961713Sgirish mii_anlpar_t anlpar; 394444961713Sgirish mii_anar_t an_common; 394544961713Sgirish mii_aner_t aner; 394644961713Sgirish mii_gsr_t gsr; 394744961713Sgirish nxge_status_t status = NXGE_OK; 394844961713Sgirish 394944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 395044961713Sgirish 395144961713Sgirish mii_regs = NULL; 395244961713Sgirish param_arr = nxgep->param_arr; 395344961713Sgirish statsp = nxgep->statsp; 395444961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 3955a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 395644961713Sgirish 3957d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3958d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 3959d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 3960d81011f0Ssbehera 396144961713Sgirish if (bmsr_ints.bits.link_status) { 3962d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3963d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 3964d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 396544961713Sgirish if (bmsr.bits.link_status) { 396644961713Sgirish soft_bmsr->bits.link_status = 1; 3967d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3968d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 3969d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 397044961713Sgirish } else { 397144961713Sgirish statsp->mac_stats.link_up = 0; 397244961713Sgirish soft_bmsr->bits.link_status = 0; 397344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 397444961713Sgirish "Link down cable problem")); 3975a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 397644961713Sgirish } 397744961713Sgirish } 397844961713Sgirish 3979d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 3980d81011f0Ssbehera param_arr[param_autoneg].value) { 398144961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 398244961713Sgirish if (bmsr.bits.auto_neg_complete) 398344961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 398444961713Sgirish else 398544961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 398644961713Sgirish } 398744961713Sgirish if (soft_bmsr->bits.link_status == 0) { 398844961713Sgirish statsp->mac_stats.link_T4 = 0; 398944961713Sgirish statsp->mac_stats.link_speed = 0; 399044961713Sgirish statsp->mac_stats.link_duplex = 0; 399144961713Sgirish statsp->mac_stats.link_asmpause = 0; 399244961713Sgirish statsp->mac_stats.link_pause = 0; 399344961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 399444961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 399544961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 399644961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 399744961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 399844961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 399944961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 400044961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 400144961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 400244961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 400344961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 400444961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 400544961713Sgirish } 400644961713Sgirish } else 400744961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 400844961713Sgirish 400944961713Sgirish if ((bmsr_ints.bits.link_status || 401044961713Sgirish bmsr_ints.bits.auto_neg_complete) && 401144961713Sgirish soft_bmsr->bits.link_status && 401244961713Sgirish soft_bmsr->bits.auto_neg_complete) { 401344961713Sgirish statsp->mac_stats.link_up = 1; 4014d81011f0Ssbehera 4015d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4016d81011f0Ssbehera "==> nxge_mii_check " 4017d81011f0Ssbehera "(auto negotiation complete or link up) " 4018d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 4019d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4020d81011f0Ssbehera 4021d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4022d81011f0Ssbehera param_arr[param_autoneg].value) { 402344961713Sgirish if ((status = nxge_mii_read(nxgep, 402444961713Sgirish statsp->mac_stats.xcvr_portn, 4025adfcba55Sjoycey #if defined(__i386) 4026adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 4027adfcba55Sjoycey #else 402844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), 4029adfcba55Sjoycey #endif 403044961713Sgirish &anar.value)) != NXGE_OK) 403144961713Sgirish goto fail; 403244961713Sgirish if ((status = nxge_mii_read(nxgep, 403344961713Sgirish statsp->mac_stats.xcvr_portn, 4034adfcba55Sjoycey #if defined(__i386) 4035adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 4036adfcba55Sjoycey #else 403744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anlpar), 4038adfcba55Sjoycey #endif 403944961713Sgirish &anlpar.value)) != NXGE_OK) 404044961713Sgirish goto fail; 404144961713Sgirish if ((status = nxge_mii_read(nxgep, 404244961713Sgirish statsp->mac_stats.xcvr_portn, 4043adfcba55Sjoycey #if defined(__i386) 4044adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 4045adfcba55Sjoycey #else 404644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->aner), 4047adfcba55Sjoycey #endif 404844961713Sgirish &aner.value)) != NXGE_OK) 404944961713Sgirish goto fail; 405044961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 405144961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 405244961713Sgirish statsp->mac_stats.lp_cap_100fdx = 405344961713Sgirish anlpar.bits.cap_100fdx; 405444961713Sgirish statsp->mac_stats.lp_cap_100hdx = 405544961713Sgirish anlpar.bits.cap_100hdx; 405644961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 405744961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 405844961713Sgirish statsp->mac_stats.lp_cap_asmpause = 405944961713Sgirish anlpar.bits.cap_asmpause; 406044961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 406144961713Sgirish an_common.value = anar.value & anlpar.value; 406244961713Sgirish if (param_arr[param_anar_1000fdx].value || 406344961713Sgirish param_arr[param_anar_1000hdx].value) { 406444961713Sgirish if ((status = nxge_mii_read(nxgep, 406544961713Sgirish statsp->mac_stats.xcvr_portn, 4066adfcba55Sjoycey #if defined(__i386) 4067adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 4068adfcba55Sjoycey #else 406944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gsr), 4070adfcba55Sjoycey #endif 407144961713Sgirish &gsr.value)) 407244961713Sgirish != NXGE_OK) 407344961713Sgirish goto fail; 407444961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 407544961713Sgirish gsr.bits.link_1000fdx; 407644961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 407744961713Sgirish gsr.bits.link_1000hdx; 407844961713Sgirish if (param_arr[param_anar_1000fdx].value && 407944961713Sgirish gsr.bits.link_1000fdx) { 408044961713Sgirish statsp->mac_stats.link_speed = 1000; 408144961713Sgirish statsp->mac_stats.link_duplex = 2; 408244961713Sgirish } else if ( 408344961713Sgirish param_arr[param_anar_1000hdx].value && 408444961713Sgirish gsr.bits.link_1000hdx) { 408544961713Sgirish statsp->mac_stats.link_speed = 1000; 408644961713Sgirish statsp->mac_stats.link_duplex = 1; 408744961713Sgirish } 408844961713Sgirish } 408944961713Sgirish if ((an_common.value != 0) && 409044961713Sgirish !(statsp->mac_stats.link_speed)) { 409144961713Sgirish if (an_common.bits.cap_100T4) { 409244961713Sgirish statsp->mac_stats.link_T4 = 1; 409344961713Sgirish statsp->mac_stats.link_speed = 100; 409444961713Sgirish statsp->mac_stats.link_duplex = 1; 409544961713Sgirish } else if (an_common.bits.cap_100fdx) { 409644961713Sgirish statsp->mac_stats.link_speed = 100; 409744961713Sgirish statsp->mac_stats.link_duplex = 2; 409844961713Sgirish } else if (an_common.bits.cap_100hdx) { 409944961713Sgirish statsp->mac_stats.link_speed = 100; 410044961713Sgirish statsp->mac_stats.link_duplex = 1; 410144961713Sgirish } else if (an_common.bits.cap_10fdx) { 410244961713Sgirish statsp->mac_stats.link_speed = 10; 410344961713Sgirish statsp->mac_stats.link_duplex = 2; 410444961713Sgirish } else if (an_common.bits.cap_10hdx) { 410544961713Sgirish statsp->mac_stats.link_speed = 10; 410644961713Sgirish statsp->mac_stats.link_duplex = 1; 410744961713Sgirish } else { 410844961713Sgirish goto fail; 410944961713Sgirish } 411044961713Sgirish } 411144961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 411244961713Sgirish statsp->mac_stats.link_asmpause = 411344961713Sgirish an_common.bits.cap_asmpause; 411444961713Sgirish if (statsp->mac_stats.link_asmpause) 411544961713Sgirish if ((statsp->mac_stats.cap_pause == 0) && 411644961713Sgirish (statsp->mac_stats.lp_cap_pause 411744961713Sgirish == 1)) 411844961713Sgirish statsp->mac_stats.link_pause 411944961713Sgirish = 0; 412044961713Sgirish else 412144961713Sgirish statsp->mac_stats.link_pause 412244961713Sgirish = 1; 412344961713Sgirish else 412444961713Sgirish statsp->mac_stats.link_pause = 412544961713Sgirish an_common.bits.cap_pause; 412644961713Sgirish } 4127d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4128d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4129d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 413044961713Sgirish } 4131a3c5bd6dSspeer *link_up = LINK_IS_UP; 4132a3c5bd6dSspeer } 4133a3c5bd6dSspeer 4134a3c5bd6dSspeer if (nxgep->link_notify) { 4135a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 4136a3c5bd6dSspeer LINK_IS_DOWN); 4137a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 413844961713Sgirish } 413944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 414044961713Sgirish return (NXGE_OK); 414144961713Sgirish fail: 414244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 414344961713Sgirish "nxge_mii_check: Unable to check MII")); 414444961713Sgirish return (status); 414544961713Sgirish } 414644961713Sgirish 41472e59129aSraghus /* Check PCS to see if there is any link status change */ 41482e59129aSraghus nxge_status_t 41492e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 41502e59129aSraghus { 41512e59129aSraghus p_nxge_stats_t statsp; 41522e59129aSraghus nxge_status_t status = NXGE_OK; 41532e59129aSraghus boolean_t linkup; 41542e59129aSraghus 41552e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 41562e59129aSraghus 41572e59129aSraghus statsp = nxgep->statsp; 41582e59129aSraghus *link_up = LINK_NO_CHANGE; 41592e59129aSraghus 41602e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 41612e59129aSraghus if (linkup) { 41622e59129aSraghus if (nxgep->link_notify || 41632e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 41642e59129aSraghus statsp->mac_stats.link_up = 1; 41652e59129aSraghus statsp->mac_stats.link_speed = 1000; 41662e59129aSraghus statsp->mac_stats.link_duplex = 2; 41672e59129aSraghus *link_up = LINK_IS_UP; 41682e59129aSraghus nxgep->link_notify = B_FALSE; 41692e59129aSraghus } 41702e59129aSraghus } else { 41712e59129aSraghus if (nxgep->link_notify || 41722e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 41732e59129aSraghus statsp->mac_stats.link_up = 0; 41742e59129aSraghus statsp->mac_stats.link_speed = 0; 41752e59129aSraghus statsp->mac_stats.link_duplex = 0; 41762e59129aSraghus *link_up = LINK_IS_DOWN; 41772e59129aSraghus nxgep->link_notify = B_FALSE; 41782e59129aSraghus } 41792e59129aSraghus } 41802e59129aSraghus 41812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 41822e59129aSraghus return (NXGE_OK); 41832e59129aSraghus fail: 41842e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 41852e59129aSraghus "nxge_pcs_check: Unable to check PCS")); 41862e59129aSraghus return (status); 41872e59129aSraghus } 41882e59129aSraghus 418944961713Sgirish /* Add a multicast address entry into the HW hash table */ 419044961713Sgirish 419144961713Sgirish nxge_status_t 419244961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 419344961713Sgirish { 419444961713Sgirish uint32_t mchash; 419544961713Sgirish p_hash_filter_t hash_filter; 419644961713Sgirish uint16_t hash_bit; 419744961713Sgirish boolean_t rx_init = B_FALSE; 419844961713Sgirish uint_t j; 419944961713Sgirish nxge_status_t status = NXGE_OK; 420044961713Sgirish 420144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 420244961713Sgirish 420344961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 420444961713Sgirish mchash = crc32_mchash(addrp); 420544961713Sgirish if (nxgep->hash_filter == NULL) { 420644961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 420744961713Sgirish "Allocating hash filter storage.")); 420844961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 420944961713Sgirish KM_SLEEP); 421044961713Sgirish } 421144961713Sgirish hash_filter = nxgep->hash_filter; 421244961713Sgirish j = mchash / HASH_REG_WIDTH; 421344961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 421444961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 421544961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 421644961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 421744961713Sgirish hash_filter->hash_ref_cnt++; 421844961713Sgirish rx_init = B_TRUE; 421944961713Sgirish } 422044961713Sgirish if (rx_init) { 422144961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 422244961713Sgirish goto fail; 422344961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 422444961713Sgirish goto fail; 422544961713Sgirish } 422644961713Sgirish 422744961713Sgirish RW_EXIT(&nxgep->filter_lock); 422844961713Sgirish 422944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 423044961713Sgirish 423144961713Sgirish return (NXGE_OK); 423244961713Sgirish fail: 423344961713Sgirish RW_EXIT(&nxgep->filter_lock); 423444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 423544961713Sgirish "Unable to add multicast address")); 423644961713Sgirish return (status); 423744961713Sgirish } 423844961713Sgirish 423944961713Sgirish /* Remove a multicast address entry from the HW hash table */ 424044961713Sgirish 424144961713Sgirish nxge_status_t 424244961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 424344961713Sgirish { 424444961713Sgirish uint32_t mchash; 424544961713Sgirish p_hash_filter_t hash_filter; 424644961713Sgirish uint16_t hash_bit; 424744961713Sgirish boolean_t rx_init = B_FALSE; 424844961713Sgirish uint_t j; 424944961713Sgirish nxge_status_t status = NXGE_OK; 425044961713Sgirish 425144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 425244961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 425344961713Sgirish mchash = crc32_mchash(addrp); 425444961713Sgirish if (nxgep->hash_filter == NULL) { 425544961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 425644961713Sgirish "Hash filter already de_allocated.")); 425744961713Sgirish RW_EXIT(&nxgep->filter_lock); 425844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 425944961713Sgirish return (NXGE_OK); 426044961713Sgirish } 426144961713Sgirish hash_filter = nxgep->hash_filter; 426244961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 426344961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 426444961713Sgirish j = mchash / HASH_REG_WIDTH; 426544961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 426644961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 426744961713Sgirish hash_filter->hash_ref_cnt--; 426844961713Sgirish rx_init = B_TRUE; 426944961713Sgirish } 427044961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 427144961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 427244961713Sgirish "De-allocating hash filter storage.")); 427344961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 427444961713Sgirish nxgep->hash_filter = NULL; 427544961713Sgirish } 427644961713Sgirish 427744961713Sgirish if (rx_init) { 427844961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 427944961713Sgirish goto fail; 428044961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 428144961713Sgirish goto fail; 428244961713Sgirish } 428344961713Sgirish RW_EXIT(&nxgep->filter_lock); 428444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 428544961713Sgirish 428644961713Sgirish return (NXGE_OK); 428744961713Sgirish fail: 428844961713Sgirish RW_EXIT(&nxgep->filter_lock); 428944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 429044961713Sgirish "Unable to remove multicast address")); 429144961713Sgirish 429244961713Sgirish return (status); 429344961713Sgirish } 429444961713Sgirish 429544961713Sgirish /* Set MAC address into MAC address HW registers */ 429644961713Sgirish 429744961713Sgirish nxge_status_t 429844961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 429944961713Sgirish { 430044961713Sgirish nxge_status_t status = NXGE_OK; 430144961713Sgirish 430244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 430344961713Sgirish 430444961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 430544961713Sgirish /* 430644961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 430744961713Sgirish */ 430844961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 430944961713Sgirish (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 431044961713Sgirish (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 431144961713Sgirish goto nxge_set_mac_addr_exit; 431244961713Sgirish } 431344961713Sgirish nxgep->ouraddr = *addrp; 431444961713Sgirish /* 431544961713Sgirish * Set new interface local address and re-init device. 431644961713Sgirish * This is destructive to any other streams attached 431744961713Sgirish * to this device. 431844961713Sgirish */ 431944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 432044961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 432144961713Sgirish goto fail; 432244961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 432344961713Sgirish goto fail; 432444961713Sgirish 432544961713Sgirish RW_EXIT(&nxgep->filter_lock); 432644961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 432744961713Sgirish goto nxge_set_mac_addr_end; 432844961713Sgirish nxge_set_mac_addr_exit: 432944961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 433044961713Sgirish nxge_set_mac_addr_end: 433144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 433244961713Sgirish 433344961713Sgirish return (NXGE_OK); 433444961713Sgirish fail: 433544961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 433644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 433744961713Sgirish "Unable to set mac address")); 433844961713Sgirish return (status); 433944961713Sgirish } 434044961713Sgirish 434198ecde52Stm static 434298ecde52Stm check_link_state_t 434398ecde52Stm nxge_check_link_stop( 434498ecde52Stm nxge_t *nxge) 434598ecde52Stm { 434698ecde52Stm /* If the poll has been cancelled, return STOP. */ 434798ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 434898ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 434998ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 435098ecde52Stm nxge->nxge_link_poll_timerid = 0; 435198ecde52Stm cv_broadcast(&nxge->poll_cv); 435298ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 435398ecde52Stm 435498ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 435598ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 435698ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 435798ecde52Stm nxge->mac.portnum)); 435898ecde52Stm return (CHECK_LINK_STOP); 435998ecde52Stm } 436098ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 436198ecde52Stm 436298ecde52Stm return (CHECK_LINK_RESCHEDULE); 436398ecde52Stm } 436498ecde52Stm 436544961713Sgirish /* Check status of MII (MIF or PCS) link */ 436644961713Sgirish 436759ac0c16Sdavemq static nxge_status_t 436844961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 436944961713Sgirish { 437044961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 437144961713Sgirish mii_anlpar_t anlpar; 437244961713Sgirish mii_gsr_t gsr; 437344961713Sgirish p_mii_regs_t mii_regs; 437444961713Sgirish nxge_status_t status = NXGE_OK; 437544961713Sgirish uint8_t portn; 4376a3c5bd6dSspeer nxge_link_state_t link_up; 437744961713Sgirish 437898ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 437998ecde52Stm return (NXGE_ERROR); 438098ecde52Stm 438198ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 438298ecde52Stm return (NXGE_OK); 438398ecde52Stm 438444961713Sgirish portn = nxgep->mac.portnum; 438544961713Sgirish 438644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 438798ecde52Stm portn)); 438844961713Sgirish 438944961713Sgirish mii_regs = NULL; 439044961713Sgirish 439144961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 439244961713Sgirish 439344961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 439444961713Sgirish goto nxge_check_mii_link_exit; 439544961713Sgirish 43962e59129aSraghus switch (nxgep->mac.portmode) { 43972e59129aSraghus default: 4398d81011f0Ssbehera bmsr_data.value = 0; 439944961713Sgirish if ((status = nxge_mii_read(nxgep, 44002e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4401adfcba55Sjoycey #if defined(__i386) 4402adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 4403adfcba55Sjoycey #else 44042e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 4405adfcba55Sjoycey #endif 44062e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 440744961713Sgirish goto fail; 440844961713Sgirish } 440944961713Sgirish 4410d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4411d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 4412d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 44132d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 4414d81011f0Ssbehera 44152e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 44162e59129aSraghus if ((status = nxge_mii_read(nxgep, 44172e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4418adfcba55Sjoycey #if defined(__i386) 4419adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 4420adfcba55Sjoycey #else 44212e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 4422adfcba55Sjoycey #endif 44232e59129aSraghus &gsr.value)) != NXGE_OK) 44242e59129aSraghus goto fail; 44252e59129aSraghus if ((status = nxge_mii_read(nxgep, 44262e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4427adfcba55Sjoycey #if defined(__i386) 4428adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 4429adfcba55Sjoycey #else 44302e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 4431adfcba55Sjoycey #endif 44322e59129aSraghus &anlpar.value)) != NXGE_OK) 44332e59129aSraghus goto fail; 4434d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 4435d81011f0Ssbehera 4436d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 4437d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 4438d81011f0Ssbehera gsr.bits.link_1000fdx) || 4439d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 4440d81011f0Ssbehera gsr.bits.link_1000hdx) || 4441d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 4442d81011f0Ssbehera anlpar.bits.cap_100T4) || 4443d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 4444d81011f0Ssbehera anlpar.bits.cap_100fdx) || 4445d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 4446d81011f0Ssbehera anlpar.bits.cap_100hdx) || 4447d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 4448d81011f0Ssbehera anlpar.bits.cap_10fdx) || 4449d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 4450d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 4451d81011f0Ssbehera bmsr_data.bits.link_status = 0; 4452d81011f0Ssbehera } 44532e59129aSraghus } 44542e59129aSraghus } 445544961713Sgirish 44562e59129aSraghus /* Workaround for link down issue */ 44572e59129aSraghus if (bmsr_data.value == 0) { 44582e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 44592e59129aSraghus goto nxge_check_mii_link_exit; 44602e59129aSraghus } 44612e59129aSraghus 4462d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4463d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 4464d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 44652d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 4466d81011f0Ssbehera 44672e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 44682e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 4469d81011f0Ssbehera 4470d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4471d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 4472d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 44732d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 4474d81011f0Ssbehera 44752e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 44762e59129aSraghus &link_up)) != NXGE_OK) { 44772e59129aSraghus goto fail; 44782e59129aSraghus } 44792e59129aSraghus break; 44802e59129aSraghus 44812e59129aSraghus case PORT_1G_SERDES: 44822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44832e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 44842e59129aSraghus if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 44852e59129aSraghus != NXGE_OK) { 44862e59129aSraghus goto fail; 44872e59129aSraghus } 44882e59129aSraghus break; 44892e59129aSraghus } 449044961713Sgirish 449144961713Sgirish nxge_check_mii_link_exit: 449244961713Sgirish RW_EXIT(&nxgep->filter_lock); 4493a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 4494a3c5bd6dSspeer nxge_link_is_up(nxgep); 4495a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 4496a3c5bd6dSspeer nxge_link_is_down(nxgep); 4497a3c5bd6dSspeer } 449844961713Sgirish 449944961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 450044961713Sgirish 450144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 45022e59129aSraghus portn)); 450344961713Sgirish return (NXGE_OK); 450444961713Sgirish 450544961713Sgirish fail: 450644961713Sgirish RW_EXIT(&nxgep->filter_lock); 450744961713Sgirish 450844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 450944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 45102e59129aSraghus "nxge_check_mii_link: Failed to check link port<%d>", 45112e59129aSraghus portn)); 451244961713Sgirish return (status); 451344961713Sgirish } 451444961713Sgirish 451544961713Sgirish 451644961713Sgirish /*ARGSUSED*/ 451759ac0c16Sdavemq static nxge_status_t 451844961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 451944961713Sgirish { 452044961713Sgirish uint8_t portn; 452144961713Sgirish nxge_status_t status = NXGE_OK; 4522763fcc44Ssbehera boolean_t link_up; 45232e59129aSraghus uint32_t val; 45242e59129aSraghus npi_status_t rs; 452544961713Sgirish 452698ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 452798ecde52Stm return (NXGE_ERROR); 452898ecde52Stm 452998ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 453098ecde52Stm return (NXGE_OK); 453198ecde52Stm 453244961713Sgirish portn = nxgep->mac.portnum; 4533d81011f0Ssbehera val = 0; 4534d81011f0Ssbehera rs = NPI_SUCCESS; 453544961713Sgirish 453644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 453798ecde52Stm portn)); 453844961713Sgirish 45392e59129aSraghus switch (nxgep->mac.portmode) { 45402e59129aSraghus default: 45412d17280bSsbehera /* 45422d17280bSsbehera * Check if the phy is present in case of hot swappable phy 45432d17280bSsbehera */ 45442d17280bSsbehera if (nxgep->hot_swappable_phy) { 45452d17280bSsbehera boolean_t phy_present_now = B_FALSE; 45462d17280bSsbehera 45472d17280bSsbehera /* 45482d17280bSsbehera * If this is the 2nd Goa port, then check 2 addresses 45492d17280bSsbehera * to take care of the Goa NEM card requirements. 45502d17280bSsbehera */ 45512d17280bSsbehera if (portn == 1) { 45522d17280bSsbehera if (nxge_is_phy_present(nxgep, 45532d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR, 45542d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 45552d17280bSsbehera phy_present_now = B_TRUE; 45562d17280bSsbehera nxgep->xcvr_addr = 45572d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR; 45582d17280bSsbehera goto phy_check_done; 45592d17280bSsbehera } 45602d17280bSsbehera } 45612d17280bSsbehera if (nxge_is_phy_present(nxgep, 45622d17280bSsbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 45632d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 45642d17280bSsbehera nxgep->xcvr_addr = 45652d17280bSsbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn; 45662d17280bSsbehera phy_present_now = B_TRUE; 45672d17280bSsbehera } 45682d17280bSsbehera 45692d17280bSsbehera phy_check_done: 45702d17280bSsbehera if (nxgep->phy_absent) { 45712d17280bSsbehera if (phy_present_now) { 45722d17280bSsbehera /* 45732d17280bSsbehera * Detect, Initialize phy and do link up 45742d17280bSsbehera * set xcvr vals, link_init, nxge_init 45752d17280bSsbehera */ 45762d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45772d17280bSsbehera "Hot swappable phy DETECTED!!")); 45782d17280bSsbehera nxgep->phy_absent = B_FALSE; 45792d17280bSsbehera (void) nxge_xcvr_find(nxgep); 45802d17280bSsbehera (void) nxge_link_init(nxgep); 45812d17280bSsbehera if (!(nxgep->drv_state & 45822d17280bSsbehera STATE_HW_INITIALIZED)) { 45832d17280bSsbehera status = nxge_init(nxgep); 45842d17280bSsbehera if (status != NXGE_OK) { 45852d17280bSsbehera NXGE_ERROR_MSG((nxgep, 45862d17280bSsbehera NXGE_ERR_CTL, 45872d17280bSsbehera "Hot swappable " 45882d17280bSsbehera "phy present, but" 45892d17280bSsbehera " driver init" 45902d17280bSsbehera " failed...")); 45912d17280bSsbehera goto fail; 45922d17280bSsbehera } 45932d17280bSsbehera } 45942d17280bSsbehera } 45952d17280bSsbehera 45962d17280bSsbehera goto start_link_check; 45972d17280bSsbehera 45982d17280bSsbehera } else if (!phy_present_now) { 45992d17280bSsbehera /* 46002d17280bSsbehera * Phy gone, bring link down reset xcvr vals 46012d17280bSsbehera */ 46022d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46032d17280bSsbehera "Hot swappable phy REMOVED!!")); 46042d17280bSsbehera nxgep->phy_absent = B_TRUE; 46052d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 46062d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 46072d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 46082d17280bSsbehera nxge_link_is_down(nxgep); 46092d17280bSsbehera nxgep->link_notify = B_FALSE; 46102d17280bSsbehera 46112d17280bSsbehera (void) nxge_xcvr_find(nxgep); 46122d17280bSsbehera 46132d17280bSsbehera goto start_link_check; 46142d17280bSsbehera 46152d17280bSsbehera } 46162d17280bSsbehera } 46172d17280bSsbehera 46182e59129aSraghus status = nxge_check_bcm8704_link(nxgep, &link_up); 46192e59129aSraghus if (status != NXGE_OK) 46202e59129aSraghus goto fail; 46212e59129aSraghus break; 46222e59129aSraghus case PORT_10G_SERDES: 46232e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4624763fcc44Ssbehera XPCS_REG_STATUS, &val); 46252e59129aSraghus if (rs != 0) 46262e59129aSraghus goto fail; 46272e59129aSraghus 46282e59129aSraghus link_up = B_FALSE; 4629763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 4630763fcc44Ssbehera link_up = B_TRUE; 46312e59129aSraghus } 46322e59129aSraghus 46332e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46342e59129aSraghus "==> nxge_check_10g_link port<%d> " 4635763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 4636763fcc44Ssbehera portn, val, link_up)); 46372e59129aSraghus 46382e59129aSraghus break; 46392e59129aSraghus } 464044961713Sgirish 464144961713Sgirish if (link_up) { 4642a3c5bd6dSspeer if (nxgep->link_notify || 4643a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 0) { 464444961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 464544961713Sgirish goto fail; 464644961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 464744961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 464844961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 464944961713Sgirish 465044961713Sgirish nxge_link_is_up(nxgep); 4651a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 465244961713Sgirish } 465344961713Sgirish } else { 4654a3c5bd6dSspeer if (nxgep->link_notify || 4655a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 1) { 465644961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 465744961713Sgirish goto fail; 465844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46592e59129aSraghus "Link down cable problem")); 466044961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 466144961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 466244961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 466344961713Sgirish 466444961713Sgirish nxge_link_is_down(nxgep); 4665a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 466644961713Sgirish } 466744961713Sgirish } 466844961713Sgirish 46692d17280bSsbehera start_link_check: 467044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 467144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 467298ecde52Stm portn)); 467344961713Sgirish return (NXGE_OK); 467444961713Sgirish 467544961713Sgirish fail: 467698ecde52Stm (void) nxge_check_link_stop(nxgep); 467798ecde52Stm 467844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 467998ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 468098ecde52Stm portn)); 468144961713Sgirish return (status); 468244961713Sgirish } 468344961713Sgirish 468444961713Sgirish 468544961713Sgirish /* Declare link down */ 468644961713Sgirish 468744961713Sgirish void 468844961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 468944961713Sgirish { 469059ac0c16Sdavemq p_nxge_stats_t statsp; 469159ac0c16Sdavemq char link_stat_msg[64]; 469259ac0c16Sdavemq 469344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 469444961713Sgirish 469559ac0c16Sdavemq statsp = nxgep->statsp; 469659ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 469759ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 469859ac0c16Sdavemq 469959ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 470059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 470159ac0c16Sdavemq } 470259ac0c16Sdavemq 470344961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 470444961713Sgirish 470544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 470644961713Sgirish } 470744961713Sgirish 470844961713Sgirish /* Declare link up */ 470944961713Sgirish 471044961713Sgirish void 471144961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 471244961713Sgirish { 471359ac0c16Sdavemq p_nxge_stats_t statsp; 471459ac0c16Sdavemq char link_stat_msg[64]; 471544961713Sgirish uint32_t val; 471644961713Sgirish 471744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 471844961713Sgirish 471959ac0c16Sdavemq statsp = nxgep->statsp; 472059ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 472159ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 472259ac0c16Sdavemq statsp->mac_stats.link_speed); 472359ac0c16Sdavemq 472459ac0c16Sdavemq if (statsp->mac_stats.link_T4) 472559ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 472659ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 472759ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 472859ac0c16Sdavemq else 472959ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 473059ac0c16Sdavemq 473144961713Sgirish (void) nxge_xif_init(nxgep); 473244961713Sgirish 473344961713Sgirish /* Clean up symbol errors incurred during link transition */ 47342e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 47352e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 473644961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 473744961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 473844961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 473944961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 474044961713Sgirish } 474144961713Sgirish 474259ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 474359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 474459ac0c16Sdavemq } 474559ac0c16Sdavemq 474644961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 474744961713Sgirish 474844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 474944961713Sgirish } 475044961713Sgirish 475144961713Sgirish /* 475244961713Sgirish * Calculate the bit in the multicast address filter 475344961713Sgirish * that selects the given * address. 475444961713Sgirish * Note: For GEM, the last 8-bits are used. 475544961713Sgirish */ 475644961713Sgirish uint32_t 475744961713Sgirish crc32_mchash(p_ether_addr_t addr) 475844961713Sgirish { 475944961713Sgirish uint8_t *cp; 476044961713Sgirish uint32_t crc; 476144961713Sgirish uint32_t c; 476244961713Sgirish int byte; 476344961713Sgirish int bit; 476444961713Sgirish 476544961713Sgirish cp = (uint8_t *)addr; 476644961713Sgirish crc = (uint32_t)0xffffffff; 476744961713Sgirish for (byte = 0; byte < 6; byte++) { 476844961713Sgirish c = (uint32_t)cp[byte]; 476944961713Sgirish for (bit = 0; bit < 8; bit++) { 477044961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 477144961713Sgirish crc = (crc >> 1)^0xedb88320; 477244961713Sgirish else 477344961713Sgirish crc = (crc >> 1); 477444961713Sgirish c >>= 1; 477544961713Sgirish } 477644961713Sgirish } 477744961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 477844961713Sgirish } 477944961713Sgirish 478044961713Sgirish /* Reset serdes */ 478144961713Sgirish 478244961713Sgirish nxge_status_t 478344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 478444961713Sgirish { 478544961713Sgirish npi_handle_t handle; 478644961713Sgirish 478744961713Sgirish handle = nxgep->npi_handle; 478844961713Sgirish 478944961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 479044961713Sgirish drv_usecwait(500); 479144961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 479244961713Sgirish 479344961713Sgirish return (NXGE_OK); 479444961713Sgirish } 479544961713Sgirish 479644961713Sgirish /* Monitor link status using interrupt or polling */ 479744961713Sgirish nxge_status_t 479844961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 479944961713Sgirish { 480044961713Sgirish nxge_status_t status = NXGE_OK; 480144961713Sgirish 4802*678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 4803*678453a8Sspeer if (isLDOMguest(nxgep)) 4804*678453a8Sspeer return (status); 4805*678453a8Sspeer 480644961713Sgirish /* 480798ecde52Stm * Return immediately if this is an imaginary XMAC port. 480898ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 480944961713Sgirish */ 48102e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 48112e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 48122e59129aSraghus (nxgep->mac.portnum > 1)) 481344961713Sgirish return (NXGE_OK); 481444961713Sgirish 481544961713Sgirish if (nxgep->statsp == NULL) { 481644961713Sgirish /* stats has not been allocated. */ 481744961713Sgirish return (NXGE_OK); 481844961713Sgirish } 4819321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 4820321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 482144961713Sgirish return (NXGE_OK); 482244961713Sgirish 482344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 482498ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 482598ecde52Stm nxgep->mac.portnum, enable)); 482644961713Sgirish if (enable == LINK_MONITOR_START) { 482744961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 482844961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 482998ecde52Stm != NXGE_OK) 483044961713Sgirish goto fail; 483144961713Sgirish } else { 483298ecde52Stm timeout_id_t timerid; 483398ecde52Stm 483498ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 483598ecde52Stm return (NXGE_OK); 483698ecde52Stm 483759ac0c16Sdavemq if (nxgep->xcvr.check_link) { 483859ac0c16Sdavemq timerid = timeout( 483959ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 484098ecde52Stm nxgep, 484198ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 484259ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 484359ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 484459ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 484559ac0c16Sdavemq } else { 484698ecde52Stm return (NXGE_ERROR); 484744961713Sgirish } 484844961713Sgirish } 484944961713Sgirish } else { 485044961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 485144961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 485298ecde52Stm != NXGE_OK) 485344961713Sgirish goto fail; 485444961713Sgirish } else { 485598ecde52Stm clock_t rv; 485698ecde52Stm 485798ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 485898ecde52Stm 485998ecde52Stm /* If <timerid> == 0, the link monitor has */ 486098ecde52Stm /* never been started, or just now stopped. */ 486198ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 486298ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 486398ecde52Stm return (NXGE_OK); 486498ecde52Stm } 486598ecde52Stm 486698ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 486798ecde52Stm rv = cv_timedwait(&nxgep->poll_cv, 486898ecde52Stm &nxgep->poll_lock, 486998ecde52Stm ddi_get_lbolt() + 487098ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 487198ecde52Stm LINK_MONITOR_PERIOD)); 487298ecde52Stm if (rv == -1) { 487398ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 487498ecde52Stm "==> stopping port %d: " 487598ecde52Stm "cv_timedwait(%d) timed out", 487698ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 487798ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 487844961713Sgirish nxgep->nxge_link_poll_timerid = 0; 487944961713Sgirish } 488098ecde52Stm 488198ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 488244961713Sgirish } 488344961713Sgirish } 488444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 488598ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 488698ecde52Stm nxgep->mac.portnum, enable)); 4887*678453a8Sspeer 488844961713Sgirish return (NXGE_OK); 488944961713Sgirish fail: 489044961713Sgirish return (status); 489144961713Sgirish } 489244961713Sgirish 489344961713Sgirish /* Set promiscous mode */ 489444961713Sgirish 489544961713Sgirish nxge_status_t 489644961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 489744961713Sgirish { 489844961713Sgirish nxge_status_t status = NXGE_OK; 489944961713Sgirish 490059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 490144961713Sgirish 490244961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 490344961713Sgirish 490444961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 490544961713Sgirish 490644961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 490744961713Sgirish goto fail; 490844961713Sgirish } 490944961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 491044961713Sgirish goto fail; 491144961713Sgirish } 491244961713Sgirish 491344961713Sgirish RW_EXIT(&nxgep->filter_lock); 491444961713Sgirish 491544961713Sgirish if (on) 491644961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 491744961713Sgirish else 491844961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 491944961713Sgirish 492044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 492144961713Sgirish 492244961713Sgirish return (NXGE_OK); 492344961713Sgirish fail: 492444961713Sgirish RW_EXIT(&nxgep->filter_lock); 492544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 492659ac0c16Sdavemq "Unable to set promisc (%d)", on)); 492744961713Sgirish 492844961713Sgirish return (status); 492944961713Sgirish } 493044961713Sgirish 493144961713Sgirish /*ARGSUSED*/ 493244961713Sgirish uint_t 493344961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 493444961713Sgirish { 493544961713Sgirish #ifdef NXGE_DEBUG 493644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 493744961713Sgirish #endif 493844961713Sgirish #if NXGE_MIF 493944961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 494044961713Sgirish uint32_t status; 494144961713Sgirish npi_handle_t handle; 494244961713Sgirish uint8_t portn; 494344961713Sgirish p_nxge_stats_t statsp; 494444961713Sgirish #endif 494544961713Sgirish 494644961713Sgirish #ifdef NXGE_MIF 494744961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 494844961713Sgirish nxgep = ldvp->nxgep; 494944961713Sgirish } 495044961713Sgirish nxgep = ldvp->nxgep; 495144961713Sgirish #endif 495244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 495344961713Sgirish 495444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 495544961713Sgirish return (DDI_INTR_CLAIMED); 495644961713Sgirish 495744961713Sgirish mif_intr_fail: 495844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 495944961713Sgirish return (DDI_INTR_UNCLAIMED); 496044961713Sgirish } 496144961713Sgirish 496244961713Sgirish /*ARGSUSED*/ 496344961713Sgirish uint_t 496444961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 496544961713Sgirish { 496644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 496744961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 496844961713Sgirish p_nxge_ldg_t ldgp; 496944961713Sgirish uint32_t status; 497044961713Sgirish npi_handle_t handle; 497144961713Sgirish uint8_t portn; 497244961713Sgirish p_nxge_stats_t statsp; 497344961713Sgirish npi_status_t rs = NPI_SUCCESS; 497444961713Sgirish 497544961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 497644961713Sgirish nxgep = ldvp->nxgep; 497744961713Sgirish } 497844961713Sgirish 497944961713Sgirish ldgp = ldvp->ldgp; 498044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 498159ac0c16Sdavemq "group %d", ldgp->ldg)); 498244961713Sgirish 498344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 498444961713Sgirish /* 498544961713Sgirish * This interrupt handler is for a specific 498644961713Sgirish * mac port. 498744961713Sgirish */ 498844961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 498944961713Sgirish portn = nxgep->mac.portnum; 499044961713Sgirish 499144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 499259ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 499344961713Sgirish 499444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 499544961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 499644961713Sgirish (xmac_tx_iconfig_t *)&status); 499744961713Sgirish if (rs != NPI_SUCCESS) 499844961713Sgirish goto npi_fail; 499944961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 500044961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 500144961713Sgirish statsp->xmac_stats.tx_underflow_err++; 500244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 500344961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 500444961713Sgirish } 500544961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 500644961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 5007f6485eecSyc /* 5008f6485eecSyc * Do not send FMA ereport because this 5009f6485eecSyc * error does not indicate HW failure. 5010f6485eecSyc */ 501144961713Sgirish } 501244961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 501344961713Sgirish statsp->xmac_stats.tx_overflow_err++; 501444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 501544961713Sgirish NXGE_FM_EREPORT_TXMAC_OVERFLOW); 501644961713Sgirish } 501744961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 501844961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 501944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 502044961713Sgirish NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 502144961713Sgirish } 502244961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 502344961713Sgirish statsp->xmac_stats.tx_byte_cnt += 502444961713Sgirish XTXMAC_BYTE_CNT_MASK; 502544961713Sgirish } 502644961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 502744961713Sgirish statsp->xmac_stats.tx_frame_cnt += 502844961713Sgirish XTXMAC_FRM_CNT_MASK; 502944961713Sgirish } 503044961713Sgirish } 503144961713Sgirish 503244961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 503344961713Sgirish (xmac_rx_iconfig_t *)&status); 503444961713Sgirish if (rs != NPI_SUCCESS) 503544961713Sgirish goto npi_fail; 503644961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 503744961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 503844961713Sgirish statsp->xmac_stats.rx_overflow_err++; 503944961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 504044961713Sgirish statsp->xmac_stats.rx_underflow_err++; 504144961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 504244961713Sgirish NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 504344961713Sgirish } 5044f6485eecSyc /* 5045f6485eecSyc * Do not send FMA ereport for the following 3 errors 5046f6485eecSyc * because they do not indicate HW failures. 5047f6485eecSyc */ 504844961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 504944961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 505044961713Sgirish XRXMAC_CRC_ER_CNT_MASK; 505144961713Sgirish } 505244961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 505344961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 505444961713Sgirish MAC_LEN_ER_CNT_MASK; 505544961713Sgirish } 505644961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 505744961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 505844961713Sgirish XRXMAC_CD_VIO_CNT_MASK; 505944961713Sgirish } 506044961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 506144961713Sgirish statsp->xmac_stats.rx_byte_cnt += 506244961713Sgirish XRXMAC_BT_CNT_MASK; 506344961713Sgirish } 506444961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 506544961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 506644961713Sgirish XRXMAC_HIST_CNT1_MASK; 506744961713Sgirish } 506844961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 506944961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 507044961713Sgirish XRXMAC_HIST_CNT2_MASK; 507144961713Sgirish } 507244961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 507344961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 507444961713Sgirish XRXMAC_HIST_CNT3_MASK; 507544961713Sgirish } 507644961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 507744961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 507844961713Sgirish XRXMAC_HIST_CNT4_MASK; 507944961713Sgirish } 508044961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 508144961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 508244961713Sgirish XRXMAC_HIST_CNT5_MASK; 508344961713Sgirish } 508444961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 508544961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 508644961713Sgirish XRXMAC_HIST_CNT6_MASK; 508744961713Sgirish } 508844961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 508944961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 509044961713Sgirish XRXMAC_BC_FRM_CNT_MASK; 509144961713Sgirish } 509244961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 509344961713Sgirish statsp->xmac_stats.rx_mult_cnt += 509444961713Sgirish XRXMAC_MC_FRM_CNT_MASK; 509544961713Sgirish } 5096f6485eecSyc /* 5097f6485eecSyc * Do not send FMA ereport for the following 3 errors 5098f6485eecSyc * because they do not indicate HW failures. 5099f6485eecSyc */ 510044961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 510144961713Sgirish statsp->xmac_stats.rx_frag_cnt += 510244961713Sgirish XRXMAC_FRAG_CNT_MASK; 510344961713Sgirish } 510444961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 510544961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 510644961713Sgirish XRXMAC_AL_ER_CNT_MASK; 510744961713Sgirish } 510844961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 510944961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 511044961713Sgirish XMAC_LINK_FLT_CNT_MASK; 511144961713Sgirish } 511244961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 511344961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 511444961713Sgirish } 511544961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 511644961713Sgirish statsp->xmac_stats.rx_localfault_err++; 511744961713Sgirish } 511844961713Sgirish } 511944961713Sgirish 512044961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 512144961713Sgirish (xmac_ctl_iconfig_t *)&status); 512244961713Sgirish if (rs != NPI_SUCCESS) 512344961713Sgirish goto npi_fail; 512444961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 512544961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 512644961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 512744961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 512844961713Sgirish statsp->xmac_stats.tx_pause_state++; 512944961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 513044961713Sgirish statsp->xmac_stats.tx_nopause_state++; 513144961713Sgirish } 513244961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 513344961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 513444961713Sgirish (bmac_tx_iconfig_t *)&status); 513544961713Sgirish if (rs != NPI_SUCCESS) 513644961713Sgirish goto npi_fail; 513744961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 513844961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 513944961713Sgirish statsp->bmac_stats.tx_underrun_err++; 514044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 514144961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 514244961713Sgirish } 514344961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 514444961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 514544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 514644961713Sgirish NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 514744961713Sgirish } 514844961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 514944961713Sgirish statsp->bmac_stats.tx_byte_cnt += 515044961713Sgirish BTXMAC_BYTE_CNT_MASK; 515144961713Sgirish } 515244961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 515344961713Sgirish statsp->bmac_stats.tx_frame_cnt += 515444961713Sgirish BTXMAC_FRM_CNT_MASK; 515544961713Sgirish } 515644961713Sgirish } 515744961713Sgirish 515844961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 515944961713Sgirish (bmac_rx_iconfig_t *)&status); 516044961713Sgirish if (rs != NPI_SUCCESS) 516144961713Sgirish goto npi_fail; 516244961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 516344961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 516444961713Sgirish statsp->bmac_stats.rx_overflow_err++; 516544961713Sgirish } 516644961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 516744961713Sgirish statsp->bmac_stats.rx_frame_cnt += 516844961713Sgirish RXMAC_FRM_CNT_MASK; 516944961713Sgirish } 517044961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 517144961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 517244961713Sgirish BMAC_CRC_ER_CNT_MASK; 517344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 517444961713Sgirish NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 517544961713Sgirish } 517644961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 517744961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 517844961713Sgirish MAC_LEN_ER_CNT_MASK; 517944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 518044961713Sgirish NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 518144961713Sgirish } 518244961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 518344961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 518444961713Sgirish BMAC_CD_VIO_CNT_MASK; 518544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 518644961713Sgirish NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 518744961713Sgirish } 518844961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 518944961713Sgirish statsp->bmac_stats.rx_byte_cnt += 519044961713Sgirish BRXMAC_BYTE_CNT_MASK; 519144961713Sgirish } 519244961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 519344961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 519444961713Sgirish BMAC_AL_ER_CNT_MASK; 519544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 519644961713Sgirish NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 519744961713Sgirish } 519844961713Sgirish 519944961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 520044961713Sgirish (bmac_ctl_iconfig_t *)&status); 520144961713Sgirish if (rs != NPI_SUCCESS) 520244961713Sgirish goto npi_fail; 520344961713Sgirish 520444961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 520544961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 520644961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 520744961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 520844961713Sgirish statsp->bmac_stats.tx_pause_state++; 520944961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 521044961713Sgirish statsp->bmac_stats.tx_nopause_state++; 521144961713Sgirish } 521244961713Sgirish } 521344961713Sgirish 521444961713Sgirish if (ldgp->nldvs == 1) { 521544961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 521644961713Sgirish B_TRUE, ldgp->ldg_timer); 521744961713Sgirish } 521844961713Sgirish 521944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 522044961713Sgirish return (DDI_INTR_CLAIMED); 522144961713Sgirish 522244961713Sgirish npi_fail: 522344961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 522444961713Sgirish return (DDI_INTR_UNCLAIMED); 522544961713Sgirish } 522644961713Sgirish 522744961713Sgirish nxge_status_t 522844961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 522944961713Sgirish { 523044961713Sgirish uint8_t phy_port_addr; 523144961713Sgirish nxge_status_t status = NXGE_OK; 523244961713Sgirish boolean_t rx_sig_ok; 523344961713Sgirish boolean_t pcs_blk_lock; 523444961713Sgirish boolean_t link_align; 523544961713Sgirish uint16_t val1, val2, val3; 523644961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 523744961713Sgirish uint16_t val_debug; 523844961713Sgirish uint16_t val; 523944961713Sgirish #endif 524044961713Sgirish 524144961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 524244961713Sgirish 524344961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 524444961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 524544961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 524644961713Sgirish if ((val_debug & ~0x200) != 0) { 524744961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 524844961713Sgirish nxgep->mac.portnum, val_debug); 524944961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 525044961713Sgirish &val_debug); 525144961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 525244961713Sgirish nxgep->mac.portnum, val_debug); 525344961713Sgirish } 525444961713Sgirish 525544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 525644961713Sgirish XPCS_REG_DESCWERR_COUNTER, &val); 525744961713Sgirish if (val != 0) 525844961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 525944961713Sgirish 526044961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 526144961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 526244961713Sgirish if (val != 0) 526344961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 526444961713Sgirish 526544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 526644961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 526744961713Sgirish if (val != 0) 526844961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 526944961713Sgirish #endif 527044961713Sgirish 527144961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 527244961713Sgirish 527344961713Sgirish /* Check Device 1 Register 0xA bit0 */ 527444961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 527544961713Sgirish BCM8704_PMA_PMD_DEV_ADDR, 527644961713Sgirish BCM8704_PMD_RECEIVE_SIG_DETECT, 527744961713Sgirish &val1); 527844961713Sgirish if (status != NXGE_OK) 527944961713Sgirish goto fail; 528044961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 528144961713Sgirish 528244961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 528344961713Sgirish if ((status = nxge_mdio_read(nxgep, phy_port_addr, 528444961713Sgirish BCM8704_PCS_DEV_ADDR, 528544961713Sgirish BCM8704_10GBASE_R_PCS_STATUS_REG, 528644961713Sgirish &val2)) != NPI_SUCCESS) 528744961713Sgirish goto fail; 528844961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 528944961713Sgirish 529044961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 529144961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 529244961713Sgirish BCM8704_PHYXS_ADDR, 529344961713Sgirish BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 529444961713Sgirish &val3); 529544961713Sgirish if (status != NXGE_OK) 529644961713Sgirish goto fail; 52972d17280bSsbehera 52982d17280bSsbehera switch (nxgep->chip_id) { 52992d17280bSsbehera case BCM8704_CHIP_ID: 53002d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 53012d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 53022d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 53032d17280bSsbehera break; 53042d17280bSsbehera case BCM8706_CHIP_ID: 53052d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 53062d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 53072d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 53082d17280bSsbehera B_TRUE : B_FALSE; 53092d17280bSsbehera break; 53102d17280bSsbehera default: 53112d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 53122d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 53132d17280bSsbehera goto fail; 53142d17280bSsbehera } 53152d17280bSsbehera 531644961713Sgirish 531744961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 531844961713Sgirish /* Temp workaround for link down issue */ 531944961713Sgirish if (pcs_blk_lock == B_FALSE) { 532044961713Sgirish if (val2 != 0x4) { 532144961713Sgirish pcs_blk_lock = B_TRUE; 532244961713Sgirish cmn_err(CE_NOTE, 532344961713Sgirish "!LINK DEBUG: port%d PHY Dev3 " 532444961713Sgirish "Reg 0x20 = 0x%x\n", 532544961713Sgirish nxgep->mac.portnum, val2); 532644961713Sgirish } 532744961713Sgirish } 532844961713Sgirish 532944961713Sgirish if (link_align == B_FALSE) { 533044961713Sgirish if (val3 != 0x140f) { 533144961713Sgirish link_align = B_TRUE; 533244961713Sgirish cmn_err(CE_NOTE, 533344961713Sgirish "!LINK DEBUG: port%d PHY Dev4 " 533444961713Sgirish "Reg 0x18 = 0x%x\n", 533544961713Sgirish nxgep->mac.portnum, val3); 533644961713Sgirish } 533744961713Sgirish } 533844961713Sgirish 533944961713Sgirish if (rx_sig_ok == B_FALSE) { 534044961713Sgirish if ((val2 == 0) || (val3 == 0)) { 534144961713Sgirish rx_sig_ok = B_TRUE; 534244961713Sgirish cmn_err(CE_NOTE, 534344961713Sgirish "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 534444961713Sgirish nxgep->mac.portnum); 534544961713Sgirish } 534644961713Sgirish } 534744961713Sgirish #endif 534844961713Sgirish 534944961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 535044961713Sgirish (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 535144961713Sgirish 535244961713Sgirish return (NXGE_OK); 535344961713Sgirish fail: 535444961713Sgirish return (status); 535544961713Sgirish } 535644961713Sgirish 535759ac0c16Sdavemq nxge_status_t 535859ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 535959ac0c16Sdavemq { 536059ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 536159ac0c16Sdavemq != NPI_SUCCESS) 536259ac0c16Sdavemq return (NXGE_ERROR); 536359ac0c16Sdavemq else 536459ac0c16Sdavemq return (NXGE_OK); 536559ac0c16Sdavemq } 536644961713Sgirish 536744961713Sgirish nxge_status_t 536859ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 536944961713Sgirish { 537059ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 537159ac0c16Sdavemq != NPI_SUCCESS) 537259ac0c16Sdavemq return (NXGE_ERROR); 537359ac0c16Sdavemq else 537459ac0c16Sdavemq return (NXGE_OK); 537559ac0c16Sdavemq } 537644961713Sgirish 53772d17280bSsbehera static boolean_t 53782d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 53792d17280bSsbehera { 53802d17280bSsbehera uint32_t pma_pmd_id = 0; 53812d17280bSsbehera uint32_t pcs_id = 0; 53822d17280bSsbehera uint32_t phy_id = 0; 53832d17280bSsbehera 53842d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 53852d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53862d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 53872d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 53882d17280bSsbehera goto found_phy; 53892d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 53902d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53912d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 53922d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 53932d17280bSsbehera goto found_phy; 53942d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 53952d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53962d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 53972d17280bSsbehera if ((phy_id & mask) == (id & mask)) 53982d17280bSsbehera goto found_phy; 53992d17280bSsbehera 54002d17280bSsbehera return (B_FALSE); 54012d17280bSsbehera 54022d17280bSsbehera found_phy: 54032d17280bSsbehera return (B_TRUE); 54042d17280bSsbehera } 54052d17280bSsbehera 540659ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 540759ac0c16Sdavemq 540859ac0c16Sdavemq static boolean_t 540959ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 541059ac0c16Sdavemq { 541159ac0c16Sdavemq int i; 541259ac0c16Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 541359ac0c16Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 541459ac0c16Sdavemq boolean_t found = B_FALSE; 541559ac0c16Sdavemq 541659ac0c16Sdavemq switch (type) { 541759ac0c16Sdavemq case CLAUSE_45_TYPE: 541859ac0c16Sdavemq for (i = 0; i < cl45_arr_len; i++) { 541930505775Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 542030505775Ssbehera (id & BCM_PHY_ID_MASK)) { 542159ac0c16Sdavemq found = B_TRUE; 542259ac0c16Sdavemq break; 542359ac0c16Sdavemq } 542459ac0c16Sdavemq } 542559ac0c16Sdavemq break; 542659ac0c16Sdavemq case CLAUSE_22_TYPE: 542759ac0c16Sdavemq for (i = 0; i < cl22_arr_len; i++) { 542830505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 542930505775Ssbehera (id & BCM_PHY_ID_MASK)) { 543059ac0c16Sdavemq found = B_TRUE; 543159ac0c16Sdavemq break; 543256d930aeSspeer } 543344961713Sgirish } 543459ac0c16Sdavemq break; 543559ac0c16Sdavemq default: 543659ac0c16Sdavemq break; 543756d930aeSspeer } 543856d930aeSspeer 543959ac0c16Sdavemq return (found); 544059ac0c16Sdavemq } 544159ac0c16Sdavemq 54422e59129aSraghus static uint32_t 54432e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 54442e59129aSraghus { 54452e59129aSraghus uint16_t val1 = 0; 54462e59129aSraghus uint16_t val2 = 0; 54472e59129aSraghus uint32_t pma_pmd_dev_id = 0; 54482e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 54492e59129aSraghus 545053560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 54512e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 54522e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 54532e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 54542e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 545553560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 54562e59129aSraghus 54572e59129aSraghus pma_pmd_dev_id = val1; 54582e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 54592e59129aSraghus pma_pmd_dev_id |= val2; 54602e59129aSraghus 54612e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 54622e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 54632e59129aSraghus 54642e59129aSraghus return (pma_pmd_dev_id); 54652e59129aSraghus } 54662e59129aSraghus 54672e59129aSraghus static uint32_t 54682e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 54692e59129aSraghus { 54702e59129aSraghus uint16_t val1 = 0; 54712e59129aSraghus uint16_t val2 = 0; 54722e59129aSraghus uint32_t pcs_dev_id = 0; 54732e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 54742e59129aSraghus 547553560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 54762e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 54772e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 54782e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 54792e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 548053560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 54812e59129aSraghus 54822e59129aSraghus pcs_dev_id = val1; 54832e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 54842e59129aSraghus pcs_dev_id |= val2; 54852e59129aSraghus 54862e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 54872e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 54882e59129aSraghus 54892e59129aSraghus return (pcs_dev_id); 54902e59129aSraghus } 54912e59129aSraghus 54922e59129aSraghus static uint32_t 54932e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 54942e59129aSraghus { 54952e59129aSraghus uint16_t val1 = 0; 54962e59129aSraghus uint16_t val2 = 0; 54972e59129aSraghus uint32_t phy_id = 0; 54982e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 54992e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 55002e59129aSraghus 5501321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 55022e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 55032e59129aSraghus &val1); 55042e59129aSraghus if (npi_status != NPI_SUCCESS) { 55052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 55062e59129aSraghus "clause 22 read to reg 2 failed!!!")); 55072e59129aSraghus goto exit; 55082e59129aSraghus } 55092e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 55102e59129aSraghus &val2); 55112e59129aSraghus if (npi_status != 0) { 55122e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 55132e59129aSraghus "clause 22 read to reg 3 failed!!!")); 55142e59129aSraghus goto exit; 55152e59129aSraghus } 55162e59129aSraghus phy_id = val1; 55172e59129aSraghus phy_id = (phy_id << 16); 55182e59129aSraghus phy_id |= val2; 55192e59129aSraghus 55202e59129aSraghus exit: 5521321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 55222e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 55232e59129aSraghus phy_port, phy_id)); 55242e59129aSraghus 55252e59129aSraghus return (phy_id); 55262e59129aSraghus } 55272e59129aSraghus 552859ac0c16Sdavemq /* 552959ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 553059ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 553159ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 553259ac0c16Sdavemq * and the Neptune type. 553359ac0c16Sdavemq */ 553459ac0c16Sdavemq 553559ac0c16Sdavemq nxge_status_t 553659ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 553759ac0c16Sdavemq { 553859a835ddSjoycey int i, j, l; 553959ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 554059ac0c16Sdavemq uint32_t pcs_dev_id = 0; 554159ac0c16Sdavemq uint32_t phy_id = 0; 554230505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 554330505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 554430505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 554559ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 554659ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 55472d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 55482d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 554959ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 555059ac0c16Sdavemq nxge_status_t status = NXGE_OK; 555156d930aeSspeer 555259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 555356d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 555459ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 555559ac0c16Sdavemq nxgep->niu_type)); 555659ac0c16Sdavemq 5557*678453a8Sspeer if (isLDOMguest(nxgep)) { 5558*678453a8Sspeer hw_p->niu_type = NIU_TYPE_NONE; 5559*678453a8Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 5560*678453a8Sspeer return (NXGE_OK); 5561*678453a8Sspeer } 5562*678453a8Sspeer 556359a835ddSjoycey j = l = 0; 556459ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 556556d930aeSspeer /* 556659ac0c16Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 556759ac0c16Sdavemq * for on chip serdes usages. 556856d930aeSspeer */ 556959ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 55702e59129aSraghus 55712e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 557259ac0c16Sdavemq 557359ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 557459ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 557559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 557659ac0c16Sdavemq "PMA/PMD dev found", i)); 557730505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 557830505775Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 557930505775Ssbehera BCM_PHY_ID_MASK; 55802d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 558159ac0c16Sdavemq j++; 558259ac0c16Sdavemq } 558359ac0c16Sdavemq } else { 558459ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 558559ac0c16Sdavemq } 558659ac0c16Sdavemq 55872e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 558859ac0c16Sdavemq 558959ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 559059ac0c16Sdavemq pcs_dev_fd[i] = 1; 559159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 559259ac0c16Sdavemq "dev found", i)); 559359a835ddSjoycey if (pma_pmd_dev_fd[i] == 1) { 559459a835ddSjoycey port_pcs_dev_id[j - 1] = pcs_dev_id & 559530505775Ssbehera BCM_PHY_ID_MASK; 559659a835ddSjoycey } else { 559759a835ddSjoycey if (j < NXGE_PORTS_NEPTUNE) { 559859a835ddSjoycey port_pcs_dev_id[j] = pcs_dev_id & 559959a835ddSjoycey BCM_PHY_ID_MASK; 560059a835ddSjoycey port_fd_arr[j] = (uint8_t)i; 560159a835ddSjoycey j++; 560259a835ddSjoycey } 560359ac0c16Sdavemq } 560459ac0c16Sdavemq } else { 560559ac0c16Sdavemq pcs_dev_fd[i] = 0; 560659ac0c16Sdavemq } 560759ac0c16Sdavemq 56082d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 56092d17280bSsbehera total_port_fd ++; 56102d17280bSsbehera } 561159ac0c16Sdavemq 56122e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 561359ac0c16Sdavemq 561459ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 56152d17280bSsbehera total_phy_fd ++; 561659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 561759ac0c16Sdavemq "found", i)); 561830505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 561930505775Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 56202d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 562159ac0c16Sdavemq l++; 562259ac0c16Sdavemq } 562359ac0c16Sdavemq } 562459ac0c16Sdavemq } 562559ac0c16Sdavemq 562659ac0c16Sdavemq switch (total_port_fd) { 562759ac0c16Sdavemq case 2: 562859ac0c16Sdavemq switch (total_phy_fd) { 562959ac0c16Sdavemq case 2: 563059a835ddSjoycey /* 2 10G, 2 1G RGMII Fiber */ 563159a835ddSjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 563259a835ddSjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 563359a835ddSjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 563459a835ddSjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 563559a835ddSjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 563659a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 563759a835ddSjoycey 563859a835ddSjoycey hw_p->platform_type = 563959a835ddSjoycey P_NEPTUNE_GENERIC; 564059a835ddSjoycey 564159a835ddSjoycey hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 564259a835ddSjoycey 564359a835ddSjoycey hw_p->xcvr_addr[0] = port_fd_arr[0]; 564459a835ddSjoycey hw_p->xcvr_addr[1] = port_fd_arr[1]; 564559a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 564659a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 564759a835ddSjoycey 564859a835ddSjoycey NXGE_DEBUG_MSG((nxgep, MAC_CTL, 564959a835ddSjoycey "ARTM card with 2 10G, 2 1G")); 565059a835ddSjoycey } else { 565159a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 565259a835ddSjoycey "Unsupported neptune type 1")); 565359a835ddSjoycey goto error_exit; 565459a835ddSjoycey } 565559a835ddSjoycey break; 565659a835ddSjoycey 565759ac0c16Sdavemq case 1: 565859ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 565959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 566059ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 566159ac0c16Sdavemq goto error_exit; 566259ac0c16Sdavemq case 0: 566359ac0c16Sdavemq /* 2 10G */ 566430505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 566530505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 566630505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 566730505775Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 56682e59129aSraghus 56692e59129aSraghus /* 56702e59129aSraghus * Check the first phy port address against 56712e59129aSraghus * the known phy start addresses to determine 56722e59129aSraghus * the platform type. 56732e59129aSraghus */ 56742d17280bSsbehera 56752d17280bSsbehera switch (port_fd_arr[0]) { 56762d17280bSsbehera case BCM8704_NEPTUNE_PORT_ADDR_BASE: 56772e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 56782e59129aSraghus hw_p->platform_type = 56792e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 56802d17280bSsbehera break; 56812d17280bSsbehera case BCM8706_GOA_PORT_ADDR_BASE: 56822d17280bSsbehera if (hw_p->platform_type != 56832d17280bSsbehera P_NEPTUNE_NIU) { 56842d17280bSsbehera hw_p->platform_type = 56852d17280bSsbehera P_NEPTUNE_GENERIC; 56862d17280bSsbehera hw_p->niu_type = 56872d17280bSsbehera NEPTUNE_2_10GF; 56882d17280bSsbehera } 56892d17280bSsbehera break; 56902d17280bSsbehera default: 56912d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 56922e59129aSraghus "Unsupported neptune type 2 - 1")); 56932e59129aSraghus goto error_exit; 56942e59129aSraghus } 56952d17280bSsbehera 56962d17280bSsbehera for (i = 0; i < 2; i++) { 56972d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 56982d17280bSsbehera } 569959ac0c16Sdavemq } else { 570059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 570159ac0c16Sdavemq "Unsupported neptune type 2")); 570259ac0c16Sdavemq goto error_exit; 570359ac0c16Sdavemq } 570459ac0c16Sdavemq break; 570559ac0c16Sdavemq case 4: 570659ac0c16Sdavemq /* Maramba with 2 XAUI */ 570730505775Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 570830505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 570930505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 571030505775Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 571130505775Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 571230505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 571330505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 571430505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 571559ac0c16Sdavemq 571659ac0c16Sdavemq /* 571759ac0c16Sdavemq * Check the first phy port address against 571859ac0c16Sdavemq * the known phy start addresses to determine 571959ac0c16Sdavemq * the platform type. 572059ac0c16Sdavemq */ 57212d17280bSsbehera switch (phy_fd_arr[0]) { 57222d17280bSsbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 572359ac0c16Sdavemq hw_p->platform_type = 572459ac0c16Sdavemq P_NEPTUNE_MARAMBA_P0; 57252d17280bSsbehera break; 57262d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 572759ac0c16Sdavemq hw_p->platform_type = 572859ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 57292d17280bSsbehera break; 57302d17280bSsbehera default: 573159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 573259ac0c16Sdavemq "Unknown port %d...Cannot " 573359ac0c16Sdavemq "determine platform type", i)); 57342e59129aSraghus goto error_exit; 573559ac0c16Sdavemq } 57362d17280bSsbehera 57372e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 57382e59129aSraghus 57392d17280bSsbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 57402d17280bSsbehera hw_p->xcvr_addr[1] = port_fd_arr[1]; 57412d17280bSsbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 57422d17280bSsbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 57432d17280bSsbehera 574459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 574559ac0c16Sdavemq "Maramba with 2 XAUI")); 574659ac0c16Sdavemq } else { 574759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 574859ac0c16Sdavemq "Unsupported neptune type 3")); 574959ac0c16Sdavemq goto error_exit; 575059ac0c16Sdavemq } 575159ac0c16Sdavemq break; 575259ac0c16Sdavemq default: 575359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 575459ac0c16Sdavemq "Unsupported neptune type 5")); 575559ac0c16Sdavemq goto error_exit; 575659ac0c16Sdavemq } 575730505775Ssbehera break; 575859ac0c16Sdavemq case 1: 575959ac0c16Sdavemq switch (total_phy_fd) { 576059ac0c16Sdavemq case 3: 57612e59129aSraghus /* 57622e59129aSraghus * TODO 3 1G, 1 10G mode. 57632e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 57642e59129aSraghus * 1_10G_3_1G 57652e59129aSraghus */ 57662e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 57672e59129aSraghus "Unsupported neptune type 7")); 57682e59129aSraghus goto error_exit; 576959ac0c16Sdavemq case 2: 577059ac0c16Sdavemq /* 577159ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 577259ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 577359ac0c16Sdavemq * 1_10G_2_1G 577459ac0c16Sdavemq */ 577559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 577659ac0c16Sdavemq "Unsupported neptune type 8")); 577759ac0c16Sdavemq goto error_exit; 577859ac0c16Sdavemq case 1: 577959ac0c16Sdavemq /* 578059ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 578159ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 578259ac0c16Sdavemq * 1_10G_1_1G 578359ac0c16Sdavemq */ 578459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 578559ac0c16Sdavemq "Unsupported neptune type 9")); 578659ac0c16Sdavemq goto error_exit; 578759ac0c16Sdavemq case 0: 57882d17280bSsbehera /* 1 10G mode, N2 with 1 XAUI */ 57892d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 57902d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 57912d17280bSsbehera 57922d17280bSsbehera /* 57932d17280bSsbehera * Check the first phy port address against 57942d17280bSsbehera * the known phy start addresses to determine 57952d17280bSsbehera * the platform type. 57962d17280bSsbehera */ 57972d17280bSsbehera 57982d17280bSsbehera switch (port_fd_arr[0]) { 57992d17280bSsbehera case BCM8704_N2_PORT_ADDR_BASE: 58002d17280bSsbehera case (BCM8704_N2_PORT_ADDR_BASE + 1): 58012d17280bSsbehera case BCM8706_ALT_GOA_PORT1_ADDR: 58022d17280bSsbehera if (hw_p->platform_type != 58032d17280bSsbehera P_NEPTUNE_NIU) { 58042d17280bSsbehera hw_p->platform_type = 58052d17280bSsbehera P_NEPTUNE_GENERIC; 58062d17280bSsbehera hw_p->niu_type = 58072d17280bSsbehera NEPTUNE_2_10GF; 58082d17280bSsbehera } 58092d17280bSsbehera break; 58102d17280bSsbehera default: 58112d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58122d17280bSsbehera "Unsupported neptune type 10")); 58132d17280bSsbehera goto error_exit; 58142d17280bSsbehera } 5815321febdeSsbehera /* 5816321febdeSsbehera * For GOA, which is a hot swappable PHY, the 5817321febdeSsbehera * phy address to function number mapping 5818321febdeSsbehera * should be preserved, i.e., addr 16 is 5819321febdeSsbehera * assigned to function 0 and 20 to function 1 5820321febdeSsbehera * But for Huron XAUI, the assignment should 5821321febdeSsbehera * be by function number, i.e., whichever 5822321febdeSsbehera * function number attaches should be 5823321febdeSsbehera * assigned the available PHY (this is required 5824321febdeSsbehera * primarily to support pre-production Huron 5825321febdeSsbehera * boards where function 0 is mapped to addr 17 5826321febdeSsbehera */ 5827321febdeSsbehera if (port_fd_arr[0] == 5828321febdeSsbehera BCM8706_ALT_GOA_PORT1_ADDR) { 5829321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 5830321febdeSsbehera } else { 5831321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 5832321febdeSsbehera port_fd_arr[0]; 5833321febdeSsbehera } 58342d17280bSsbehera } else { 58352d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 58362d17280bSsbehera "Unsupported neptune type 10 - 1")); 58372d17280bSsbehera goto error_exit; 58382d17280bSsbehera } 58392d17280bSsbehera break; 584059ac0c16Sdavemq case 4: 584159ac0c16Sdavemq /* Maramba with 1 XAUI */ 584230505775Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 584330505775Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 584459ac0c16Sdavemq 584559ac0c16Sdavemq /* 584659ac0c16Sdavemq * Check the first phy port address against 584759ac0c16Sdavemq * the known phy start addresses to determine 584859ac0c16Sdavemq * the platform type. 584959ac0c16Sdavemq */ 58502d17280bSsbehera switch (phy_fd_arr[0]) { 58512d17280bSsbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 585259ac0c16Sdavemq hw_p->platform_type = 585359ac0c16Sdavemq P_NEPTUNE_MARAMBA_P0; 58542d17280bSsbehera break; 58552d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 585659ac0c16Sdavemq hw_p->platform_type = 585759ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 58582d17280bSsbehera break; 58592d17280bSsbehera default: 586059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 586159ac0c16Sdavemq "Unknown port %d...Cannot " 58622d17280bSsbehera "determine platform type 10 - 2", 58632d17280bSsbehera i)); 58642e59129aSraghus goto error_exit; 58652e59129aSraghus } 58662e59129aSraghus 58672d17280bSsbehera /* 58682d17280bSsbehera * Check the BCM8704 address to determine 58692d17280bSsbehera * if XAUI is in port 0 or port 1. 58702d17280bSsbehera */ 58712d17280bSsbehera switch (port_fd_arr[0]) { 58722d17280bSsbehera case BCM8704_MARAMBA_PORT_ADDR_BASE: 58732e59129aSraghus hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 58742d17280bSsbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 58752d17280bSsbehera for (i = 1; i < NXGE_MAX_PORTS; i++) { 58762d17280bSsbehera hw_p->xcvr_addr[i] = 58772d17280bSsbehera phy_fd_arr[i]; 58782d17280bSsbehera } 58792d17280bSsbehera break; 58802d17280bSsbehera case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1): 58812e59129aSraghus hw_p->niu_type = 58822e59129aSraghus NEPTUNE_1_1GC_1_10GF_2_1GC; 58832d17280bSsbehera hw_p->xcvr_addr[0] = phy_fd_arr[0]; 58842d17280bSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 58852d17280bSsbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 58862d17280bSsbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 58872d17280bSsbehera break; 58882d17280bSsbehera default: 58892e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 58902e59129aSraghus "Unsupported neptune type 11")); 58912e59129aSraghus goto error_exit; 589259ac0c16Sdavemq } 589359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 589459ac0c16Sdavemq "Maramba with 1 XAUI")); 589559ac0c16Sdavemq } else { 589659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 589759ac0c16Sdavemq "Unsupported neptune type 12")); 589859ac0c16Sdavemq goto error_exit; 589959ac0c16Sdavemq } 590059ac0c16Sdavemq break; 590159ac0c16Sdavemq default: 590259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 590359ac0c16Sdavemq "Unsupported neptune type 13")); 590459ac0c16Sdavemq goto error_exit; 590559ac0c16Sdavemq } 590659ac0c16Sdavemq break; 590759ac0c16Sdavemq case 0: 590859ac0c16Sdavemq switch (total_phy_fd) { 590959ac0c16Sdavemq case 4: 591030505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 591130505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 591230505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 591330505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 591459ac0c16Sdavemq 591559ac0c16Sdavemq /* 591659ac0c16Sdavemq * Check the first phy port address against 591759ac0c16Sdavemq * the known phy start addresses to determine 591859ac0c16Sdavemq * the platform type. 591959ac0c16Sdavemq */ 59202d17280bSsbehera switch (phy_fd_arr[0]) { 59212d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 592259ac0c16Sdavemq hw_p->platform_type = 592359ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 59242d17280bSsbehera break; 59252d17280bSsbehera case BCM5464_NEPTUNE_PORT_ADDR_BASE: 59262e59129aSraghus hw_p->platform_type = 59272e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 59282d17280bSsbehera break; 59292d17280bSsbehera default: 59302e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59312e59129aSraghus "Unknown port %d...Cannot " 59322e59129aSraghus "determine platform type", i)); 59332e59129aSraghus goto error_exit; 593459ac0c16Sdavemq } 59352e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 59362d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 59372d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 59382d17280bSsbehera } 593959ac0c16Sdavemq } else { 594059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 594159ac0c16Sdavemq "Unsupported neptune type 14")); 594259ac0c16Sdavemq goto error_exit; 594359ac0c16Sdavemq } 594459ac0c16Sdavemq break; 594559ac0c16Sdavemq case 3: 594659ac0c16Sdavemq /* TODO 3 1G mode */ 594759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 594859ac0c16Sdavemq "Unsupported neptune type 15")); 594959ac0c16Sdavemq goto error_exit; 595059ac0c16Sdavemq case 2: 595159ac0c16Sdavemq /* TODO 2 1G mode */ 595259a835ddSjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 595359a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 595459a835ddSjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 595559a835ddSjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 595659a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 595759a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 595859a835ddSjoycey } else { 595959a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 596059a835ddSjoycey "Unsupported neptune type 16")); 596159a835ddSjoycey goto error_exit; 596259a835ddSjoycey } 596359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 596459a835ddSjoycey "2 RGMII Fiber ports - RTM")); 596559a835ddSjoycey break; 596659a835ddSjoycey 596759ac0c16Sdavemq case 1: 596859ac0c16Sdavemq /* TODO 1 1G mode */ 596959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 597059ac0c16Sdavemq "Unsupported neptune type 17")); 597159ac0c16Sdavemq goto error_exit; 597259ac0c16Sdavemq default: 597359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 597459ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 597559ac0c16Sdavemq total_phy_fd)); 597659ac0c16Sdavemq goto error_exit; 597759ac0c16Sdavemq } 597859ac0c16Sdavemq break; 597959ac0c16Sdavemq default: 598056d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 598159ac0c16Sdavemq "Unsupported neptune type 19")); 598259ac0c16Sdavemq goto error_exit; 598344961713Sgirish } 598444961713Sgirish 598559ac0c16Sdavemq scan_exit: 598644961713Sgirish 598759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 598859ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 598959ac0c16Sdavemq return (status); 599044961713Sgirish 599159ac0c16Sdavemq error_exit: 599259ac0c16Sdavemq return (NXGE_ERROR); 599344961713Sgirish } 599456d930aeSspeer 599556d930aeSspeer boolean_t 599656d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 599756d930aeSspeer { 599856d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 599956d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 600056d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 600156d930aeSspeer return (B_FALSE); 600256d930aeSspeer else 600356d930aeSspeer return (B_TRUE); 600456d930aeSspeer } 600559ac0c16Sdavemq 600659ac0c16Sdavemq static void 600759ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 600859ac0c16Sdavemq 600959ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 601059ac0c16Sdavemq uint8_t xcvr_portn; 601159ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 601259ac0c16Sdavemq 601359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 601459ac0c16Sdavemq 601559ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 601659ac0c16Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 601759ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 601859ac0c16Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 601959ac0c16Sdavemq } 602059ac0c16Sdavemq /* 602159ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 602259ac0c16Sdavemq * swapped with ethernet port number. This is 602359ac0c16Sdavemq * designed for better signal integrity in routing. 602459ac0c16Sdavemq */ 602559ac0c16Sdavemq switch (portn) { 602659ac0c16Sdavemq case 0: 602759ac0c16Sdavemq xcvr_portn += 3; 602859ac0c16Sdavemq break; 602959ac0c16Sdavemq case 1: 603059ac0c16Sdavemq xcvr_portn += 2; 603159ac0c16Sdavemq break; 603259ac0c16Sdavemq case 2: 603359ac0c16Sdavemq xcvr_portn += 1; 603459ac0c16Sdavemq break; 603559ac0c16Sdavemq case 3: 603659ac0c16Sdavemq default: 603759ac0c16Sdavemq break; 603859ac0c16Sdavemq } 603959ac0c16Sdavemq 6040321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 604159ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 604259ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 604359ac0c16Sdavemq if (rs != NPI_SUCCESS) { 604459ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 604559ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 604659ac0c16Sdavemq "returned error 0x[%x]", rs)); 6047321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 604859ac0c16Sdavemq return; 604959ac0c16Sdavemq } 605059ac0c16Sdavemq 605159ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 605259ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 605359ac0c16Sdavemq if (rs != NPI_SUCCESS) { 605459ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 605559ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 605659ac0c16Sdavemq "returned error 0x[%x]", rs)); 605759ac0c16Sdavemq } 605859ac0c16Sdavemq 6059321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 606059ac0c16Sdavemq } 6061d81011f0Ssbehera 6062d81011f0Ssbehera static nxge_status_t 6063d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 6064d81011f0Ssbehera { 6065d81011f0Ssbehera p_nxge_stats_t statsp; 6066d81011f0Ssbehera uint8_t xcvr_portn; 6067d81011f0Ssbehera p_mii_regs_t mii_regs; 6068d81011f0Ssbehera mii_mode_control_stat_t mode; 6069d81011f0Ssbehera int status = NXGE_OK; 6070d81011f0Ssbehera 6071d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 6072d81011f0Ssbehera 6073d81011f0Ssbehera statsp = nxgep->statsp; 6074d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 6075d81011f0Ssbehera mii_regs = NULL; 6076d81011f0Ssbehera mode.value = 0; 60776b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 6078d81011f0Ssbehera #if defined(__i386) 6079d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 6080d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 6081d81011f0Ssbehera mode.value)) != NXGE_OK) { 6082d81011f0Ssbehera goto fail; 6083d81011f0Ssbehera #else 6084d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 6085d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 6086d81011f0Ssbehera mode.value)) != NXGE_OK) { 6087d81011f0Ssbehera goto fail; 6088d81011f0Ssbehera #endif 6089d81011f0Ssbehera } 6090d81011f0Ssbehera #if defined(__i386) 6091d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 6092d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 6093d81011f0Ssbehera &mode.value)) != NXGE_OK) { 6094d81011f0Ssbehera goto fail; 6095d81011f0Ssbehera } 6096d81011f0Ssbehera #else 6097d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 6098d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 6099d81011f0Ssbehera &mode.value)) != NXGE_OK) { 6100d81011f0Ssbehera goto fail; 6101d81011f0Ssbehera } 6102d81011f0Ssbehera #endif 6103d81011f0Ssbehera 6104d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 6105d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6106d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6107d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 6108d81011f0Ssbehera } 6109d81011f0Ssbehera 6110d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6111d81011f0Ssbehera "nxge_mii_get_link_mode: " 6112d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 61136b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 6114d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 6115d81011f0Ssbehera 6116d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6117d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 6118d81011f0Ssbehera return (status); 6119d81011f0Ssbehera fail: 6120d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6121d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 6122d81011f0Ssbehera return (NXGE_ERROR); 6123d81011f0Ssbehera } 6124d81011f0Ssbehera 61251bd6825cSml nxge_status_t 61261bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep) 61271bd6825cSml { 61281bd6825cSml npi_attr_t ap; 61291bd6825cSml uint8_t portn; 61301bd6825cSml npi_handle_t handle; 61311bd6825cSml npi_status_t rs = NPI_SUCCESS; 61321bd6825cSml 61331bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 61341bd6825cSml 61351bd6825cSml portn = NXGE_GET_PORT_NUM(nxgep->function_num); 61361bd6825cSml handle = nxgep->npi_handle; 61371bd6825cSml 61381bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61391bd6825cSml "==> nxge_mac_sec_framesize: port<%d> " 61401bd6825cSml "min framesize %d max framesize %d ", 61411bd6825cSml portn, 61421bd6825cSml nxgep->mac.minframesize, 61431bd6825cSml nxgep->mac.maxframesize)); 61441bd6825cSml 61451bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 61461bd6825cSml MAC_PORT_FRAME_SIZE, 61471bd6825cSml nxgep->mac.minframesize, 61481bd6825cSml nxgep->mac.maxframesize, 61491bd6825cSml rs); 61501bd6825cSml if (rs != NPI_SUCCESS) { 61511bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61521bd6825cSml "<== nxge_mac_set_framesize: failed to configure " 61531bd6825cSml "max/min frame size port %d", portn)); 61541bd6825cSml 61551bd6825cSml return (NXGE_ERROR | rs); 61561bd6825cSml } 61571bd6825cSml 61581bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61591bd6825cSml "<== nxge_mac_set_framesize: port<%d>", portn)); 61601bd6825cSml 61611bd6825cSml return (NXGE_OK); 61621bd6825cSml } 61631bd6825cSml 6164d81011f0Ssbehera #ifdef NXGE_DEBUG 6165d81011f0Ssbehera static void 6166d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 6167d81011f0Ssbehera { 6168d81011f0Ssbehera p_nxge_stats_t statsp; 6169d81011f0Ssbehera uint8_t xcvr_portn; 6170d81011f0Ssbehera p_mii_regs_t mii_regs; 6171d81011f0Ssbehera mii_bmcr_t bmcr; 6172d81011f0Ssbehera mii_bmsr_t bmsr; 6173d81011f0Ssbehera mii_idr1_t idr1; 6174d81011f0Ssbehera mii_idr2_t idr2; 6175d81011f0Ssbehera mii_mode_control_stat_t mode; 6176*678453a8Sspeer p_nxge_param_t param_arr; 6177d81011f0Ssbehera 6178d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 6179d81011f0Ssbehera 6180d81011f0Ssbehera statsp = nxgep->statsp; 6181d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 6182d81011f0Ssbehera 6183d81011f0Ssbehera mii_regs = NULL; 6184d81011f0Ssbehera 6185d81011f0Ssbehera #if defined(__i386) 6186d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 6187d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 6188d81011f0Ssbehera #else 6189d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 6190d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 6191d81011f0Ssbehera #endif 6192d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6193d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 6194d81011f0Ssbehera xcvr_portn, bmcr.value)); 6195d81011f0Ssbehera 6196d81011f0Ssbehera #if defined(__i386) 6197d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6198d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6199d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 6200d81011f0Ssbehera #else 6201d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6202d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6203d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 6204d81011f0Ssbehera #endif 6205d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6206d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 6207d81011f0Ssbehera xcvr_portn, bmsr.value)); 6208d81011f0Ssbehera 6209d81011f0Ssbehera #if defined(__i386) 6210d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6211d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6212d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 6213d81011f0Ssbehera #else 6214d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6215d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6216d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 6217d81011f0Ssbehera #endif 6218d81011f0Ssbehera 6219d81011f0Ssbehera 6220d81011f0Ssbehera #if defined(__i386) 6221d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6222d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6223d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 6224d81011f0Ssbehera #else 6225d81011f0Ssbehera (void) nxge_mii_read(nxgep, 6226d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 6227d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 6228d81011f0Ssbehera #endif 6229d81011f0Ssbehera 6230d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6231d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 6232d81011f0Ssbehera xcvr_portn, idr1.value)); 6233d81011f0Ssbehera 6234d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6235d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 6236d81011f0Ssbehera xcvr_portn, idr2.value)); 6237d81011f0Ssbehera 6238d81011f0Ssbehera mode.value = 0; 62396b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 6240d81011f0Ssbehera 6241d81011f0Ssbehera #if defined(__i386) 6242d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 6243d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 6244d81011f0Ssbehera 6245d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 6246d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 6247d81011f0Ssbehera #else 6248d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 6249d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 6250d81011f0Ssbehera 6251d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 6252d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 6253d81011f0Ssbehera #endif 6254d81011f0Ssbehera 6255d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6256d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 6257d81011f0Ssbehera xcvr_portn, mode.value)); 6258d81011f0Ssbehera } 6259d81011f0Ssbehera #endif 6260