13859Sml29623 /* 23859Sml29623 * CDDL HEADER START 33859Sml29623 * 43859Sml29623 * The contents of this file are subject to the terms of the 53859Sml29623 * Common Development and Distribution License (the "License"). 63859Sml29623 * You may not use this file except in compliance with the License. 73859Sml29623 * 83859Sml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93859Sml29623 * or http://www.opensolaris.org/os/licensing. 103859Sml29623 * See the License for the specific language governing permissions 113859Sml29623 * and limitations under the License. 123859Sml29623 * 133859Sml29623 * When distributing Covered Code, include this CDDL HEADER in each 143859Sml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153859Sml29623 * If applicable, add the following below this CDDL HEADER, with the 163859Sml29623 * fields enclosed by brackets "[]" replaced with your own identifying 173859Sml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 183859Sml29623 * 193859Sml29623 * CDDL HEADER END 203859Sml29623 */ 213859Sml29623 /* 225780Ssbehera * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 233859Sml29623 * Use is subject to license terms. 243859Sml29623 */ 253859Sml29623 263859Sml29623 #pragma ident "%Z%%M% %I% %E% SMI" 273859Sml29623 283859Sml29623 #include <sys/nxge/nxge_impl.h> 293859Sml29623 #include <sys/nxge/nxge_mac.h> 306495Sspeer #include <sys/nxge/nxge_hio.h> 313859Sml29623 324693Stm144005 #define LINK_MONITOR_PERIOD (1000 * 1000) 334693Stm144005 #define LM_WAIT_MULTIPLIER 8 344693Stm144005 356075Ssbehera #define SERDES_RDY_WT_INTERVAL 50 366075Ssbehera #define MAX_SERDES_RDY_RETRIES 10 376075Ssbehera 383859Sml29623 extern uint32_t nxge_no_link_notify; 394732Sdavemq extern boolean_t nxge_no_msg; 403859Sml29623 extern uint32_t nxge_lb_dbg; 413859Sml29623 extern boolean_t nxge_jumbo_enable; 426028Ssbehera extern uint32_t nxge_jumbo_mtu; 433859Sml29623 446495Sspeer /* The following functions may be found in nxge_main.c */ 456495Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 466495Sspeer boolean_t factory); 476495Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 486495Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 496495Sspeer 504693Stm144005 typedef enum { 514693Stm144005 CHECK_LINK_RESCHEDULE, 524693Stm144005 CHECK_LINK_STOP 534693Stm144005 } check_link_state_t; 544693Stm144005 554693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *); 564693Stm144005 573859Sml29623 /* 583859Sml29623 * Ethernet broadcast address definition. 593859Sml29623 */ 603859Sml29623 static ether_addr_st etherbroadcastaddr = 613859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 624732Sdavemq /* 634732Sdavemq * Ethernet zero address definition. 644732Sdavemq */ 654185Sspeer static ether_addr_st etherzeroaddr = 664185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 674732Sdavemq /* 684732Sdavemq * Supported chip types 694732Sdavemq */ 706604Ssbehera static uint32_t nxge_supported_cl45_ids[] = { 716604Ssbehera BCM8704_DEV_ID, 726604Ssbehera MARVELL_88X_201X_DEV_ID, 736604Ssbehera BCM8706_DEV_ID 746604Ssbehera }; 756604Ssbehera 766604Ssbehera static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 774732Sdavemq 784732Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 794732Sdavemq sizeof (uint32_t)) 804732Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 814732Sdavemq sizeof (uint32_t)) 824732Sdavemq /* 834732Sdavemq * static functions 844732Sdavemq */ 854977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 864977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 874977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 884732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 895572Ssbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 904732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 914732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 924732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 934732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 944732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 954732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 964732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 974732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 984732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 994732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 1004732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 1014732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 1025572Ssbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 1035572Ssbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 1044732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 1054732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 1066604Ssbehera static nxge_status_t nxge_mrvl88x2011_link(p_nxge_t, boolean_t *); 1076604Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t); 1084732Sdavemq 1094732Sdavemq /* 1104732Sdavemq * xcvr tables for supported transceivers 1114732Sdavemq */ 1124732Sdavemq 1134977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 1144732Sdavemq nxge_n2_serdes_init, 1154732Sdavemq nxge_10G_xcvr_init, 1164732Sdavemq nxge_10G_link_intr_stop, 1174732Sdavemq nxge_10G_link_intr_start, 1184732Sdavemq nxge_check_10g_link, 1195572Ssbehera PCS_XCVR 1204732Sdavemq }; 1214732Sdavemq 1224977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1234977Sraghus nxge_n2_serdes_init, 1244977Sraghus nxge_1G_xcvr_init, 1254977Sraghus nxge_1G_fiber_link_intr_stop, 1264977Sraghus nxge_1G_fiber_link_intr_start, 1274977Sraghus nxge_check_mii_link, 1285572Ssbehera PCS_XCVR 1294977Sraghus }; 1304977Sraghus 1314732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 1324732Sdavemq nxge_neptune_10G_serdes_init, 1334732Sdavemq nxge_10G_xcvr_init, 1344732Sdavemq nxge_10G_link_intr_stop, 1354732Sdavemq nxge_10G_link_intr_start, 1364732Sdavemq nxge_check_10g_link, 1375572Ssbehera PCS_XCVR 1384732Sdavemq }; 1394732Sdavemq 1404732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 1414732Sdavemq NULL, 1424732Sdavemq nxge_1G_xcvr_init, 1434732Sdavemq nxge_1G_copper_link_intr_stop, 1444732Sdavemq nxge_1G_copper_link_intr_start, 1454732Sdavemq nxge_check_mii_link, 1465572Ssbehera INT_MII_XCVR 1474732Sdavemq }; 1484732Sdavemq 1494732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 1504732Sdavemq nxge_1G_serdes_init, 1514732Sdavemq nxge_1G_xcvr_init, 1524732Sdavemq nxge_1G_fiber_link_intr_stop, 1534732Sdavemq nxge_1G_fiber_link_intr_start, 1544732Sdavemq nxge_check_mii_link, 1555572Ssbehera PCS_XCVR 1564732Sdavemq }; 1574732Sdavemq 1584732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 1594732Sdavemq nxge_neptune_10G_serdes_init, 1604732Sdavemq NULL, 1614732Sdavemq NULL, 1624732Sdavemq NULL, 1634977Sraghus NULL, 1645572Ssbehera PCS_XCVR 1654732Sdavemq }; 1663859Sml29623 1673859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 1683859Sml29623 1695196Ssbehera #ifdef NXGE_DEBUG 1705196Ssbehera static void nxge_mii_dump(p_nxge_t); 1715196Ssbehera #endif 1725196Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 1735196Ssbehera 1744977Sraghus nxge_status_t 1754977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep) 1764977Sraghus { 1774977Sraghus nxge_status_t status = NXGE_OK; 1784977Sraghus char *phy_type; 1794977Sraghus char *prop_val; 1804977Sraghus 1814977Sraghus nxgep->mac.portmode = 0; 1825572Ssbehera nxgep->xcvr_addr = 0; 1835572Ssbehera 1845572Ssbehera /* 1855572Ssbehera * First check for hot swappable phy property. 1865572Ssbehera */ 1875572Ssbehera if (nxgep->hot_swappable_phy == B_TRUE) { 1885572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1895572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 1905572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 1915572Ssbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 1925572Ssbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1935572Ssbehera "hot-swappable-phy") == 1) { 1945572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1955572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 1965572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 1975572Ssbehera } else if (nxgep->niu_type == N2_NIU && 1985572Ssbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 1995572Ssbehera "hot-swappable-phy") == 1) { 2005572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 2015572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 2025572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 2035572Ssbehera } 2045572Ssbehera 2055572Ssbehera /* 2065572Ssbehera * MDIO polling support for Monza RTM card, Goa NEM card 2075572Ssbehera */ 2085572Ssbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 2095572Ssbehera 2105572Ssbehera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2115572Ssbehera 2125572Ssbehera nxgep->hot_swappable_phy = B_TRUE; 2135572Ssbehera /* 2145572Ssbehera * If this is the 2nd NIU port, then check 2 addresses 2155572Ssbehera * to take care of the Goa NEM card. Port 1 can have addr 17 2165572Ssbehera * (in the eval board) or 20 (in the P0 board). 2175572Ssbehera */ 2185572Ssbehera if (portn == 1) { 2195572Ssbehera if (nxge_is_phy_present(nxgep, 2205572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID, 2215572Ssbehera BCM_PHY_ID_MASK)) { 2225572Ssbehera nxgep->xcvr_addr = 2235572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR; 2245572Ssbehera goto found_phy; 2255572Ssbehera } 2265572Ssbehera } 2275572Ssbehera if (nxge_is_phy_present(nxgep, 2286495Sspeer BCM8706_GOA_PORT_ADDR_BASE + portn, 2295572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 2306495Sspeer nxgep->xcvr_addr = BCM8706_GOA_PORT_ADDR_BASE + 2315572Ssbehera portn; 2325572Ssbehera goto found_phy; 2335572Ssbehera } 2345572Ssbehera 2355572Ssbehera nxgep->phy_absent = B_TRUE; 2365572Ssbehera goto check_phy_done; 2375572Ssbehera found_phy: 2385572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2395572Ssbehera nxgep->mac.portmode = PORT_10G_FIBER; 2405572Ssbehera nxgep->phy_absent = B_FALSE; 2415572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 2425572Ssbehera "found for hot swappable phy")); 2435572Ssbehera check_phy_done: 2445572Ssbehera return (status); 2455572Ssbehera } 2465572Ssbehera 2475572Ssbehera /* Get phy-type property from the driver conf. file */ 2484977Sraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 2494977Sraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2504977Sraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 2514977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2524977Sraghus "found conf file: phy-type %s", prop_val)); 2534977Sraghus if (strcmp("xgsd", prop_val) == 0) { 2544977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2554977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 2564977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2574977Sraghus "found: 10G Serdes")); 2584977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 2594977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2604977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 2614977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 2624977Sraghus } else if (strcmp("mif", prop_val) == 0) { 2634977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 2644977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 2654977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 2664977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 2674977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2684977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 2694977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 2706075Ssbehera } else if (strcmp("xgf", prop_val) == 0) { 2716075Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2726075Ssbehera nxgep->mac.portmode = PORT_10G_FIBER; 2736075Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr")); 2744977Sraghus } 2754977Sraghus 2764977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 2774977Sraghus "phy-type", prop_val); 2784977Sraghus ddi_prop_free(prop_val); 2794977Sraghus 2804977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 2814977Sraghus "Got phy type [0x%x] from conf file", 2824977Sraghus nxgep->mac.portmode)); 2834977Sraghus 2844977Sraghus return (NXGE_OK); 2854977Sraghus } 2865572Ssbehera 2875572Ssbehera /* Get phy-type property from OBP */ 2884977Sraghus if (nxgep->niu_type == N2_NIU) { 2894977Sraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 2904977Sraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 2914977Sraghus if (strcmp("xgf", prop_val) == 0) { 2924977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2934977Sraghus XPCS_XCVR; 2944977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 2954977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2964977Sraghus "10G Fiber Xcvr")); 2974977Sraghus } else if (strcmp("mif", prop_val) == 0) { 2984977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2994977Sraghus INT_MII_XCVR; 3004977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 3014977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3024977Sraghus "1G Copper Xcvr")); 3034977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 3044977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3054977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 3064977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3074977Sraghus "1G Fiber Xcvr")); 3084977Sraghus } else if (strcmp("xgc", prop_val) == 0) { 3094977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 3104977Sraghus XPCS_XCVR; 3114977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 3124977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3134977Sraghus "10G Copper Xcvr")); 3144977Sraghus } else if (strcmp("xgsd", prop_val) == 0) { 3154977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3164977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 3174977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3184977Sraghus "OBP: 10G Serdes")); 3194977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 3204977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3214977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 3224977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3234977Sraghus "OBP: 1G Serdes")); 3244977Sraghus } else { 3254977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3264977Sraghus "Unknown phy-type: %s", prop_val)); 3274977Sraghus ddi_prop_free(prop_val); 3284977Sraghus return (NXGE_ERROR); 3294977Sraghus } 3304977Sraghus status = NXGE_OK; 3314977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3324977Sraghus nxgep->dip, "phy-type", prop_val); 3334977Sraghus ddi_prop_free(prop_val); 3344977Sraghus 3354977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3364977Sraghus "Got phy type [0x%x] from OBP", 3374977Sraghus nxgep->mac.portmode)); 3384977Sraghus 3394977Sraghus return (status); 3404977Sraghus } else { 3414977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3424977Sraghus "Exiting...phy-type property not found")); 3434977Sraghus return (NXGE_ERROR); 3444977Sraghus } 3454977Sraghus } 3464977Sraghus 3474977Sraghus 3484977Sraghus if (!nxgep->vpd_info.present) { 3494977Sraghus return (NXGE_OK); 3504977Sraghus } 3514977Sraghus 3524977Sraghus if (!nxgep->vpd_info.ver_valid) { 3534977Sraghus goto read_seeprom; 3544977Sraghus } 3554977Sraghus 3564977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3574977Sraghus "Reading phy type from expansion ROM")); 3584977Sraghus /* 3594977Sraghus * Try to read the phy type from the vpd data read off the 3604977Sraghus * expansion ROM. 3614977Sraghus */ 3624977Sraghus phy_type = nxgep->vpd_info.phy_type; 3634977Sraghus 3645196Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 3654977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 3664977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3675196Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 3684977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 3694977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3705196Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 3714977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 3724977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3735196Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 3744977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 3754977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3765196Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 3775196Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 3785196Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3795196Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 3805196Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 3815196Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3824977Sraghus } else { 3835196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3844977Sraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3854977Sraghus phy_type[0], phy_type[1], phy_type[2])); 3864977Sraghus goto read_seeprom; 3874977Sraghus } 3884977Sraghus 3894977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3904977Sraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 3914977Sraghus 3924977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3934977Sraghus return (status); 3944977Sraghus 3954977Sraghus read_seeprom: 3964977Sraghus /* 3974977Sraghus * read the phy type from the SEEPROM - NCR registers 3984977Sraghus */ 3994977Sraghus status = nxge_espc_phy_type_get(nxgep); 4004977Sraghus if (status != NXGE_OK) { 4014977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4024977Sraghus "Failed to get phy type")); 4034977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 4044977Sraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 4054977Sraghus } 4064977Sraghus 4074977Sraghus return (status); 4084977Sraghus 4094977Sraghus } 4104977Sraghus 4114732Sdavemq /* Set up the PHY specific values. */ 4124732Sdavemq 4134732Sdavemq nxge_status_t 4144732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 4154732Sdavemq { 4164732Sdavemq nxge_status_t status = NXGE_OK; 4174732Sdavemq uint32_t port_type; 4184732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4194977Sraghus uint32_t pcs_id = 0; 4204977Sraghus uint32_t pma_pmd_id = 0; 4214977Sraghus uint32_t phy_id = 0; 4225572Ssbehera uint16_t chip_id = 0; 4234732Sdavemq 4244732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 4254732Sdavemq portn)); 4264732Sdavemq 4274977Sraghus switch (nxgep->niu_type) { 4284977Sraghus case N2_NIU: 4294977Sraghus switch (nxgep->mac.portmode) { 4304977Sraghus case PORT_1G_FIBER: 4314977Sraghus case PORT_1G_SERDES: 4324977Sraghus nxgep->xcvr = nxge_n2_1G_table; 4335572Ssbehera nxgep->xcvr_addr = portn; 4344977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 4354977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 4364977Sraghus "Serdes")); 4374977Sraghus break; 4384977Sraghus case PORT_10G_FIBER: 4394977Sraghus case PORT_10G_SERDES: 4404977Sraghus nxgep->xcvr = nxge_n2_10G_table; 4415572Ssbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 4425572Ssbehera nxgep->xcvr_addr = 4435572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 4445572Ssbehera } 4454977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 4464977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 4474977Sraghus "Serdes")); 4484977Sraghus break; 4495572Ssbehera case PORT_HSP_MODE: 4505572Ssbehera nxgep->xcvr = nxge_n2_10G_table; 4515572Ssbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 4525572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 4535572Ssbehera "Swappable Xcvr (not present)")); 4545572Ssbehera break; 4554977Sraghus default: 4564977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4574977Sraghus "<== nxge_setup_xcvr_table: " 4584977Sraghus "Unable to determine NIU portmode")); 4594977Sraghus return (NXGE_ERROR); 4604977Sraghus } 4614977Sraghus break; 4624977Sraghus default: 4634977Sraghus if (nxgep->mac.portmode == 0) { 4644977Sraghus /* 4654977Sraghus * Would be the case for platforms like Maramba 4664977Sraghus * in which the phy type could not be got from conf 4674977Sraghus * file, OBP, VPD or Serial PROM. 4684977Sraghus */ 4694977Sraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 4704977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4714977Sraghus "<== nxge_setup_xcvr_table:" 4724977Sraghus " Invalid Neptune type [0x%x]", 4734977Sraghus nxgep->niu_type)); 4744977Sraghus return (NXGE_ERROR); 4754977Sraghus } 4764977Sraghus 4774977Sraghus port_type = nxgep->niu_type >> 4784977Sraghus (NXGE_PORT_TYPE_SHIFT * portn); 4794977Sraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 4804977Sraghus 4814977Sraghus switch (port_type) { 4824977Sraghus 4834977Sraghus case NXGE_PORT_1G_COPPER: 4844977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 4854977Sraghus break; 4864977Sraghus case NXGE_PORT_10G_COPPER: 4874977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 4884977Sraghus break; 4894977Sraghus case NXGE_PORT_1G_FIBRE: 4904977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 4914977Sraghus break; 4924977Sraghus case NXGE_PORT_10G_FIBRE: 4934977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 4944977Sraghus break; 4954977Sraghus case NXGE_PORT_1G_SERDES: 4964977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 4974977Sraghus break; 4984977Sraghus case NXGE_PORT_10G_SERDES: 4994977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 5004977Sraghus break; 5014977Sraghus case NXGE_PORT_1G_RGMII_FIBER: 5024977Sraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 5034977Sraghus break; 5044977Sraghus default: 5054977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5064977Sraghus "<== nxge_setup_xcvr_table: " 5074977Sraghus "Unknown port-type: 0x%x", port_type)); 5084977Sraghus return (NXGE_ERROR); 5094977Sraghus } 5104977Sraghus } 5114977Sraghus 5124977Sraghus switch (nxgep->mac.portmode) { 5134977Sraghus case PORT_1G_COPPER: 5144977Sraghus case PORT_1G_RGMII_FIBER: 5154732Sdavemq nxgep->xcvr = nxge_1G_copper_table; 5165572Ssbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 5174732Sdavemq /* 5184732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 5194732Sdavemq * swapped with ethernet port number. This is 5204977Sraghus * designed for better signal integrity in 5214977Sraghus * routing. This is also the case for the 5224977Sraghus * on-board Neptune copper ports on the Maramba 5234977Sraghus * platform. 5244732Sdavemq */ 5254977Sraghus switch (nxgep->platform_type) { 5264977Sraghus case P_NEPTUNE_ATLAS_4PORT: 5274977Sraghus case P_NEPTUNE_MARAMBA_P0: 5284977Sraghus case P_NEPTUNE_MARAMBA_P1: 5294977Sraghus switch (portn) { 5304977Sraghus case 0: 5315572Ssbehera nxgep->xcvr_addr += 3; 5324977Sraghus break; 5334977Sraghus case 1: 5345572Ssbehera nxgep->xcvr_addr += 1; 5354977Sraghus break; 5364977Sraghus case 2: 5375572Ssbehera nxgep->xcvr_addr -= 1; 5384977Sraghus break; 5394977Sraghus case 3: 5405572Ssbehera nxgep->xcvr_addr -= 3; 5414977Sraghus break; 5424977Sraghus default: 5434977Sraghus return (NXGE_ERROR); 5444977Sraghus } 5454732Sdavemq break; 5464732Sdavemq default: 5474977Sraghus break; 5484732Sdavemq } 5495196Ssbehera 5504977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5514977Sraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 5524977Sraghus "Copper" : "RGMII Fiber")); 5534732Sdavemq break; 5544977Sraghus case PORT_10G_COPPER: 5554732Sdavemq nxgep->xcvr = nxge_10G_copper_table; 5564732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 5574732Sdavemq break; 5584977Sraghus case PORT_1G_FIBER: 5594977Sraghus case PORT_1G_SERDES: 5604732Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 5615572Ssbehera nxgep->xcvr_addr = portn; 5624977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5634977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 5644977Sraghus "Fiber" : "Serdes")); 5654732Sdavemq break; 5664977Sraghus case PORT_10G_FIBER: 5674977Sraghus case PORT_10G_SERDES: 5684732Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 5695572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 5705572Ssbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 5715572Ssbehera "nxgep->xcvr_addr = [%d]", 5725572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn], 5735572Ssbehera nxgep->xcvr_addr)); 5745572Ssbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5755572Ssbehera nxgep->xcvr_addr = 5765572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 5775572Ssbehera } 5784977Sraghus switch (nxgep->platform_type) { 5794977Sraghus case P_NEPTUNE_MARAMBA_P0: 5804977Sraghus case P_NEPTUNE_MARAMBA_P1: 5814732Sdavemq /* 5824732Sdavemq * Switch off LED for corresponding copper 5834732Sdavemq * port 5844732Sdavemq */ 5854732Sdavemq nxge_bcm5464_link_led_off(nxgep); 5864977Sraghus break; 5874977Sraghus default: 5884977Sraghus break; 5894732Sdavemq } 5904977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 5914977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 5924977Sraghus "Fiber" : "Serdes")); 5934732Sdavemq break; 5945572Ssbehera 5955572Ssbehera case PORT_HSP_MODE: 5965572Ssbehera nxgep->xcvr = nxge_10G_fiber_table; 5975572Ssbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 5985572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 5995572Ssbehera "Swappable Xcvr (not present)")); 6005572Ssbehera break; 6014732Sdavemq default: 6024732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6034732Sdavemq "Unknown port-type: 0x%x", port_type)); 6044732Sdavemq return (NXGE_ERROR); 6054732Sdavemq } 6064732Sdavemq } 6074732Sdavemq 6085572Ssbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 6096604Ssbehera uint32_t pma_pmd_id; 6106604Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 6116604Ssbehera nxgep->xcvr_addr); 6126604Ssbehera if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 6136604Ssbehera chip_id = MRVL88X201X_CHIP_ID; 6146604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6156604Ssbehera "nxge_setup_xcvr_table: " 6166604Ssbehera "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 6176604Ssbehera } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6185572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 6195572Ssbehera &chip_id)) == NXGE_OK) { 6205572Ssbehera 6215572Ssbehera switch (chip_id) { 6225572Ssbehera case BCM8704_CHIP_ID: 6235572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6245572Ssbehera "nxge_setup_xcvr_table: " 6255572Ssbehera "Chip ID 8704 [0x%x] for 10G xcvr", 6265572Ssbehera chip_id)); 6275572Ssbehera break; 6285572Ssbehera case BCM8706_CHIP_ID: 6295572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6305572Ssbehera "nxge_setup_xcvr_table: " 6315572Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", 6325572Ssbehera chip_id)); 6335572Ssbehera break; 6345572Ssbehera default: 6355572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6365572Ssbehera "nxge_setup_xcvr_table: " 6375572Ssbehera "Unknown Chip ID [0x%x] for 10G xcvr", 6385572Ssbehera chip_id)); 6395572Ssbehera break; 6405572Ssbehera } 6415572Ssbehera } 6425572Ssbehera } 6435572Ssbehera 6444732Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 6455572Ssbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 6465572Ssbehera nxgep->chip_id = chip_id; 6474977Sraghus 6484977Sraghus /* 6494977Sraghus * Get the actual device ID value returned by MDIO read. 6504977Sraghus */ 6514977Sraghus nxgep->statsp->mac_stats.xcvr_id = 0; 6524977Sraghus 6535572Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 6544977Sraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 6554977Sraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 6564977Sraghus } else { 6575572Ssbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 6584977Sraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 6594977Sraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 6604977Sraghus } else { 6614977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, 6625572Ssbehera nxgep->xcvr_addr); 6634977Sraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6644977Sraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 6654977Sraghus } 6664977Sraghus } 6674977Sraghus } 6684977Sraghus 6694732Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 6704732Sdavemq 6714977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 6725572Ssbehera "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type, 6735572Ssbehera nxgep->platform_type, nxgep->xcvr_addr)); 6744977Sraghus 6754732Sdavemq return (status); 6764732Sdavemq } 6774732Sdavemq 6783859Sml29623 /* Initialize the entire MAC and physical layer */ 6793859Sml29623 6803859Sml29623 nxge_status_t 6813859Sml29623 nxge_mac_init(p_nxge_t nxgep) 6823859Sml29623 { 6833859Sml29623 uint8_t portn; 6843859Sml29623 nxge_status_t status = NXGE_OK; 6853859Sml29623 6863859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6873859Sml29623 6883859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 6893859Sml29623 6903859Sml29623 nxgep->mac.portnum = portn; 6913859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 6923859Sml29623 6933859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 6943859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 6953859Sml29623 6963859Sml29623 /* Initialize XIF to configure a network mode */ 6973859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 6983859Sml29623 goto fail; 6993859Sml29623 } 7003859Sml29623 7013859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 7023859Sml29623 goto fail; 7033859Sml29623 } 7043859Sml29623 7053859Sml29623 /* Initialize TX and RX MACs */ 7063859Sml29623 /* 7073859Sml29623 * Always perform XIF init first, before TX and RX MAC init 7083859Sml29623 */ 7093859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 7103859Sml29623 goto fail; 7113859Sml29623 7123859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 7133859Sml29623 goto fail; 7143859Sml29623 7153859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 7163859Sml29623 goto fail; 7173859Sml29623 7183859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 7193859Sml29623 goto fail; 7203859Sml29623 7213859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 7223859Sml29623 goto fail; 7233859Sml29623 7243859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 7253859Sml29623 goto fail; 7263859Sml29623 7275553Smisaki /* Initialize MAC control configuration */ 7285553Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 7295553Smisaki goto fail; 7305553Smisaki } 7315553Smisaki 7323859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 7333859Sml29623 7345196Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 7355196Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 7365196Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 7375196Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 7385196Ssbehera ((portn == 0) || (portn == 1))) { 7395196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7405196Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 7415196Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 7425196Ssbehera goto fail; 7435196Ssbehera } 7445196Ssbehera } 7455196Ssbehera 7464977Sraghus 7473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 7483859Sml29623 7493859Sml29623 return (NXGE_OK); 7503859Sml29623 fail: 7513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7523859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 7533859Sml29623 portn)); 7543859Sml29623 return (status); 7553859Sml29623 } 7563859Sml29623 7573859Sml29623 /* Initialize the Ethernet Link */ 7583859Sml29623 7593859Sml29623 nxge_status_t 7603859Sml29623 nxge_link_init(p_nxge_t nxgep) 7613859Sml29623 { 7623859Sml29623 nxge_status_t status = NXGE_OK; 7634977Sraghus nxge_port_mode_t portmode; 7643859Sml29623 #ifdef NXGE_DEBUG 7653859Sml29623 uint8_t portn; 7663859Sml29623 7673859Sml29623 portn = nxgep->mac.portnum; 7683859Sml29623 7693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 7703859Sml29623 #endif 7715572Ssbehera if (nxgep->hot_swappable_phy && nxgep->phy_absent) { 7725572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: " 7735572Ssbehera "Phy not present, cannot initialize link")); 7745572Ssbehera return (status); 7755572Ssbehera } 7763859Sml29623 7774977Sraghus portmode = nxgep->mac.portmode; 7785572Ssbehera 7794977Sraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 7804977Sraghus (portmode != PORT_1G_SERDES)) { 7813859Sml29623 /* Workaround to get link up in both NIU ports */ 7824977Sraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 7833859Sml29623 goto fail; 7844977Sraghus } 7853859Sml29623 } 7863859Sml29623 NXGE_DELAY(200000); 7873859Sml29623 /* Initialize internal serdes */ 7883859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 7893859Sml29623 goto fail; 7903859Sml29623 NXGE_DELAY(200000); 7913859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 7923859Sml29623 goto fail; 7933859Sml29623 7943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 7953859Sml29623 7963859Sml29623 return (NXGE_OK); 7973859Sml29623 7983859Sml29623 fail: 7993859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8003859Sml29623 "nxge_link_init: ", 8013859Sml29623 "failed to initialize Ethernet link on port<%d>", 8023859Sml29623 portn)); 8033859Sml29623 8043859Sml29623 return (status); 8053859Sml29623 } 8063859Sml29623 8073859Sml29623 8083859Sml29623 /* Initialize the XIF sub-block within the MAC */ 8093859Sml29623 8103859Sml29623 nxge_status_t 8113859Sml29623 nxge_xif_init(p_nxge_t nxgep) 8123859Sml29623 { 8133859Sml29623 uint32_t xif_cfg = 0; 8143859Sml29623 npi_attr_t ap; 8153859Sml29623 uint8_t portn; 8163859Sml29623 nxge_port_t portt; 8173859Sml29623 nxge_port_mode_t portmode; 8183859Sml29623 p_nxge_stats_t statsp; 8193859Sml29623 npi_status_t rs = NPI_SUCCESS; 8203859Sml29623 npi_handle_t handle; 8213859Sml29623 8223859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8233859Sml29623 8243859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 8253859Sml29623 8263859Sml29623 handle = nxgep->npi_handle; 8273859Sml29623 portmode = nxgep->mac.portmode; 8283859Sml29623 portt = nxgep->mac.porttype; 8293859Sml29623 statsp = nxgep->statsp; 8303859Sml29623 8315196Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 8325196Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 8335196Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 8345196Ssbehera ((portn == 0) || (portn == 1))) { 8355196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8365196Ssbehera "nxge_xcvr_init: set ATCA mode")); 8375196Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 8385196Ssbehera } 8395196Ssbehera 8403859Sml29623 if (portt == PORT_TYPE_XMAC) { 8413859Sml29623 8423859Sml29623 /* Setup XIF Configuration for XMAC */ 8433859Sml29623 8443859Sml29623 if ((portmode == PORT_10G_FIBER) || 8454977Sraghus (portmode == PORT_10G_COPPER) || 8464977Sraghus (portmode == PORT_10G_SERDES)) 8473859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 8483859Sml29623 8493859Sml29623 if (portmode == PORT_1G_COPPER) { 8503859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 8513859Sml29623 } 8523859Sml29623 8533859Sml29623 /* Set MAC Internal Loopback if necessary */ 8543859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 8553859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 8563859Sml29623 8573859Sml29623 if (statsp->mac_stats.link_speed == 100) 8583859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 8593859Sml29623 8603859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 8613859Sml29623 8624977Sraghus if ((portmode == PORT_10G_FIBER) || 8634977Sraghus (portmode == PORT_10G_SERDES)) { 8643859Sml29623 if (statsp->mac_stats.link_up) { 8653859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 8663859Sml29623 } else { 8673859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 8683859Sml29623 } 8693859Sml29623 } 8703859Sml29623 8713859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 8723859Sml29623 if (rs != NPI_SUCCESS) 8733859Sml29623 goto fail; 8743859Sml29623 8753859Sml29623 nxgep->mac.xif_config = xif_cfg; 8763859Sml29623 8773859Sml29623 /* Set Port Mode */ 8783859Sml29623 if ((portmode == PORT_10G_FIBER) || 8794977Sraghus (portmode == PORT_10G_COPPER) || 8804977Sraghus (portmode == PORT_10G_SERDES)) { 8813859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 8823859Sml29623 MAC_XGMII_MODE, rs); 8833859Sml29623 if (rs != NPI_SUCCESS) 8843859Sml29623 goto fail; 8853859Sml29623 if (statsp->mac_stats.link_up) { 8863859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 8873859Sml29623 goto fail; 8883859Sml29623 } else { 8893859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 8903859Sml29623 goto fail; 8913859Sml29623 } 8923859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 8934977Sraghus (portmode == PORT_1G_COPPER) || 8945196Ssbehera (portmode == PORT_1G_SERDES) || 8955196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 8965196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8975196Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 8985196Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 8993859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 9003859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 9013859Sml29623 MAC_GMII_MODE, rs); 9023859Sml29623 } else { 9033859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 9043859Sml29623 MAC_MII_MODE, rs); 9053859Sml29623 } 9063859Sml29623 if (rs != NPI_SUCCESS) 9073859Sml29623 goto fail; 9083859Sml29623 } else { 9093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9103859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 9113859Sml29623 " for port<%d>", portmode, portn)); 9123859Sml29623 goto fail; 9133859Sml29623 } 9143859Sml29623 9155196Ssbehera /* Enable ATCA mode */ 9165196Ssbehera 9173859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 9183859Sml29623 9193859Sml29623 /* Setup XIF Configuration for BMAC */ 9203859Sml29623 9215196Ssbehera if ((portmode == PORT_1G_COPPER) || 9225196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 9233859Sml29623 if (statsp->mac_stats.link_speed == 100) 9243859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 9253859Sml29623 } 9263859Sml29623 9273859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 9283859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 9293859Sml29623 9303859Sml29623 if (statsp->mac_stats.link_speed == 1000) 9313859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 9323859Sml29623 9333859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 9343859Sml29623 9353859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 9363859Sml29623 if (rs != NPI_SUCCESS) 9373859Sml29623 goto fail; 9383859Sml29623 nxgep->mac.xif_config = xif_cfg; 9393859Sml29623 } 9403859Sml29623 9413859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 9423859Sml29623 return (NXGE_OK); 9433859Sml29623 fail: 9443859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9453859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 9463859Sml29623 portn)); 9473859Sml29623 return (NXGE_ERROR | rs); 9483859Sml29623 } 9493859Sml29623 9503859Sml29623 /* Initialize the PCS sub-block in the MAC */ 9513859Sml29623 9523859Sml29623 nxge_status_t 9533859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 9543859Sml29623 { 9553859Sml29623 pcs_cfg_t pcs_cfg; 9563859Sml29623 uint32_t val; 9573859Sml29623 uint8_t portn; 9583859Sml29623 nxge_port_mode_t portmode; 9593859Sml29623 npi_handle_t handle; 9603859Sml29623 p_nxge_stats_t statsp; 9613859Sml29623 npi_status_t rs = NPI_SUCCESS; 9623859Sml29623 9633859Sml29623 handle = nxgep->npi_handle; 9643859Sml29623 portmode = nxgep->mac.portmode; 9653859Sml29623 portn = nxgep->mac.portnum; 9663859Sml29623 statsp = nxgep->statsp; 9673859Sml29623 9683859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 9693859Sml29623 9704977Sraghus if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 9714977Sraghus if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 9724977Sraghus goto fail; 9734977Sraghus } 9744977Sraghus 9753859Sml29623 /* Initialize port's PCS */ 9763859Sml29623 pcs_cfg.value = 0; 9773859Sml29623 pcs_cfg.bits.w0.enable = 1; 9783859Sml29623 pcs_cfg.bits.w0.mask = 1; 9793859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 9803859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 9814977Sraghus 9824977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9834977Sraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 9844977Sraghus portn, pcs_cfg.value)); 9853859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 9864977Sraghus (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 9873859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 9883859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 9893859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 9903859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 9913859Sml29623 9923859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 9933859Sml29623 goto fail; 9943859Sml29623 9953859Sml29623 /* Set XPCS Internal Loopback if necessary */ 9963859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 9973859Sml29623 XPCS_REG_CONTROL1, &val)) 9983859Sml29623 != NPI_SUCCESS) 9993859Sml29623 goto fail; 10003859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 10013859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 10023859Sml29623 val |= XPCS_CTRL1_LOOPBK; 10033859Sml29623 else 10043859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 10053859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 10063859Sml29623 XPCS_REG_CONTROL1, val)) 10073859Sml29623 != NPI_SUCCESS) 10083859Sml29623 goto fail; 10093859Sml29623 10103859Sml29623 /* Clear descw errors */ 10113859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 10123859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 10133859Sml29623 != NPI_SUCCESS) 10143859Sml29623 goto fail; 10153859Sml29623 /* Clear symbol errors */ 10163859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 10173859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 10183859Sml29623 != NPI_SUCCESS) 10193859Sml29623 goto fail; 10203859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 10213859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 10223859Sml29623 != NPI_SUCCESS) 10233859Sml29623 goto fail; 10243859Sml29623 10255196Ssbehera } else if ((portmode == PORT_1G_COPPER) || 10265196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 10275196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10285196Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 10293859Sml29623 if (portn < 4) { 10303859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 10313859Sml29623 PCS_DATAPATH_MODE_MII); 10323859Sml29623 } 10333859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 10343859Sml29623 goto fail; 10353859Sml29623 10363859Sml29623 } else { 10373859Sml29623 goto fail; 10383859Sml29623 } 10393859Sml29623 pass: 10403859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 10413859Sml29623 return (NXGE_OK); 10423859Sml29623 fail: 10433859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10443859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 10453859Sml29623 portn)); 10463859Sml29623 return (NXGE_ERROR | rs); 10473859Sml29623 } 10483859Sml29623 10495553Smisaki /* 10505553Smisaki * Initialize the MAC CTRL sub-block within the MAC 10515553Smisaki * Only the receive-pause-cap is supported. 10525553Smisaki */ 10535553Smisaki nxge_status_t 10545553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 10555553Smisaki { 10565553Smisaki uint8_t portn; 10575553Smisaki nxge_port_t portt; 10585553Smisaki p_nxge_stats_t statsp; 10595553Smisaki npi_handle_t handle; 10605553Smisaki uint32_t val; 10615553Smisaki 10625553Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 10635553Smisaki 10645553Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 10655553Smisaki portn)); 10665553Smisaki 10675553Smisaki handle = nxgep->npi_handle; 10685553Smisaki portt = nxgep->mac.porttype; 10695553Smisaki statsp = nxgep->statsp; 10705553Smisaki 10715553Smisaki if (portt == PORT_TYPE_XMAC) { 10725553Smisaki /* Readin the current XMAC Config Register for XMAC */ 10735553Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 10745553Smisaki 10755553Smisaki /* 10765553Smisaki * Setup XMAC Configuration for XMAC 10775553Smisaki * XMAC only supports receive-pause 10785553Smisaki */ 10795553Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 10805553Smisaki if (!statsp->mac_stats.adv_cap_pause) { 10815553Smisaki /* 10825553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 10835553Smisaki * is 0, enable receive pause. 10845553Smisaki */ 10855553Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 10865553Smisaki } else { 10875553Smisaki /* 10885553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 10895553Smisaki * is 1, disable receive pause. Send pause is 10905553Smisaki * not supported. 10915553Smisaki */ 10925553Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 10935553Smisaki } 10945553Smisaki } else { 10956439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10966439Sml29623 "==> nxge_mac_ctrl_init: port<%d>: pause", 10976439Sml29623 portn)); 10985553Smisaki if (statsp->mac_stats.adv_cap_pause) { 10996439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11006439Sml29623 "==> nxge_mac_ctrl_init: port<%d>: " 11016439Sml29623 "enable pause", portn)); 11025553Smisaki /* 11035553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11045553Smisaki * is 1, enable receive pause. 11055553Smisaki */ 11065553Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 11075553Smisaki } else { 11085553Smisaki /* 11095553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11105553Smisaki * is 0, disable receive pause. Send pause is 11115553Smisaki * not supported 11125553Smisaki */ 11136439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11146439Sml29623 "==> nxge_mac_ctrl_init: port<%d>: " 11156439Sml29623 "disable pause", portn)); 11165553Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 11175553Smisaki } 11185553Smisaki } 11195553Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 11205553Smisaki } else if (portt == PORT_TYPE_BMAC) { 11215553Smisaki /* Readin the current MAC CTRL Config Register for BMAC */ 11225553Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 11235553Smisaki 11245553Smisaki /* Setup MAC CTRL Configuration for BMAC */ 11255553Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 11265553Smisaki if (statsp->mac_stats.adv_cap_pause) { 11275553Smisaki /* 11285553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 11295553Smisaki * is 1, disable receive pause. Send pause 11305553Smisaki * is not supported 11315553Smisaki */ 11325553Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 11335553Smisaki } else { 11345553Smisaki /* 11355553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 11365553Smisaki * is 0, enable receive pause and disable 11375553Smisaki * send pause. 11385553Smisaki */ 11395553Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 11405553Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 11415553Smisaki } 11425553Smisaki } else { 11435553Smisaki if (statsp->mac_stats.adv_cap_pause) { 11445553Smisaki /* 11455553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11465553Smisaki * is 1, enable receive pause. Send pause is 11475553Smisaki * not supported. 11485553Smisaki */ 11495553Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 11505553Smisaki } else { 11515553Smisaki /* 11525553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11535553Smisaki * is 0, pause capability is not available in 11545553Smisaki * either direction. 11555553Smisaki */ 11565553Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 11575553Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 11585553Smisaki } 11595553Smisaki } 11605553Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 11615553Smisaki } 11625553Smisaki 11635553Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 11645553Smisaki portn)); 11655553Smisaki 11665553Smisaki return (NXGE_OK); 11675553Smisaki } 11685553Smisaki 11693859Sml29623 /* Initialize the Internal Serdes */ 11703859Sml29623 11713859Sml29623 nxge_status_t 11723859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 11733859Sml29623 { 11743859Sml29623 p_nxge_stats_t statsp; 11753859Sml29623 #ifdef NXGE_DEBUG 11763859Sml29623 uint8_t portn; 11773859Sml29623 #endif 11783859Sml29623 nxge_status_t status = NXGE_OK; 11793859Sml29623 11803859Sml29623 #ifdef NXGE_DEBUG 11813859Sml29623 portn = nxgep->mac.portnum; 11823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11834732Sdavemq "==> nxge_serdes_init port<%d>", portn)); 11843859Sml29623 #endif 11853859Sml29623 11864732Sdavemq if (nxgep->xcvr.serdes_init) { 11874732Sdavemq statsp = nxgep->statsp; 11884732Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 11894732Sdavemq if (status != NXGE_OK) 11903859Sml29623 goto fail; 11914732Sdavemq statsp->mac_stats.serdes_inits++; 11923859Sml29623 } 11933859Sml29623 11943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 11954732Sdavemq portn)); 11963859Sml29623 11973859Sml29623 return (NXGE_OK); 11983859Sml29623 11993859Sml29623 fail: 12003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12014732Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 12024732Sdavemq portn)); 12033859Sml29623 12043859Sml29623 return (status); 12053859Sml29623 } 12063859Sml29623 12073859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 12083859Sml29623 12094732Sdavemq static nxge_status_t 12103859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 12113859Sml29623 { 12123859Sml29623 uint8_t portn; 12133859Sml29623 int chan; 12143859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 12154977Sraghus esr_ti_cfgpll_l_t pll_sts_l; 12163859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 12173859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 12183859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 12193859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 12204977Sraghus #ifdef NXGE_DEBUG 12214977Sraghus esr_ti_testcfg_t cfg; 12224977Sraghus #endif 12233859Sml29623 esr_ti_testcfg_t test_cfg; 12243859Sml29623 nxge_status_t status = NXGE_OK; 12253859Sml29623 12263859Sml29623 portn = nxgep->mac.portnum; 12273859Sml29623 12283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 12293859Sml29623 portn)); 12303859Sml29623 12313859Sml29623 tx_cfg_l.value = 0; 12323859Sml29623 tx_cfg_h.value = 0; 12333859Sml29623 rx_cfg_l.value = 0; 12343859Sml29623 rx_cfg_h.value = 0; 12353859Sml29623 pll_cfg_l.value = 0; 12364977Sraghus pll_sts_l.value = 0; 12373859Sml29623 test_cfg.value = 0; 12383859Sml29623 12394977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 12404977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 12413859Sml29623 /* 0x0E01 */ 12423859Sml29623 tx_cfg_l.bits.entx = 1; 12433859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 12443859Sml29623 12453859Sml29623 /* 0x9101 */ 12463859Sml29623 rx_cfg_l.bits.enrx = 1; 12473859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 12483859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 12493859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 12503859Sml29623 12513859Sml29623 /* 0x0008 */ 12523859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12533859Sml29623 12543859Sml29623 /* Set loopback mode if necessary */ 12553859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 12563859Sml29623 tx_cfg_l.bits.entest = 1; 12573859Sml29623 rx_cfg_l.bits.entest = 1; 12583859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 12593859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 12603859Sml29623 ESR_N2_DEV_ADDR, 12613859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 12623859Sml29623 != NXGE_OK) 12633859Sml29623 goto fail; 12643859Sml29623 } 12653859Sml29623 12663859Sml29623 /* Use default PLL value */ 12673859Sml29623 12684977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 12694977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 12703859Sml29623 12713859Sml29623 /* 0x0E21 */ 12723859Sml29623 tx_cfg_l.bits.entx = 1; 12733859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 12743859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 12753859Sml29623 12763859Sml29623 /* 0x9121 */ 12773859Sml29623 rx_cfg_l.bits.enrx = 1; 12783859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 12793859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 12803859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 12813859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 12823859Sml29623 12834977Sraghus if (portn == 0) { 12844977Sraghus /* 0x8 */ 12854977Sraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12864977Sraghus } 12873859Sml29623 12883859Sml29623 /* MPY = 0x100 */ 12893859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 12903859Sml29623 12913859Sml29623 /* Set PLL */ 12923859Sml29623 pll_cfg_l.bits.enpll = 1; 12934977Sraghus pll_sts_l.bits.enpll = 1; 12943859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 12953859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 12963859Sml29623 != NXGE_OK) 12973859Sml29623 goto fail; 12984977Sraghus 12994977Sraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13004977Sraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 13014977Sraghus goto fail; 13024977Sraghus 13034977Sraghus #ifdef NXGE_DEBUG 13044977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 13054977Sraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 13064977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13074977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 13084977Sraghus portn, pll_cfg_l.value, cfg.value)); 13094977Sraghus 13104977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 13114977Sraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 13124977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13134977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 13144977Sraghus portn, pll_sts_l.value, cfg.value)); 13154977Sraghus #endif 13164977Sraghus 13174977Sraghus /* Set loopback mode if necessary */ 13184977Sraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 13194977Sraghus tx_cfg_l.bits.entest = 1; 13204977Sraghus rx_cfg_l.bits.entest = 1; 13214977Sraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 13224977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13234977Sraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 13244977Sraghus portn, test_cfg.value)); 13254977Sraghus if ((status = nxge_mdio_write(nxgep, portn, 13264977Sraghus ESR_N2_DEV_ADDR, 13274977Sraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 13284977Sraghus goto fail; 13294977Sraghus } 13304977Sraghus } 13313859Sml29623 } else { 13323859Sml29623 goto fail; 13333859Sml29623 } 13343859Sml29623 13353859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 13363859Sml29623 13373859Sml29623 NXGE_DELAY(20); 13383859Sml29623 13393859Sml29623 /* init TX channels */ 13403859Sml29623 for (chan = 0; chan < 4; chan++) { 13413859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13423859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 13433859Sml29623 != NXGE_OK) 13443859Sml29623 goto fail; 13453859Sml29623 13463859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13473859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 13483859Sml29623 != NXGE_OK) 13493859Sml29623 goto fail; 13504977Sraghus 13514977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13524977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 13534977Sraghus portn, chan, tx_cfg_l.value)); 13544977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13554977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 13564977Sraghus portn, chan, tx_cfg_h.value)); 13573859Sml29623 } 13583859Sml29623 13593859Sml29623 /* init RX channels */ 13603859Sml29623 for (chan = 0; chan < 4; chan++) { 13613859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13623859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 13633859Sml29623 != NXGE_OK) 13643859Sml29623 goto fail; 13653859Sml29623 13663859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13673859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 13683859Sml29623 != NXGE_OK) 13693859Sml29623 goto fail; 13704977Sraghus 13714977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13724977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 13734977Sraghus portn, chan, rx_cfg_l.value)); 13744977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13754977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 13764977Sraghus portn, chan, rx_cfg_h.value)); 13773859Sml29623 } 13783859Sml29623 13793859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 13803859Sml29623 portn)); 13813859Sml29623 13823859Sml29623 return (NXGE_OK); 13833859Sml29623 fail: 13845572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13855572Ssbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 13865572Ssbehera portn)); 13873859Sml29623 13883859Sml29623 return (status); 13893859Sml29623 } 13903859Sml29623 13914732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 13924732Sdavemq 13934732Sdavemq static nxge_status_t 13944732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 13953859Sml29623 { 13963859Sml29623 npi_handle_t handle; 13973859Sml29623 uint8_t portn; 13986075Ssbehera int chan, i; 13993859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 14003859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 14013859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 14023859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 14033859Sml29623 uint64_t val; 14043859Sml29623 uint16_t val16l; 14053859Sml29623 uint16_t val16h; 14063859Sml29623 nxge_status_t status = NXGE_OK; 14073859Sml29623 14083859Sml29623 portn = nxgep->mac.portnum; 14093859Sml29623 14103859Sml29623 if ((portn != 0) && (portn != 1)) 14113859Sml29623 return (NXGE_OK); 14123859Sml29623 14134732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 14144732Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 14153859Sml29623 14163859Sml29623 handle = nxgep->npi_handle; 14174732Sdavemq switch (portn) { 14184732Sdavemq case 0: 14196028Ssbehera /* Reset Serdes */ 14206028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 14216028Ssbehera NXGE_DELAY(20); 14226028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14236028Ssbehera NXGE_DELAY(2000); 14246028Ssbehera 14256028Ssbehera /* Configure Serdes to 10G mode */ 14266028Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 14276028Ssbehera ESR_PLL_CFG_10G_SERDES); 14286028Ssbehera 14294732Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 14304732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 14314732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 14324732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 14334732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 14344732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 14354732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14364732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14374732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 14384732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 14394732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 14404732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 14414732Sdavemq 14424732Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 14434732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 14444732Sdavemq ESR_REG_WR(handle, 14454732Sdavemq ESR_0_TEST_CONFIG_REG, 14464732Sdavemq ESR_PAD_LOOPBACK_CH3 | 14474732Sdavemq ESR_PAD_LOOPBACK_CH2 | 14484732Sdavemq ESR_PAD_LOOPBACK_CH1 | 14494732Sdavemq ESR_PAD_LOOPBACK_CH0); 14504732Sdavemq } else { 14514732Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 14523859Sml29623 } 14534732Sdavemq break; 14544732Sdavemq case 1: 14556028Ssbehera /* Reset Serdes */ 14566028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 14576028Ssbehera NXGE_DELAY(20); 14586028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14596028Ssbehera NXGE_DELAY(2000); 14606028Ssbehera 14616028Ssbehera /* Configure Serdes to 10G mode */ 14626028Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 14636028Ssbehera ESR_PLL_CFG_10G_SERDES); 14646028Ssbehera 14654732Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 14664732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 14674732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 14684732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 14694732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 14704732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 14714732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14724732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14734732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 14744732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 14754732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 14764732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 14774732Sdavemq 14784732Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 14794732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 14804732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 14814732Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 14824732Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 14834732Sdavemq } else { 14844732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 14853859Sml29623 } 14864732Sdavemq break; 14874732Sdavemq default: 14884732Sdavemq /* Nothing to do here */ 14894732Sdavemq goto done; 14904732Sdavemq } 14914732Sdavemq 14924732Sdavemq /* init TX RX channels */ 14934732Sdavemq for (chan = 0; chan < 4; chan++) { 14944732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 14954732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 14964732Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 14973859Sml29623 goto fail; 14984732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 14994732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 15004732Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 15013859Sml29623 goto fail; 15023859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 15034732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 15044732Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 15053859Sml29623 goto fail; 15063859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 15074732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 15084732Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 15094732Sdavemq goto fail; 15104732Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 15114732Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 15124732Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 15134732Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 15144732Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 15154732Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 15164732Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 15174732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15184732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 15194732Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 15204732Sdavemq goto fail; 15214732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15224732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 15234732Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 15244732Sdavemq goto fail; 15254732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15264732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 15274732Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 15284732Sdavemq goto fail; 15294732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15304732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 15314732Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 15323859Sml29623 goto fail; 15333859Sml29623 } 15343859Sml29623 15354732Sdavemq /* Apply Tx core reset */ 15364732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15374732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 15384732Sdavemq (uint16_t)0)) != NXGE_OK) 15394732Sdavemq goto fail; 15404732Sdavemq 15414732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15424732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 15434732Sdavemq NXGE_OK) 15444732Sdavemq goto fail; 15454732Sdavemq 15464732Sdavemq NXGE_DELAY(200); 15474732Sdavemq 15484732Sdavemq /* Apply Rx core reset */ 15494732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15504732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 15514732Sdavemq NXGE_OK) 15524732Sdavemq goto fail; 15534732Sdavemq 15544732Sdavemq NXGE_DELAY(200); 15554732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15564732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 15574732Sdavemq goto fail; 15584732Sdavemq 15594732Sdavemq NXGE_DELAY(200); 15604732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 15614732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 15624732Sdavemq &val16l)) != NXGE_OK) 15634732Sdavemq goto fail; 15644732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15654732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 15664732Sdavemq goto fail; 15674732Sdavemq if ((val16l != 0) || (val16h != 0)) { 15684732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15695196Ssbehera "Failed to reset port<%d> XAUI Serdes " 15705196Ssbehera "(val16l 0x%x val16h 0x%x)", 15715196Ssbehera portn, val16l, val16h)); 15724732Sdavemq } 15734732Sdavemq 15744732Sdavemq if (portn == 0) { 15756075Ssbehera /* Wait for serdes to be ready */ 15766075Ssbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 15776075Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 15786075Ssbehera if ((val & ESR_SIG_P0_BITS_MASK) != 15796075Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 15806075Ssbehera ESR_SIG_XSERDES_RDY_P0 | 15816075Ssbehera ESR_SIG_XDETECT_P0_CH3 | 15826075Ssbehera ESR_SIG_XDETECT_P0_CH2 | 15836075Ssbehera ESR_SIG_XDETECT_P0_CH1 | 15846075Ssbehera ESR_SIG_XDETECT_P0_CH0)) 15856075Ssbehera 15866075Ssbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 15876075Ssbehera else 15886075Ssbehera break; 15896075Ssbehera } 15906075Ssbehera 15916075Ssbehera if (i == MAX_SERDES_RDY_RETRIES) { 1592*6650Sjoycey /* 1593*6650Sjoycey * RDY signal stays low may due to the absent of the 1594*6650Sjoycey * external PHY, it is not an error condition. But still 1595*6650Sjoycey * print the message for the debugging purpose when link 1596*6650Sjoycey * stays down 1597*6650Sjoycey */ 15986075Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15996075Ssbehera "nxge_neptune_10G_serdes_init: " 16006075Ssbehera "Serdes/signal for port<%d> not ready", portn)); 1601*6650Sjoycey goto done; 16024732Sdavemq } 16034732Sdavemq } else if (portn == 1) { 16046075Ssbehera /* Wait for serdes to be ready */ 16056075Ssbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 16066075Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 16076075Ssbehera if ((val & ESR_SIG_P1_BITS_MASK) != 16086075Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 16096075Ssbehera ESR_SIG_XSERDES_RDY_P1 | 16106075Ssbehera ESR_SIG_XDETECT_P1_CH3 | 16116075Ssbehera ESR_SIG_XDETECT_P1_CH2 | 16126075Ssbehera ESR_SIG_XDETECT_P1_CH1 | 16136075Ssbehera ESR_SIG_XDETECT_P1_CH0)) 16146075Ssbehera 16156075Ssbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 16166075Ssbehera else 16176075Ssbehera break; 16186075Ssbehera } 16196075Ssbehera 16206075Ssbehera if (i == MAX_SERDES_RDY_RETRIES) { 1621*6650Sjoycey /* 1622*6650Sjoycey * RDY signal stays low may due to the absent of the 1623*6650Sjoycey * external PHY, it is not an error condition. But still 1624*6650Sjoycey * print the message for the debugging purpose when link 1625*6650Sjoycey * stays down 1626*6650Sjoycey */ 16276075Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16286075Ssbehera "nxge_neptune_10G_serdes_init: " 16296075Ssbehera "Serdes/signal for port<%d> not ready", portn)); 1630*6650Sjoycey goto done; 16313859Sml29623 } 16323859Sml29623 } 16333859Sml29623 16343859Sml29623 done: 16354732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16364732Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 16374732Sdavemq 16383859Sml29623 return (NXGE_OK); 16393859Sml29623 fail: 16405572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16414732Sdavemq "nxge_neptune_10G_serdes_init: " 16424732Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 16433859Sml29623 16443859Sml29623 return (status); 16453859Sml29623 } 16463859Sml29623 16474732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 16484732Sdavemq 16494732Sdavemq static nxge_status_t 16504732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 16513859Sml29623 { 16524732Sdavemq npi_handle_t handle; 16534732Sdavemq uint8_t portn; 16545196Ssbehera int chan; 16555196Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 16565196Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 16575196Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 16585196Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 16594732Sdavemq uint64_t val; 16605196Ssbehera uint16_t val16l; 16615196Ssbehera uint16_t val16h; 16625196Ssbehera nxge_status_t status = NXGE_OK; 16633859Sml29623 16643859Sml29623 portn = nxgep->mac.portnum; 16654732Sdavemq 16664732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16674732Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 16684732Sdavemq 16694732Sdavemq handle = nxgep->npi_handle; 16704732Sdavemq 16714732Sdavemq switch (portn) { 16724732Sdavemq case 0: 16735196Ssbehera /* Assert the reset register */ 16745196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16755196Ssbehera val |= ESR_RESET_0; 16765196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16775196Ssbehera 16785196Ssbehera /* Set the PLL register to 0x79 */ 16795196Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 16805196Ssbehera ESR_PLL_CFG_1G_SERDES); 16815196Ssbehera 16825196Ssbehera /* Set the control register to 0x249249f */ 16835196Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 16845196Ssbehera 16855196Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 16865196Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16875196Ssbehera /* Set pad loopback modes 0xaa */ 16885196Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 16895196Ssbehera ESR_TSTCFG_LBTEST_PAD); 16905196Ssbehera } else { 16915196Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 16925196Ssbehera } 16935196Ssbehera 16945196Ssbehera /* Deassert the reset register */ 16955196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16965196Ssbehera val &= ~ESR_RESET_0; 16975196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16984732Sdavemq break; 16995196Ssbehera 17004732Sdavemq case 1: 17015196Ssbehera /* Assert the reset register */ 17025196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 17035196Ssbehera val |= ESR_RESET_1; 17045196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 17055196Ssbehera 17065196Ssbehera /* Set PLL register to 0x79 */ 17075196Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 17085196Ssbehera ESR_PLL_CFG_1G_SERDES); 17095196Ssbehera 17105196Ssbehera /* Set the control register to 0x249249f */ 17115196Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 17125196Ssbehera 17135196Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 17145196Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 17155196Ssbehera /* Set pad loopback mode 0xaa */ 17165196Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 17175196Ssbehera ESR_TSTCFG_LBTEST_PAD); 17185196Ssbehera } else { 17195196Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 17205196Ssbehera } 17215196Ssbehera 17225196Ssbehera /* Deassert the reset register */ 17235196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 17245196Ssbehera val &= ~ESR_RESET_1; 17255196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 17264732Sdavemq break; 17275196Ssbehera 17284732Sdavemq default: 17295196Ssbehera /* Nothing to do here */ 17305196Ssbehera goto done; 17315196Ssbehera } 17325196Ssbehera 17335196Ssbehera /* init TX RX channels */ 17345196Ssbehera for (chan = 0; chan < 4; chan++) { 17355196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 17365196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 17375196Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 17385196Ssbehera goto fail; 17395196Ssbehera } 17405196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 17415196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 17425196Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 17435196Ssbehera goto fail; 17445196Ssbehera } 17455196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 17465196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 17475196Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 17485196Ssbehera goto fail; 17495196Ssbehera } 17505196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 17515196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 17525196Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 17535196Ssbehera goto fail; 17545196Ssbehera } 17555196Ssbehera 17565196Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 17575196Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 17585196Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 17595196Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 17605196Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 17615196Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 17625196Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 17635196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17645196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 17655196Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 17665196Ssbehera goto fail; 17675196Ssbehera } 17685196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17695196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 17705196Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 17715196Ssbehera goto fail; 17725196Ssbehera } 17735196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17745196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 17755196Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 17765196Ssbehera goto fail; 17775196Ssbehera } 17785196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17795196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 17805196Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 17815196Ssbehera goto fail; 17825196Ssbehera } 17835196Ssbehera } 17845196Ssbehera 17855196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17865196Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 17874732Sdavemq goto fail; 17883859Sml29623 } 17895196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17905196Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 17915196Ssbehera goto fail; 17925196Ssbehera } 17935196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17945196Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 17955196Ssbehera goto fail; 17965196Ssbehera } 17975196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17985196Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 17995196Ssbehera goto fail; 18005196Ssbehera } 18015196Ssbehera 18025196Ssbehera /* Apply Tx core reset */ 18035196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18045196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 18055196Ssbehera goto fail; 18065196Ssbehera } 18075196Ssbehera 18085196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18095196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 18105196Ssbehera NXGE_OK) { 18115196Ssbehera goto fail; 18125196Ssbehera } 18135196Ssbehera 18145196Ssbehera NXGE_DELAY(200); 18155196Ssbehera 18165196Ssbehera /* Apply Rx core reset */ 18175196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18185196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 18195196Ssbehera NXGE_OK) { 18205196Ssbehera goto fail; 18215196Ssbehera } 18225196Ssbehera 18235196Ssbehera NXGE_DELAY(200); 18245196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18255196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 18265196Ssbehera goto fail; 18275196Ssbehera } 18285196Ssbehera 18295196Ssbehera NXGE_DELAY(200); 18305196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18315196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 18325196Ssbehera goto fail; 18335196Ssbehera } 18345196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 18355196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 18365196Ssbehera goto fail; 18375196Ssbehera } 18385196Ssbehera if ((val16l != 0) || (val16h != 0)) { 18395196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18405196Ssbehera "Failed to reset port<%d> XAUI Serdes " 18415196Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 18425196Ssbehera status = NXGE_ERROR; 18435196Ssbehera goto fail; 18445196Ssbehera } 18455196Ssbehera 18465196Ssbehera NXGE_DELAY(200); 18475196Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 18485196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18495196Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 18505196Ssbehera "val 0x%x", portn, val)); 18515196Ssbehera if (portn == 0) { 18525196Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 18535196Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 1854*6650Sjoycey /* 1855*6650Sjoycey * RDY signal stays low may due to the absent of the 1856*6650Sjoycey * external PHY, it is not an error condition. But still 1857*6650Sjoycey * print the message for the debugging purpose when link 1858*6650Sjoycey * stays down 1859*6650Sjoycey */ 18605196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1861*6650Sjoycey "nxge_neptune_1G_serdes_init: " 1862*6650Sjoycey "Serdes/signal for port<%d> not ready", portn)); 1863*6650Sjoycey goto done; 18645196Ssbehera } 18655196Ssbehera } else if (portn == 1) { 18665196Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 18675196Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 1868*6650Sjoycey /* 1869*6650Sjoycey * RDY signal stays low may due to the absent of the 1870*6650Sjoycey * external PHY, it is not an error condition. But still 1871*6650Sjoycey * print the message for the debugging purpose when link 1872*6650Sjoycey * stays down 1873*6650Sjoycey */ 18745196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1875*6650Sjoycey "nxge_neptune_1G_serdes_init: " 1876*6650Sjoycey "Serdes/signal for port<%d> not ready", portn)); 1877*6650Sjoycey goto done; 18785196Ssbehera } 18795196Ssbehera } 18805196Ssbehera done: 18814732Sdavemq 18824732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18834732Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 18843859Sml29623 return (NXGE_OK); 18854732Sdavemq fail: 18865196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18874732Sdavemq "nxge_1G_serdes_init: " 18884732Sdavemq "Failed to initialize Neptune serdes for port<%d>", 18894732Sdavemq portn)); 18904732Sdavemq 18915196Ssbehera return (status); 18923859Sml29623 } 18933859Sml29623 18945572Ssbehera /* Initialize the BCM 8704 xcvr */ 18954732Sdavemq 18964732Sdavemq static nxge_status_t 18975572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 18983859Sml29623 { 18993859Sml29623 uint16_t val; 19003859Sml29623 #ifdef NXGE_DEBUG 19013859Sml29623 uint8_t portn; 19023859Sml29623 uint16_t val1; 19033859Sml29623 #endif 19043859Sml29623 uint8_t phy_port_addr; 19053859Sml29623 pmd_tx_control_t tx_ctl; 19063859Sml29623 control_t ctl; 19073859Sml29623 phyxs_control_t phyxs_ctl; 19083859Sml29623 pcs_control_t pcs_ctl; 19093859Sml29623 uint32_t delay = 0; 19103859Sml29623 optics_dcntr_t op_ctr; 19113859Sml29623 nxge_status_t status = NXGE_OK; 19123859Sml29623 #ifdef NXGE_DEBUG 19133859Sml29623 portn = nxgep->mac.portnum; 19143859Sml29623 #endif 19155572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 19164732Sdavemq portn)); 19174732Sdavemq 19184732Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 19194732Sdavemq 19204732Sdavemq /* Reset the transceiver */ 19214732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 19224732Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 19234732Sdavemq goto fail; 19244732Sdavemq 19254732Sdavemq phyxs_ctl.bits.reset = 1; 19264732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 19274732Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 19284732Sdavemq goto fail; 19294732Sdavemq 19304732Sdavemq do { 19314732Sdavemq drv_usecwait(500); 19324732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19334732Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 19344732Sdavemq &phyxs_ctl.value)) != NXGE_OK) 19354732Sdavemq goto fail; 19364732Sdavemq delay++; 19374732Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 19384732Sdavemq if (delay == 100) { 19394732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 19404732Sdavemq "failed to reset Transceiver on port<%d>", portn)); 19414732Sdavemq status = NXGE_ERROR; 19424732Sdavemq goto fail; 19434732Sdavemq } 19444732Sdavemq 19454732Sdavemq /* Set to 0x7FBF */ 19464732Sdavemq ctl.value = 0; 19474732Sdavemq ctl.bits.res1 = 0x3F; 19484732Sdavemq ctl.bits.optxon_lvl = 1; 19494732Sdavemq ctl.bits.oprxflt_lvl = 1; 19504732Sdavemq ctl.bits.optrxlos_lvl = 1; 19514732Sdavemq ctl.bits.optxflt_lvl = 1; 19524732Sdavemq ctl.bits.opprflt_lvl = 1; 19534732Sdavemq ctl.bits.obtmpflt_lvl = 1; 19544732Sdavemq ctl.bits.opbiasflt_lvl = 1; 19554732Sdavemq ctl.bits.optxrst_lvl = 1; 19564732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 19574732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 19584732Sdavemq != NXGE_OK) 19594732Sdavemq goto fail; 19604732Sdavemq 19614732Sdavemq /* Set to 0x164 */ 19624732Sdavemq tx_ctl.value = 0; 19634732Sdavemq tx_ctl.bits.tsck_lpwren = 1; 19644732Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 19654732Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 19664732Sdavemq tx_ctl.bits.xfp_clken = 1; 19674732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 19684732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 19694732Sdavemq tx_ctl.value)) != NXGE_OK) 19704732Sdavemq goto fail; 19714732Sdavemq /* 19724732Sdavemq * According to Broadcom's instruction, SW needs to read 19734732Sdavemq * back these registers twice after written. 19744732Sdavemq */ 19754732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19764732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 19774732Sdavemq != NXGE_OK) 19784732Sdavemq goto fail; 19794732Sdavemq 19804732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19814732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 19824732Sdavemq != NXGE_OK) 19834732Sdavemq goto fail; 19844732Sdavemq 19854732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19864732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 19874732Sdavemq != NXGE_OK) 19884732Sdavemq goto fail; 19894732Sdavemq 19904732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19914732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 19924732Sdavemq != NXGE_OK) 19934732Sdavemq goto fail; 19944732Sdavemq 19954732Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 19964732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19974732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 19984732Sdavemq &op_ctr.value)) != NXGE_OK) 19994732Sdavemq goto fail; 20005553Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 20015553Smisaki op_ctr.bits.gpio_sel = 0x1; 20025553Smisaki } else { 20035553Smisaki op_ctr.bits.gpio_sel = 0x3; 20045553Smisaki } 20054732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 20064732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 20074732Sdavemq op_ctr.value)) != NXGE_OK) 20084732Sdavemq goto fail; 20094732Sdavemq 20104732Sdavemq NXGE_DELAY(1000000); 20114732Sdavemq 20124732Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 20134732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20144732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 20154732Sdavemq != NXGE_OK) 20164732Sdavemq goto fail; 20174732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 20184732Sdavemq pcs_ctl.bits.loopback = 1; 20194732Sdavemq else 20204732Sdavemq pcs_ctl.bits.loopback = 0; 20214732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 20224732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 20234732Sdavemq != NXGE_OK) 20244732Sdavemq goto fail; 20254732Sdavemq 20264732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 20274732Sdavemq if (status != NXGE_OK) 20284732Sdavemq goto fail; 20294732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20304732Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 20314732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 20324732Sdavemq if (status != NXGE_OK) 20334732Sdavemq goto fail; 20344732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20354732Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 20364732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 20374732Sdavemq if (status != NXGE_OK) 20384732Sdavemq goto fail; 20394732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20404732Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 20414732Sdavemq 20424732Sdavemq #ifdef NXGE_DEBUG 20434732Sdavemq /* Diagnose link issue if link is not up */ 20444732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 20454732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 20464732Sdavemq &val); 20474732Sdavemq if (status != NXGE_OK) 20484732Sdavemq goto fail; 20494732Sdavemq 20504732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 20514732Sdavemq BCM8704_USER_DEV3_ADDR, 20524732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 20534732Sdavemq &val); 20544732Sdavemq if (status != NXGE_OK) 20554732Sdavemq goto fail; 20564732Sdavemq 20574732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 20584732Sdavemq BCM8704_USER_DEV3_ADDR, 20594732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 20604732Sdavemq &val1); 20614732Sdavemq if (status != NXGE_OK) 20624732Sdavemq goto fail; 20634732Sdavemq 20644732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 20654732Sdavemq BCM8704_USER_DEV3_ADDR, 20664732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 20674732Sdavemq &val1); 20684732Sdavemq if (status != NXGE_OK) 20694732Sdavemq goto fail; 20704732Sdavemq 20714732Sdavemq if (val != 0x3FC) { 20724732Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 20734732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20744732Sdavemq "Cable not connected to peer or bad" 20754732Sdavemq " cable on port<%d>\n", portn)); 20764732Sdavemq } else if (val == 0x639C) { 20774732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20784732Sdavemq "Optical module (XFP) is bad or absent" 20794732Sdavemq " on port<%d>\n", portn)); 20804732Sdavemq } 20814732Sdavemq } 20824732Sdavemq #endif 20834732Sdavemq 20845572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 20855572Ssbehera portn)); 20865572Ssbehera return (NXGE_OK); 20875572Ssbehera 20885572Ssbehera fail: 20895572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20905572Ssbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 20915572Ssbehera "port<%d>", nxgep->mac.portnum)); 20925572Ssbehera return (NXGE_ERROR); 20935572Ssbehera } 20945572Ssbehera 20955572Ssbehera /* Initialize the BCM 8706 Transceiver */ 20965572Ssbehera 20975572Ssbehera static nxge_status_t 20985572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 20995572Ssbehera { 21005572Ssbehera uint8_t phy_port_addr; 21015572Ssbehera phyxs_control_t phyxs_ctl; 21025572Ssbehera pcs_control_t pcs_ctl; 21035572Ssbehera uint32_t delay = 0; 21045572Ssbehera optics_dcntr_t op_ctr; 21055572Ssbehera nxge_status_t status = NXGE_OK; 21065572Ssbehera #ifdef NXGE_DEBUG 21075572Ssbehera uint8_t portn = nxgep->mac.portnum; 21085572Ssbehera #endif 21095572Ssbehera 21105572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 21115572Ssbehera portn)); 21125572Ssbehera 21135572Ssbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 21145572Ssbehera 21155572Ssbehera /* Reset the transceiver */ 21165572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 21175572Ssbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 21185572Ssbehera goto fail; 21195572Ssbehera 21205572Ssbehera phyxs_ctl.bits.reset = 1; 21215572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 21225572Ssbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 21235572Ssbehera goto fail; 21245572Ssbehera do { 21255572Ssbehera drv_usecwait(500); 21265572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21275572Ssbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 21285572Ssbehera &phyxs_ctl.value)) != NXGE_OK) 21295572Ssbehera goto fail; 21305572Ssbehera delay++; 21315572Ssbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 21325572Ssbehera 21335572Ssbehera if (delay == 100) { 21345572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21355572Ssbehera "failed to reset Transceiver on port<%d>", portn)); 21365572Ssbehera status = NXGE_ERROR; 21375572Ssbehera goto fail; 21385572Ssbehera } 21395572Ssbehera 21405572Ssbehera NXGE_DELAY(1000000); 21415572Ssbehera 21425572Ssbehera /* Set BCM8706 Internal Loopback mode if necessary */ 21435572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21445572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 21455572Ssbehera != NXGE_OK) 21465572Ssbehera goto fail; 21475572Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 21485572Ssbehera pcs_ctl.bits.loopback = 1; 21495572Ssbehera else 21505572Ssbehera pcs_ctl.bits.loopback = 0; 21515572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21525572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 21535572Ssbehera != NXGE_OK) 21545572Ssbehera goto fail; 21555572Ssbehera 21565572Ssbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 21575572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21585572Ssbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21595572Ssbehera &op_ctr.value)) != NXGE_OK) 21605572Ssbehera goto fail; 21615572Ssbehera op_ctr.bits.gpio_sel = 0x3; 21625572Ssbehera op_ctr.bits.res2 = 0x1; 21635572Ssbehera 21645572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21655572Ssbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21665572Ssbehera op_ctr.value)) != NXGE_OK) 21675572Ssbehera goto fail; 21685572Ssbehera 21695572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 21705572Ssbehera portn)); 21715572Ssbehera return (NXGE_OK); 21725572Ssbehera 21735572Ssbehera fail: 21745572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21755572Ssbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 21765572Ssbehera "port<%d>", nxgep->mac.portnum)); 21775572Ssbehera return (status); 21785572Ssbehera } 21795572Ssbehera 21806604Ssbehera #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 21816604Ssbehera 21826604Ssbehera #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 21836604Ssbehera CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 21846604Ssbehera 21856604Ssbehera #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 21866604Ssbehera CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 21876604Ssbehera 21886604Ssbehera 21896604Ssbehera static void 21906604Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 21916604Ssbehera { 21926604Ssbehera uint16_t value; 21936604Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 21946604Ssbehera 21956604Ssbehera if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 21966604Ssbehera MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 21976604Ssbehera value &= ~MRVL_88X2011_LED_BLK_MASK; 21986604Ssbehera value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 21996604Ssbehera (void) nxge_mdio_write(nxgep, phy, 22006604Ssbehera MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 22016604Ssbehera value); 22026604Ssbehera } 22036604Ssbehera } 22046604Ssbehera 22056604Ssbehera static nxge_status_t 22066604Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 22076604Ssbehera { 22086604Ssbehera nxge_status_t status; 22096604Ssbehera pcs_control_t pcs_ctl; 22106604Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 22116604Ssbehera 22126604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 22136604Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 22146604Ssbehera 22156604Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 22166604Ssbehera pcs_ctl.bits.loopback = 1; 22176604Ssbehera else 22186604Ssbehera pcs_ctl.bits.loopback = 0; 22196604Ssbehera 22206604Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 22216604Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 22226604Ssbehera 22236604Ssbehera fail: 22246604Ssbehera return (status); 22256604Ssbehera } 22266604Ssbehera 22276604Ssbehera 22286604Ssbehera static void 22296604Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 22306604Ssbehera { 22316604Ssbehera uint16_t val2; 22326604Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 22336604Ssbehera 22346604Ssbehera val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 22356604Ssbehera val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 22366604Ssbehera MRVL_88X2011_LED_CTL_MASK); 22376604Ssbehera val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 22386604Ssbehera 22396604Ssbehera if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 22406604Ssbehera MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 22416604Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22426604Ssbehera "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 22436604Ssbehera } 22446604Ssbehera } 22456604Ssbehera 22466604Ssbehera 22476604Ssbehera static nxge_status_t 22486604Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 22496604Ssbehera { 22506604Ssbehera uint8_t phy; 22516604Ssbehera nxge_status_t status; 22526604Ssbehera uint16_t clk; 22536604Ssbehera 22546604Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 22556604Ssbehera 22566604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 22576604Ssbehera "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 22586604Ssbehera nxgep->mac.portnum, phy)); 22596604Ssbehera 22606604Ssbehera /* Set LED functions */ 22616604Ssbehera nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 22626604Ssbehera /* PCS activity */ 22636604Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 22646604Ssbehera 22656604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 22666604Ssbehera MRVL_88X2011_GEN_CTL, &clk); 22676604Ssbehera clk |= MRVL_88X2011_ENA_XFPREFCLK; 22686604Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 22696604Ssbehera MRVL_88X2011_GEN_CTL, clk); 22706604Ssbehera 22716604Ssbehera /* Set internal loopback mode if necessary */ 22726604Ssbehera 22736604Ssbehera CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 22746604Ssbehera 22756604Ssbehera /* Enable PMD */ 22766604Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 22776604Ssbehera MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 22786604Ssbehera 22796604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 22806604Ssbehera 22816604Ssbehera fail: 22826604Ssbehera return (status); 22836604Ssbehera } 22846604Ssbehera 22856604Ssbehera 22866604Ssbehera 22875572Ssbehera /* Initialize the 10G Transceiver */ 22885572Ssbehera 22895572Ssbehera static nxge_status_t 22905572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 22915572Ssbehera { 22925572Ssbehera p_nxge_stats_t statsp; 22936439Sml29623 p_nxge_param_t param_arr = nxgep->param_arr; 22945572Ssbehera nxge_status_t status = NXGE_OK; 22955572Ssbehera #ifdef NXGE_DEBUG 22965572Ssbehera uint8_t portn = nxgep->mac.portnum; 22975572Ssbehera #endif 22985572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 22995572Ssbehera portn)); 23005572Ssbehera 23015572Ssbehera statsp = nxgep->statsp; 23025572Ssbehera 23035572Ssbehera if (nxgep->mac.portmode == PORT_10G_SERDES) { 23045572Ssbehera goto done; 23055572Ssbehera } 23065572Ssbehera 23075572Ssbehera /* Disable Link LEDs */ 23085572Ssbehera if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 23095572Ssbehera goto fail; 23105572Ssbehera 23115572Ssbehera /* Set Clause 45 */ 23125572Ssbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 23135572Ssbehera 23145572Ssbehera switch (nxgep->chip_id) { 23155572Ssbehera case BCM8704_CHIP_ID: 23165572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 23175572Ssbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 23185572Ssbehera status = nxge_BCM8704_xcvr_init(nxgep); 23195572Ssbehera break; 23205572Ssbehera case BCM8706_CHIP_ID: 23215572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 23225572Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 23235572Ssbehera status = nxge_BCM8706_xcvr_init(nxgep); 23245572Ssbehera break; 23256604Ssbehera case MRVL88X201X_CHIP_ID: 23266604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 23276604Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 23286604Ssbehera status = nxge_mrvl88x2011_xcvr_init(nxgep); 23296604Ssbehera break; 23305572Ssbehera default: 23315572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 23325572Ssbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 23335572Ssbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 23345572Ssbehera goto fail; 23355572Ssbehera } 23365572Ssbehera 23375572Ssbehera if (status != NXGE_OK) { 23385572Ssbehera goto fail; 23395572Ssbehera } 23404977Sraghus done: 23414732Sdavemq statsp->mac_stats.cap_10gfdx = 1; 23424732Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 23436439Sml29623 statsp->mac_stats.adv_cap_asmpause = 23446439Sml29623 param_arr[param_anar_asmpause].value; 23456439Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 23464732Sdavemq 23474732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 23484732Sdavemq portn)); 23494732Sdavemq return (NXGE_OK); 23504732Sdavemq 23514732Sdavemq fail: 23525572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23534732Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 23545572Ssbehera "port<%d>", nxgep->mac.portnum)); 23555572Ssbehera return (NXGE_ERROR); 23564732Sdavemq } 23574732Sdavemq 23584732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 23594732Sdavemq 23604732Sdavemq static nxge_status_t 23614732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 23624732Sdavemq { 23634732Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 23644732Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 23654732Sdavemq nxge_status_t status = NXGE_OK; 23664732Sdavemq 23674977Sraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 23684977Sraghus statsp->mac_stats.cap_1000fdx = 23694977Sraghus param_arr[param_anar_1000fdx].value; 23704977Sraghus goto done; 23714977Sraghus } 23724977Sraghus 23734732Sdavemq /* Set Clause 22 */ 23744732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 23754732Sdavemq 23764732Sdavemq /* Set capability flags */ 23774732Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 23784977Sraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 23794977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 23804977Sraghus statsp->mac_stats.cap_100fdx = 23814977Sraghus param_arr[param_anar_100fdx].value; 23824977Sraghus statsp->mac_stats.cap_10fdx = 23834977Sraghus param_arr[param_anar_10fdx].value; 23844977Sraghus } 23854732Sdavemq 23864732Sdavemq status = nxge_mii_xcvr_init(nxgep); 23874977Sraghus done: 23884732Sdavemq return (status); 23894732Sdavemq } 23904732Sdavemq 23914732Sdavemq /* Initialize transceiver */ 23924732Sdavemq 23934732Sdavemq nxge_status_t 23944732Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 23954732Sdavemq { 23964732Sdavemq p_nxge_stats_t statsp; 23974732Sdavemq #ifdef NXGE_DEBUG 23984732Sdavemq uint8_t portn; 23994732Sdavemq #endif 24004732Sdavemq 24014732Sdavemq nxge_status_t status = NXGE_OK; 24024732Sdavemq #ifdef NXGE_DEBUG 24034732Sdavemq portn = nxgep->mac.portnum; 24044732Sdavemq #endif 24053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 24063859Sml29623 statsp = nxgep->statsp; 24073859Sml29623 24083859Sml29623 /* 24093859Sml29623 * Initialize the xcvr statistics. 24103859Sml29623 */ 24113859Sml29623 statsp->mac_stats.cap_autoneg = 0; 24123859Sml29623 statsp->mac_stats.cap_100T4 = 0; 24133859Sml29623 statsp->mac_stats.cap_100fdx = 0; 24143859Sml29623 statsp->mac_stats.cap_100hdx = 0; 24153859Sml29623 statsp->mac_stats.cap_10fdx = 0; 24163859Sml29623 statsp->mac_stats.cap_10hdx = 0; 24173859Sml29623 statsp->mac_stats.cap_asmpause = 0; 24183859Sml29623 statsp->mac_stats.cap_pause = 0; 24193859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 24203859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 24213859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 24223859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 24233859Sml29623 24243859Sml29623 /* 24253859Sml29623 * Initialize the link statistics. 24263859Sml29623 */ 24273859Sml29623 statsp->mac_stats.link_T4 = 0; 24283859Sml29623 statsp->mac_stats.link_asmpause = 0; 24293859Sml29623 statsp->mac_stats.link_pause = 0; 24303859Sml29623 24314732Sdavemq if (nxgep->xcvr.xcvr_init) { 24324732Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 24333859Sml29623 if (status != NXGE_OK) 24343859Sml29623 goto fail; 24354732Sdavemq statsp->mac_stats.xcvr_inits++; 24363859Sml29623 } 24373859Sml29623 24384732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 24394732Sdavemq portn)); 24403859Sml29623 return (NXGE_OK); 24413859Sml29623 24423859Sml29623 fail: 24433859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 24444732Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 24454732Sdavemq portn)); 24463859Sml29623 return (status); 24473859Sml29623 } 24483859Sml29623 24494977Sraghus /* Look for transceiver type */ 24504977Sraghus 24514977Sraghus nxge_status_t 24524977Sraghus nxge_xcvr_find(p_nxge_t nxgep) 24534977Sraghus { 24545196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 24555196Ssbehera nxgep->mac.portnum)); 24564977Sraghus 24574977Sraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 24584977Sraghus return (NXGE_ERROR); 24594977Sraghus 24604977Sraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 24614977Sraghus return (NXGE_ERROR); 24624977Sraghus 24634977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 24644977Sraghus nxgep->statsp->mac_stats.xcvr_inuse)); 24654977Sraghus return (NXGE_OK); 24664977Sraghus } 24673859Sml29623 24683859Sml29623 /* Initialize the TxMAC sub-block */ 24693859Sml29623 24703859Sml29623 nxge_status_t 24713859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 24723859Sml29623 { 24733859Sml29623 npi_attr_t ap; 24743859Sml29623 uint8_t portn; 24753859Sml29623 nxge_port_mode_t portmode; 24763859Sml29623 nxge_port_t portt; 24773859Sml29623 npi_handle_t handle; 24783859Sml29623 npi_status_t rs = NPI_SUCCESS; 24793859Sml29623 24803859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 24813859Sml29623 portt = nxgep->mac.porttype; 24823859Sml29623 handle = nxgep->npi_handle; 24833859Sml29623 portmode = nxgep->mac.portmode; 24843859Sml29623 24853859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 24863859Sml29623 portn)); 24873859Sml29623 /* Set Max and Min Frame Size */ 24886439Sml29623 /* 24896439Sml29623 * Use maxframesize to configure the hardware maxframe size 24906439Sml29623 * and minframesize to configure the hardwae minframe size. 24916439Sml29623 */ 24926439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 24936439Sml29623 "==> nxge_tx_mac_init: port<%d> " 24946439Sml29623 "min framesize %d max framesize %d ", 24956439Sml29623 nxgep->mac.minframesize, 24966439Sml29623 nxgep->mac.maxframesize, 24976439Sml29623 portn)); 24986439Sml29623 24996439Sml29623 SET_MAC_ATTR2(handle, ap, portn, 25006439Sml29623 MAC_PORT_FRAME_SIZE, 25016439Sml29623 nxgep->mac.minframesize, 25026439Sml29623 nxgep->mac.maxframesize, 25036439Sml29623 rs); 25043859Sml29623 if (rs != NPI_SUCCESS) 25053859Sml29623 goto fail; 25063859Sml29623 25073859Sml29623 if (portt == PORT_TYPE_XMAC) { 25083859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 25093859Sml29623 0)) != NPI_SUCCESS) 25103859Sml29623 goto fail; 25113859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 25123859Sml29623 if ((portmode == PORT_10G_FIBER) || 25134977Sraghus (portmode == PORT_10G_COPPER) || 25144977Sraghus (portmode == PORT_10G_SERDES)) { 25153859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 25163859Sml29623 XGMII_IPG_12_15, rs); 25173859Sml29623 if (rs != NPI_SUCCESS) 25183859Sml29623 goto fail; 25193859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 25203859Sml29623 } else { 25213859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 25223859Sml29623 MII_GMII_IPG_12, rs); 25233859Sml29623 if (rs != NPI_SUCCESS) 25243859Sml29623 goto fail; 25253859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 25263859Sml29623 } 25273859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 25283859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 25293859Sml29623 goto fail; 25303859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 25313859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 25323859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 25333859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 25343859Sml29623 25353859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 25363859Sml29623 != NPI_SUCCESS) 25373859Sml29623 goto fail; 25383859Sml29623 25393859Sml29623 } else { 25403859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 25413859Sml29623 0)) != NPI_SUCCESS) 25423859Sml29623 goto fail; 25433859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 25443859Sml29623 25453859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 25463859Sml29623 rs); 25473859Sml29623 if (rs != NPI_SUCCESS) 25483859Sml29623 goto fail; 25493859Sml29623 nxgep->mac.ctrltype = 0x8808; 25503859Sml29623 25513859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 25523859Sml29623 if (rs != NPI_SUCCESS) 25533859Sml29623 goto fail; 25543859Sml29623 nxgep->mac.pa_size = 0x7; 25553859Sml29623 25563859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 25573859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 25583859Sml29623 goto fail; 25593859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 25603859Sml29623 } 25613859Sml29623 25623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 25633859Sml29623 portn)); 25643859Sml29623 25653859Sml29623 return (NXGE_OK); 25663859Sml29623 fail: 25673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 25683859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 25693859Sml29623 portn)); 25703859Sml29623 25713859Sml29623 return (NXGE_ERROR | rs); 25723859Sml29623 } 25733859Sml29623 25746495Sspeer int 25756495Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep) 25766495Sspeer { 25776495Sspeer int rdc_tbl; 25786495Sspeer 25796495Sspeer /* 25806495Sspeer * Get an RDC table (version 0). 25816495Sspeer */ 25826495Sspeer if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) { 25836495Sspeer NXGE_ERROR_MSG((nxgep, OBP_CTL, 25846495Sspeer "nxge_hio_hostinfo_get_rdc_table: " 25856495Sspeer "there are no free RDC tables!")); 25866495Sspeer return (EBUSY); 25876495Sspeer } 25886495Sspeer 25896495Sspeer return (rdc_tbl); 25906495Sspeer } 25916495Sspeer 25926495Sspeer /* 25936495Sspeer * nxge_hio_hostinfo_init 25946495Sspeer * 25956495Sspeer * Initialize an alternate MAC address, and bind a macrdctbln to it. 25966495Sspeer * 25976495Sspeer * Arguments: 25986495Sspeer * nxge 25996495Sspeer * vr The Virtualization Region 26006495Sspeer * macaddr The alternate MAC address 26016495Sspeer * 26026495Sspeer * Notes: 26036495Sspeer * 1. Find & bind an RDC table to <nxge>. 26046495Sspeer * 2. Program an alternate MAC address (<macaddr>). 26056495Sspeer * 3. Bind the RDC table to <macaddr>. 26066495Sspeer * 26076495Sspeer * Context: 26086495Sspeer * Service domain 26096495Sspeer * 26106495Sspeer * Side Effects: 26116495Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 26126495Sspeer * vr->slot & vr->altmac 26136495Sspeer * 26146495Sspeer */ 26156495Sspeer int 26166495Sspeer nxge_hio_hostinfo_init( 26176495Sspeer nxge_t *nxge, 26186495Sspeer nxge_hio_vr_t *vr, /* Virtualization Region */ 26196495Sspeer ether_addr_t *macaddr) /* The alternate MAC address */ 26206495Sspeer { 26216495Sspeer int rdc_tbl, slot; 26226495Sspeer 26236495Sspeer nxge_class_pt_cfg_t *class; 26246495Sspeer hostinfo_t mac_rdc; 26256495Sspeer npi_mac_addr_t altmac; 26266495Sspeer nxge_mmac_t *mmac_info; 26276495Sspeer nxge_rdc_grp_t *group; 26286495Sspeer uint8_t *addr = (uint8_t *)macaddr; 26296495Sspeer 26306495Sspeer mutex_enter(nxge->genlock); 26316495Sspeer 26326495Sspeer rdc_tbl = vr->rdc_tbl; 26336495Sspeer 26346495Sspeer /* Initialize the NXGE RDC table data structure. */ 26356495Sspeer group = &nxge->pt_config.rdc_grps[rdc_tbl]; 26366495Sspeer group->port = NXGE_GET_PORT_NUM(nxge->function_num); 26376495Sspeer group->config_method = RDC_TABLE_ENTRY_METHOD_REP; 26386495Sspeer group->flag = 1; /* This group has been configured. */ 26396495Sspeer 26406495Sspeer mmac_info = &nxge->nxge_mmac_info; 26416495Sspeer 26426495Sspeer /* 26436495Sspeer * Are there free slots. 26446495Sspeer */ 26456495Sspeer if (mmac_info->naddrfree == 0) { 26466495Sspeer mutex_exit(nxge->genlock); 26476495Sspeer return (ENOSPC); 26486495Sspeer } 26496495Sspeer 26506495Sspeer /* 26516495Sspeer * The vswitch has already added this MAC address. 26526495Sspeer * Find its assigned slot. 26536495Sspeer */ 26546495Sspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 26556495Sspeer for (slot = mmac_info->num_factory_mmac + 1; 26566495Sspeer slot <= mmac_info->num_mmac; slot++) { 26576495Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 26586495Sspeer break; 26596495Sspeer } 26606495Sspeer if (slot > mmac_info->num_mmac) { 26616495Sspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 26626495Sspeer slot++) { 26636495Sspeer if (!(mmac_info->mac_pool[slot].flags 26646495Sspeer & MMAC_SLOT_USED)) 26656495Sspeer break; 26666495Sspeer } 26676495Sspeer } 26686495Sspeer } else { 26696495Sspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 26706495Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 26716495Sspeer break; 26726495Sspeer } 26736495Sspeer } 26746495Sspeer 26756495Sspeer ASSERT(slot <= mmac_info->num_mmac); 26766495Sspeer vr->slot = slot; 26776495Sspeer slot = vr->slot - 1; 26786495Sspeer 26796495Sspeer /* 26806495Sspeer * Programm the mac address. 26816495Sspeer */ 26826495Sspeer altmac.w2 = (((uint16_t)addr[0]) << 8) | 26836495Sspeer (((uint16_t)addr[1]) & 0x0ff); 26846495Sspeer altmac.w1 = (((uint16_t)addr[2]) << 8) | 26856495Sspeer (((uint16_t)addr[3]) & 0x0ff); 26866495Sspeer altmac.w0 = (((uint16_t)addr[4]) << 8) | 26876495Sspeer (((uint16_t)addr[5]) & 0x0ff); 26886495Sspeer 26896495Sspeer if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET, 26906495Sspeer nxge->function_num, slot, &altmac) != NPI_SUCCESS) { 26916495Sspeer mutex_exit(nxge->genlock); 26926495Sspeer return (EIO); 26936495Sspeer } 26946495Sspeer 26956495Sspeer /* 26966495Sspeer * Associate <rdc_tbl> with this MAC address slot. 26976495Sspeer */ 26986495Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 26996495Sspeer 27006495Sspeer /* Update this variable. */ 27016495Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 27026495Sspeer class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl; 27036495Sspeer 27046495Sspeer mac_rdc.value = 0; 27056495Sspeer mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl; 27066495Sspeer mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr; 27076495Sspeer /* <mpr_npr> had better be 1! */ 27086495Sspeer 27096495Sspeer /* Program the RDC table. */ 27106495Sspeer if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET, 27116495Sspeer nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) { 27126495Sspeer mutex_exit(nxge->genlock); 27136495Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 27146495Sspeer return (EIO); 27156495Sspeer } 27166495Sspeer 27176495Sspeer if (nxge->mac.portnum != XMAC_PORT_0 && 27186495Sspeer nxge->mac.portnum != XMAC_PORT_1) 27196495Sspeer slot++; 27206495Sspeer 27216495Sspeer /* (Re-)enable the MAC address. */ 27226495Sspeer (void) npi_mac_altaddr_enable( 27236495Sspeer nxge->npi_handle, nxge->mac.portnum, slot); 27246495Sspeer 27256495Sspeer bcopy(macaddr, vr->altmac, sizeof (vr->altmac)); 27266495Sspeer 27276495Sspeer /* 27286495Sspeer * Update mmac 27296495Sspeer */ 27306495Sspeer bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL); 27316495Sspeer mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED; 27326495Sspeer mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR; 27336495Sspeer mmac_info->naddrfree--; 27346495Sspeer nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE); 27356495Sspeer 27366495Sspeer mutex_exit(nxge->genlock); 27376495Sspeer return (0); 27386495Sspeer } 27396495Sspeer 27406495Sspeer /* 27416495Sspeer * nxge_hio_hostinfo_uninit 27426495Sspeer * 27436495Sspeer * Uninitialize an alternate MAC address. 27446495Sspeer * 27456495Sspeer * Arguments: 27466495Sspeer * nxge 27476495Sspeer * vr The Virtualization Region 27486495Sspeer * 27496495Sspeer * Notes: 27506495Sspeer * 1. Remove the VR's alternate MAC address. 27516495Sspeer * 1. Free (unbind) the RDC table allocated to this VR. 27526495Sspeer * 27536495Sspeer * Context: 27546495Sspeer * Service domain 27556495Sspeer * 27566495Sspeer * Side Effects: 27576495Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 27586495Sspeer * 27596495Sspeer */ 27606495Sspeer void 27616495Sspeer nxge_hio_hostinfo_uninit( 27626495Sspeer nxge_t *nxge, 27636495Sspeer nxge_hio_vr_t *vr) 27646495Sspeer { 27656495Sspeer nxge_class_pt_cfg_t *class; 27666495Sspeer 27676495Sspeer (void) npi_mac_altaddr_disable( 27686495Sspeer nxge->npi_handle, nxge->mac.portnum, vr->slot); 27696495Sspeer 27706495Sspeer /* Set this variable to its default. */ 27716495Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 27726495Sspeer class->mac_host_info[vr->slot].rdctbl = 27736495Sspeer nxge->pt_config.hw_config.def_mac_rxdma_grpid; 27746495Sspeer 27756495Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 27766495Sspeer vr->slot = -1; 27776495Sspeer 27786495Sspeer (void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl); 27796495Sspeer vr->rdc_tbl = -1; 27806495Sspeer } 27816495Sspeer 27823859Sml29623 /* Initialize the RxMAC sub-block */ 27833859Sml29623 27843859Sml29623 nxge_status_t 27853859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 27863859Sml29623 { 27873859Sml29623 npi_attr_t ap; 27883859Sml29623 uint32_t i; 27893859Sml29623 uint16_t hashtab_e; 27903859Sml29623 p_hash_filter_t hash_filter; 27913859Sml29623 nxge_port_t portt; 27923859Sml29623 uint8_t portn; 27933859Sml29623 npi_handle_t handle; 27943859Sml29623 npi_status_t rs = NPI_SUCCESS; 27953859Sml29623 uint16_t *addr16p; 27963859Sml29623 uint16_t addr0, addr1, addr2; 27973859Sml29623 xmac_rx_config_t xconfig; 27983859Sml29623 bmac_rx_config_t bconfig; 27993859Sml29623 28003859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 28013859Sml29623 28023859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 28033859Sml29623 portn)); 28043859Sml29623 handle = nxgep->npi_handle; 28053859Sml29623 portt = nxgep->mac.porttype; 28063859Sml29623 28073859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 28083859Sml29623 addr0 = ntohs(addr16p[2]); 28093859Sml29623 addr1 = ntohs(addr16p[1]); 28103859Sml29623 addr2 = ntohs(addr16p[0]); 28113859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 28123859Sml29623 rs); 28133859Sml29623 28143859Sml29623 if (rs != NPI_SUCCESS) 28153859Sml29623 goto fail; 28163859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 28173859Sml29623 if (rs != NPI_SUCCESS) 28183859Sml29623 goto fail; 28193859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 28203859Sml29623 if (rs != NPI_SUCCESS) 28213859Sml29623 goto fail; 28223859Sml29623 28233859Sml29623 /* 28243859Sml29623 * Load the multicast hash filter bits. 28253859Sml29623 */ 28263859Sml29623 hash_filter = nxgep->hash_filter; 28273859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 28283859Sml29623 if (hash_filter != NULL) { 28293859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 28303859Sml29623 (NMCFILTER_REGS - 1) - i]; 28313859Sml29623 } else { 28323859Sml29623 hashtab_e = 0; 28333859Sml29623 } 28343859Sml29623 28353859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 28363859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 28373859Sml29623 goto fail; 28383859Sml29623 } 28393859Sml29623 28403859Sml29623 if (portt == PORT_TYPE_XMAC) { 28413859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 28423859Sml29623 0)) != NPI_SUCCESS) 28433859Sml29623 goto fail; 28443859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 28453859Sml29623 28463859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 28473859Sml29623 28483859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 28493859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 28503859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 28513859Sml29623 28523859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 28533859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 28543859Sml29623 28553859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 28563859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 28573859Sml29623 28583859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 28593859Sml29623 28603859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 28613859Sml29623 xconfig)) != NPI_SUCCESS) 28623859Sml29623 goto fail; 28633859Sml29623 nxgep->mac.rx_config = xconfig; 28643859Sml29623 28653859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 28663859Sml29623 28673859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 28683859Sml29623 != NPI_SUCCESS) 28693859Sml29623 goto fail; 28703859Sml29623 } else { 28713859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 28723859Sml29623 28733859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 28743859Sml29623 0) != NPI_SUCCESS) 28753859Sml29623 goto fail; 28763859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 28773859Sml29623 28783859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 28793859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 28803859Sml29623 28813859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 28823859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 28833859Sml29623 28843859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 28853859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 28863859Sml29623 28873859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 28883859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 28893859Sml29623 bconfig)) != NPI_SUCCESS) 28903859Sml29623 goto fail; 28913859Sml29623 nxgep->mac.rx_config = bconfig; 28923859Sml29623 28933859Sml29623 /* Always enable comparison of mac unique address */ 28943859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 28953859Sml29623 != NPI_SUCCESS) 28963859Sml29623 goto fail; 28973859Sml29623 } 28983859Sml29623 28993859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 29003859Sml29623 portn)); 29013859Sml29623 29023859Sml29623 return (NXGE_OK); 29033859Sml29623 29043859Sml29623 fail: 29053859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 29063859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 29073859Sml29623 portn)); 29083859Sml29623 29093859Sml29623 return (NXGE_ERROR | rs); 29103859Sml29623 } 29113859Sml29623 29123859Sml29623 /* Enable TXMAC */ 29133859Sml29623 29143859Sml29623 nxge_status_t 29153859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 29163859Sml29623 { 29173859Sml29623 npi_handle_t handle; 29183859Sml29623 npi_status_t rs = NPI_SUCCESS; 29193859Sml29623 nxge_status_t status = NXGE_OK; 29203859Sml29623 29213859Sml29623 handle = nxgep->npi_handle; 29223859Sml29623 29233859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 29243859Sml29623 nxgep->mac.portnum)); 29253859Sml29623 29263859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 29273859Sml29623 goto fail; 29283859Sml29623 29293859Sml29623 /* based on speed */ 29303859Sml29623 nxgep->msg_min = ETHERMIN; 29313859Sml29623 29323859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 29333859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 29343859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 29353859Sml29623 goto fail; 29363859Sml29623 } else { 29373859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 29383859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 29393859Sml29623 goto fail; 29403859Sml29623 } 29413859Sml29623 29423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 29433859Sml29623 nxgep->mac.portnum)); 29443859Sml29623 29453859Sml29623 return (NXGE_OK); 29463859Sml29623 fail: 29473859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 29483859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 29493859Sml29623 nxgep->mac.portnum)); 29503859Sml29623 if (rs != NPI_SUCCESS) 29513859Sml29623 return (NXGE_ERROR | rs); 29523859Sml29623 else 29533859Sml29623 return (status); 29543859Sml29623 } 29553859Sml29623 29563859Sml29623 /* Disable TXMAC */ 29573859Sml29623 29583859Sml29623 nxge_status_t 29593859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 29603859Sml29623 { 29613859Sml29623 npi_handle_t handle; 29623859Sml29623 npi_status_t rs = NPI_SUCCESS; 29633859Sml29623 29646495Sspeer if (isLDOMguest(nxgep)) 29656495Sspeer return (NXGE_OK); 29666495Sspeer 29673859Sml29623 handle = nxgep->npi_handle; 29683859Sml29623 29693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 29703859Sml29623 nxgep->mac.portnum)); 29713859Sml29623 29723859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 29733859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 29743859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 29753859Sml29623 goto fail; 29763859Sml29623 } else { 29773859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 29783859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 29793859Sml29623 goto fail; 29803859Sml29623 } 29813859Sml29623 29823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 29833859Sml29623 nxgep->mac.portnum)); 29843859Sml29623 return (NXGE_OK); 29853859Sml29623 fail: 29863859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 29873859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 29883859Sml29623 nxgep->mac.portnum)); 29893859Sml29623 return (NXGE_ERROR | rs); 29903859Sml29623 } 29913859Sml29623 29923859Sml29623 /* Enable RXMAC */ 29933859Sml29623 29943859Sml29623 nxge_status_t 29953859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 29963859Sml29623 { 29973859Sml29623 npi_handle_t handle; 29983859Sml29623 uint8_t portn; 29993859Sml29623 npi_status_t rs = NPI_SUCCESS; 30003859Sml29623 nxge_status_t status = NXGE_OK; 30013859Sml29623 30026495Sspeer /* This is a service-domain-only activity. */ 30036495Sspeer if (isLDOMguest(nxgep)) 30046495Sspeer return (status); 30056495Sspeer 30063859Sml29623 handle = nxgep->npi_handle; 30073859Sml29623 portn = nxgep->mac.portnum; 30083859Sml29623 30093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 30103859Sml29623 portn)); 30113859Sml29623 30123859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 30133859Sml29623 goto fail; 30143859Sml29623 30153859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 30163859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 30176495Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 30183859Sml29623 goto fail; 30193859Sml29623 } else { 30203859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 30216495Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 30223859Sml29623 goto fail; 30233859Sml29623 } 30243859Sml29623 30256495Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30266495Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 30273859Sml29623 30283859Sml29623 return (NXGE_OK); 30293859Sml29623 fail: 30303859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 30316495Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 30323859Sml29623 30333859Sml29623 if (rs != NPI_SUCCESS) 30343859Sml29623 return (NXGE_ERROR | rs); 30353859Sml29623 else 30363859Sml29623 return (status); 30373859Sml29623 } 30383859Sml29623 30393859Sml29623 /* Disable RXMAC */ 30403859Sml29623 30413859Sml29623 nxge_status_t 30423859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 30433859Sml29623 { 30443859Sml29623 npi_handle_t handle; 30453859Sml29623 uint8_t portn; 30463859Sml29623 npi_status_t rs = NPI_SUCCESS; 30473859Sml29623 30486495Sspeer /* If we are a guest domain driver, don't bother. */ 30496495Sspeer if (isLDOMguest(nxgep)) 30506495Sspeer return (NXGE_OK); 30516495Sspeer 30523859Sml29623 handle = nxgep->npi_handle; 30533859Sml29623 portn = nxgep->mac.portnum; 30543859Sml29623 30553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 30563859Sml29623 portn)); 30573859Sml29623 30583859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 30593859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 30603859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 30613859Sml29623 goto fail; 30623859Sml29623 } else { 30633859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 30643859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 30653859Sml29623 goto fail; 30663859Sml29623 } 30673859Sml29623 30683859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 30693859Sml29623 portn)); 30703859Sml29623 return (NXGE_OK); 30713859Sml29623 fail: 30723859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 30733859Sml29623 "nxgep_rx_mac_disable: ", 30743859Sml29623 "Failed to disable port<%d> RxMAC", 30753859Sml29623 portn)); 30763859Sml29623 30773859Sml29623 return (NXGE_ERROR | rs); 30783859Sml29623 } 30793859Sml29623 30803859Sml29623 /* Reset TXMAC */ 30813859Sml29623 30823859Sml29623 nxge_status_t 30833859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 30843859Sml29623 { 30853859Sml29623 npi_handle_t handle; 30863859Sml29623 uint8_t portn; 30873859Sml29623 npi_status_t rs = NPI_SUCCESS; 30883859Sml29623 30893859Sml29623 handle = nxgep->npi_handle; 30903859Sml29623 portn = nxgep->mac.portnum; 30913859Sml29623 30923859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 30933859Sml29623 portn)); 30943859Sml29623 30953859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 30963859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 30973859Sml29623 != NPI_SUCCESS) 30983859Sml29623 goto fail; 30993859Sml29623 } else { 31003859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 31013859Sml29623 != NPI_SUCCESS) 31023859Sml29623 goto fail; 31033859Sml29623 } 31043859Sml29623 31053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 31063859Sml29623 portn)); 31073859Sml29623 31083859Sml29623 return (NXGE_OK); 31093859Sml29623 fail: 31103859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 31113859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 31123859Sml29623 portn)); 31133859Sml29623 31143859Sml29623 return (NXGE_ERROR | rs); 31153859Sml29623 } 31163859Sml29623 31173859Sml29623 /* Reset RXMAC */ 31183859Sml29623 31193859Sml29623 nxge_status_t 31203859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 31213859Sml29623 { 31223859Sml29623 npi_handle_t handle; 31233859Sml29623 uint8_t portn; 31243859Sml29623 npi_status_t rs = NPI_SUCCESS; 31253859Sml29623 31263859Sml29623 handle = nxgep->npi_handle; 31273859Sml29623 portn = nxgep->mac.portnum; 31283859Sml29623 31293859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 31303859Sml29623 portn)); 31313859Sml29623 31323859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 31333859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 31343859Sml29623 != NPI_SUCCESS) 31353859Sml29623 goto fail; 31363859Sml29623 } else { 31373859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 31383859Sml29623 != NPI_SUCCESS) 31393859Sml29623 goto fail; 31403859Sml29623 } 31413859Sml29623 31423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 31433859Sml29623 portn)); 31443859Sml29623 31453859Sml29623 return (NXGE_OK); 31463859Sml29623 fail: 31473859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 31483859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 31493859Sml29623 portn)); 31503859Sml29623 return (NXGE_ERROR | rs); 31513859Sml29623 } 31523859Sml29623 31534732Sdavemq /* 10G fiber link interrupt start routine */ 31544732Sdavemq 31554732Sdavemq static nxge_status_t 31564732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 31574732Sdavemq { 31584732Sdavemq npi_status_t rs = NPI_SUCCESS; 31594732Sdavemq uint8_t portn = nxgep->mac.portnum; 31604732Sdavemq 31614732Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 31624732Sdavemq 31634732Sdavemq if (rs != NPI_SUCCESS) 31644732Sdavemq return (NXGE_ERROR | rs); 31654732Sdavemq else 31664732Sdavemq return (NXGE_OK); 31674732Sdavemq } 31684732Sdavemq 31694732Sdavemq /* 10G fiber link interrupt stop routine */ 31704732Sdavemq 31714732Sdavemq static nxge_status_t 31724732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 31734732Sdavemq { 31744732Sdavemq npi_status_t rs = NPI_SUCCESS; 31754732Sdavemq uint8_t portn = nxgep->mac.portnum; 31764732Sdavemq 31774732Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 31784732Sdavemq 31794732Sdavemq if (rs != NPI_SUCCESS) 31804732Sdavemq return (NXGE_ERROR | rs); 31814732Sdavemq else 31824732Sdavemq return (NXGE_OK); 31834732Sdavemq } 31844732Sdavemq 31854732Sdavemq /* 1G fiber link interrupt start routine */ 31864732Sdavemq 31874732Sdavemq static nxge_status_t 31884732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 31894732Sdavemq { 31904732Sdavemq npi_status_t rs = NPI_SUCCESS; 31914732Sdavemq uint8_t portn = nxgep->mac.portnum; 31924732Sdavemq 31934732Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 31944732Sdavemq if (rs != NPI_SUCCESS) 31954732Sdavemq return (NXGE_ERROR | rs); 31964732Sdavemq else 31974732Sdavemq return (NXGE_OK); 31984732Sdavemq } 31994732Sdavemq 32004732Sdavemq /* 1G fiber link interrupt stop routine */ 32014732Sdavemq 32024732Sdavemq static nxge_status_t 32034732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 32044732Sdavemq { 32054732Sdavemq npi_status_t rs = NPI_SUCCESS; 32064732Sdavemq uint8_t portn = nxgep->mac.portnum; 32074732Sdavemq 32084732Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 32094732Sdavemq 32104732Sdavemq if (rs != NPI_SUCCESS) 32114732Sdavemq return (NXGE_ERROR | rs); 32124732Sdavemq else 32134732Sdavemq return (NXGE_OK); 32144732Sdavemq } 32154732Sdavemq 32164732Sdavemq /* 1G copper link interrupt start routine */ 32174732Sdavemq 32184732Sdavemq static nxge_status_t 32194732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 32204732Sdavemq { 32214732Sdavemq npi_status_t rs = NPI_SUCCESS; 32224732Sdavemq uint8_t portn = nxgep->mac.portnum; 32234732Sdavemq 32244732Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 32255203Ssbehera MII_STATUS, MII_STATUS_LINKUP); 32264732Sdavemq 32274732Sdavemq if (rs != NPI_SUCCESS) 32284732Sdavemq return (NXGE_ERROR | rs); 32294732Sdavemq else 32304732Sdavemq return (NXGE_OK); 32314732Sdavemq } 32324732Sdavemq 32334732Sdavemq /* 1G copper link interrupt stop routine */ 32344732Sdavemq 32354732Sdavemq static nxge_status_t 32364732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 32374732Sdavemq { 32384732Sdavemq npi_status_t rs = NPI_SUCCESS; 32394732Sdavemq uint8_t portn = nxgep->mac.portnum; 32404732Sdavemq 32414732Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 32424732Sdavemq 32434732Sdavemq if (rs != NPI_SUCCESS) 32444732Sdavemq return (NXGE_ERROR | rs); 32454732Sdavemq else 32464732Sdavemq return (NXGE_OK); 32474732Sdavemq } 32484732Sdavemq 32494732Sdavemq /* Enable/Disable Link Status change interrupt */ 32503859Sml29623 32513859Sml29623 nxge_status_t 32523859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 32533859Sml29623 { 32544732Sdavemq uint8_t portn; 32554732Sdavemq nxge_status_t status = NXGE_OK; 32563859Sml29623 32573859Sml29623 portn = nxgep->mac.portnum; 32583859Sml29623 32593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 32604732Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 32614732Sdavemq return (NXGE_OK); 32624732Sdavemq 32634732Sdavemq if (enable == LINK_INTR_START) 32644732Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 32654732Sdavemq else if (enable == LINK_INTR_STOP) 32664732Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 32674732Sdavemq if (status != NXGE_OK) 32684732Sdavemq goto fail; 32693859Sml29623 32703859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 32713859Sml29623 32723859Sml29623 return (NXGE_OK); 32733859Sml29623 fail: 32743859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 32753859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 32763859Sml29623 portn)); 32773859Sml29623 32784732Sdavemq return (status); 32793859Sml29623 } 32803859Sml29623 32813859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 32823859Sml29623 32833859Sml29623 nxge_status_t 32843859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 32853859Sml29623 { 32863859Sml29623 p_nxge_param_t param_arr; 32873859Sml29623 p_nxge_stats_t statsp; 32883859Sml29623 uint8_t xcvr_portn; 32893859Sml29623 p_mii_regs_t mii_regs; 32903859Sml29623 mii_bmcr_t bmcr; 32913859Sml29623 mii_bmsr_t bmsr; 32923859Sml29623 mii_anar_t anar; 32933859Sml29623 mii_gcr_t gcr; 32943859Sml29623 mii_esr_t esr; 32953859Sml29623 mii_aux_ctl_t bcm5464r_aux; 32963859Sml29623 int status = NXGE_OK; 32973859Sml29623 32983859Sml29623 uint_t delay; 32993859Sml29623 33003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 33013859Sml29623 33023859Sml29623 param_arr = nxgep->param_arr; 33033859Sml29623 statsp = nxgep->statsp; 33043859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 33053859Sml29623 33063859Sml29623 mii_regs = NULL; 33073859Sml29623 33083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 33093859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 33103859Sml29623 33113859Sml29623 /* 33125196Ssbehera * The mif phy mode may be connected to either a copper link 33135196Ssbehera * or fiber link. Read the mode control register to get the fiber 33145196Ssbehera * configuration if it is hard-wired to fiber link. 33155196Ssbehera */ 33165196Ssbehera (void) nxge_mii_get_link_mode(nxgep); 33175196Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 33185196Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 33195196Ssbehera } 33205196Ssbehera 33215196Ssbehera /* 33223859Sml29623 * Reset the transceiver. 33233859Sml29623 */ 33243859Sml29623 delay = 0; 33253859Sml29623 bmcr.value = 0; 33263859Sml29623 bmcr.bits.reset = 1; 33273859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 33285125Sjoycey #if defined(__i386) 33295125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 33305125Sjoycey #else 33313859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 33325125Sjoycey #endif 33333859Sml29623 goto fail; 33343859Sml29623 do { 33353859Sml29623 drv_usecwait(500); 33363859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 33375125Sjoycey #if defined(__i386) 33385125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 33395125Sjoycey #else 33403859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 33415125Sjoycey #endif 33423859Sml29623 != NXGE_OK) 33433859Sml29623 goto fail; 33443859Sml29623 delay++; 33453859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 33463859Sml29623 if (delay == 1000) { 33473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 33483859Sml29623 goto fail; 33493859Sml29623 } 33503859Sml29623 33513859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 33525125Sjoycey #if defined(__i386) 33535125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 33545125Sjoycey #else 33553859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 33565125Sjoycey #endif 33573859Sml29623 &bmsr.value)) != NXGE_OK) 33583859Sml29623 goto fail; 33593859Sml29623 33603859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 33613859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 33623859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 33633859Sml29623 param_arr[param_anar_100hdx].value = 0; 33643859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 33653859Sml29623 param_arr[param_anar_10hdx].value = 0; 33663859Sml29623 33673859Sml29623 /* 33683859Sml29623 * Initialize the xcvr statistics. 33693859Sml29623 */ 33703859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 33713859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 33723859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 33733859Sml29623 statsp->mac_stats.cap_100hdx = 0; 33743859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 33753859Sml29623 statsp->mac_stats.cap_10hdx = 0; 33763859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 33773859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 33783859Sml29623 33793859Sml29623 /* 33803859Sml29623 * Initialise the xcvr advertised capability statistics. 33813859Sml29623 */ 33823859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 33833859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 33843859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 33853859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 33863859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 33873859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 33883859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 33893859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 33903859Sml29623 statsp->mac_stats.adv_cap_asmpause = 33913859Sml29623 param_arr[param_anar_asmpause].value; 33923859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 33933859Sml29623 33943859Sml29623 33953859Sml29623 /* 33963859Sml29623 * Check for extended status just in case we're 33973859Sml29623 * running a Gigibit phy. 33983859Sml29623 */ 33993859Sml29623 if (bmsr.bits.extend_status) { 34003859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 34015125Sjoycey #if defined(__i386) 34025125Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 34035125Sjoycey #else 34043859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 34055125Sjoycey #endif 34063859Sml29623 != NXGE_OK) 34073859Sml29623 goto fail; 34083859Sml29623 param_arr[param_anar_1000fdx].value &= 34093859Sml29623 esr.bits.link_1000fdx; 34103859Sml29623 param_arr[param_anar_1000hdx].value = 0; 34113859Sml29623 34123859Sml29623 statsp->mac_stats.cap_1000fdx = 34133859Sml29623 (esr.bits.link_1000Xfdx || 34143859Sml29623 esr.bits.link_1000fdx); 34153859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 34163859Sml29623 } else { 34173859Sml29623 param_arr[param_anar_1000fdx].value = 0; 34183859Sml29623 param_arr[param_anar_1000hdx].value = 0; 34193859Sml29623 } 34203859Sml29623 34213859Sml29623 /* 34223859Sml29623 * Initialize 1G Statistics once the capability is established. 34233859Sml29623 */ 34243859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 34253859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 34263859Sml29623 34273859Sml29623 /* 34283859Sml29623 * Initialise the link statistics. 34293859Sml29623 */ 34303859Sml29623 statsp->mac_stats.link_T4 = 0; 34313859Sml29623 statsp->mac_stats.link_asmpause = 0; 34323859Sml29623 statsp->mac_stats.link_pause = 0; 34333859Sml29623 statsp->mac_stats.link_speed = 0; 34343859Sml29623 statsp->mac_stats.link_duplex = 0; 34353859Sml29623 statsp->mac_stats.link_up = 0; 34363859Sml29623 34373859Sml29623 /* 34383859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 34393859Sml29623 */ 34403859Sml29623 bmcr.value = 0; 34413859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 34425125Sjoycey #if defined(__i386) 34435125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 34445125Sjoycey #else 34453859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 34465125Sjoycey #endif 34473859Sml29623 goto fail; 34483859Sml29623 34493859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 34503859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 34513859Sml29623 bmcr.bits.loopback = 1; 34523859Sml29623 bmcr.bits.enable_autoneg = 0; 34533859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 34543859Sml29623 bmcr.bits.speed_1000_sel = 1; 34553859Sml29623 bmcr.bits.duplex_mode = 1; 34563859Sml29623 param_arr[param_autoneg].value = 0; 34573859Sml29623 } else { 34583859Sml29623 bmcr.bits.loopback = 0; 34593859Sml29623 } 34603859Sml29623 34613859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 34623859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 34633859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 34643859Sml29623 param_arr[param_autoneg].value = 0; 34653859Sml29623 bcm5464r_aux.value = 0; 34663859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 34673859Sml29623 bcm5464r_aux.bits.write_1 = 1; 34683859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 34693859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 34703859Sml29623 != NXGE_OK) 34713859Sml29623 goto fail; 34723859Sml29623 } 34733859Sml29623 34743859Sml29623 if (param_arr[param_autoneg].value) { 34753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 34763859Sml29623 "Restarting Auto-negotiation.")); 34773859Sml29623 /* 34783859Sml29623 * Setup our Auto-negotiation advertisement register. 34793859Sml29623 */ 34803859Sml29623 anar.value = 0; 34813859Sml29623 anar.bits.selector = 1; 34823859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 34833859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 34843859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 34853859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 34863859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 34873859Sml29623 anar.bits.cap_asmpause = 0; 34883859Sml29623 anar.bits.cap_pause = 0; 34893859Sml29623 if (param_arr[param_anar_1000fdx].value || 34903859Sml29623 param_arr[param_anar_100fdx].value || 34913859Sml29623 param_arr[param_anar_10fdx].value) { 34923859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 34933859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 34943859Sml29623 } 34953859Sml29623 34963859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 34975125Sjoycey #if defined(__i386) 34985125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 34995125Sjoycey #else 35003859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 35015125Sjoycey #endif 35023859Sml29623 != NXGE_OK) 35033859Sml29623 goto fail; 35043859Sml29623 if (bmsr.bits.extend_status) { 35053859Sml29623 gcr.value = 0; 35063859Sml29623 gcr.bits.ms_mode_en = 35073859Sml29623 param_arr[param_master_cfg_enable].value; 35083859Sml29623 gcr.bits.master = 35093859Sml29623 param_arr[param_master_cfg_value].value; 35103859Sml29623 gcr.bits.link_1000fdx = 35113859Sml29623 param_arr[param_anar_1000fdx].value; 35123859Sml29623 gcr.bits.link_1000hdx = 35133859Sml29623 param_arr[param_anar_1000hdx].value; 35143859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 35155125Sjoycey #if defined(__i386) 35165125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 35175125Sjoycey #else 35183859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 35195125Sjoycey #endif 35203859Sml29623 != NXGE_OK) 35213859Sml29623 goto fail; 35223859Sml29623 } 35233859Sml29623 35243859Sml29623 bmcr.bits.enable_autoneg = 1; 35253859Sml29623 bmcr.bits.restart_autoneg = 1; 35263859Sml29623 35273859Sml29623 } else { 35283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 35293859Sml29623 bmcr.bits.speed_1000_sel = 35303859Sml29623 param_arr[param_anar_1000fdx].value | 35313859Sml29623 param_arr[param_anar_1000hdx].value; 35323859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 35333859Sml29623 (param_arr[param_anar_100fdx].value | 35343859Sml29623 param_arr[param_anar_100hdx].value); 35353859Sml29623 if (bmcr.bits.speed_1000_sel) { 35363859Sml29623 statsp->mac_stats.link_speed = 1000; 35373859Sml29623 gcr.value = 0; 35383859Sml29623 gcr.bits.ms_mode_en = 35393859Sml29623 param_arr[param_master_cfg_enable].value; 35403859Sml29623 gcr.bits.master = 35413859Sml29623 param_arr[param_master_cfg_value].value; 35423859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 35435125Sjoycey #if defined(__i386) 35445125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 35455125Sjoycey #else 35463859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 35475125Sjoycey #endif 35483859Sml29623 gcr.value)) 35493859Sml29623 != NXGE_OK) 35503859Sml29623 goto fail; 35513859Sml29623 if (param_arr[param_anar_1000fdx].value) { 35523859Sml29623 bmcr.bits.duplex_mode = 1; 35533859Sml29623 statsp->mac_stats.link_duplex = 2; 35543859Sml29623 } else 35553859Sml29623 statsp->mac_stats.link_duplex = 1; 35563859Sml29623 } else if (bmcr.bits.speed_sel) { 35573859Sml29623 statsp->mac_stats.link_speed = 100; 35583859Sml29623 if (param_arr[param_anar_100fdx].value) { 35593859Sml29623 bmcr.bits.duplex_mode = 1; 35603859Sml29623 statsp->mac_stats.link_duplex = 2; 35613859Sml29623 } else 35623859Sml29623 statsp->mac_stats.link_duplex = 1; 35633859Sml29623 } else { 35643859Sml29623 statsp->mac_stats.link_speed = 10; 35653859Sml29623 if (param_arr[param_anar_10fdx].value) { 35663859Sml29623 bmcr.bits.duplex_mode = 1; 35673859Sml29623 statsp->mac_stats.link_duplex = 2; 35683859Sml29623 } else 35693859Sml29623 statsp->mac_stats.link_duplex = 1; 35703859Sml29623 } 35713859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 35723859Sml29623 statsp->mac_stats.link_asmpause = 35733859Sml29623 statsp->mac_stats.cap_asmpause; 35743859Sml29623 statsp->mac_stats.link_pause = 35753859Sml29623 statsp->mac_stats.cap_pause; 35763859Sml29623 } 35773859Sml29623 35783859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 35793859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 35803859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 35813859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 35823859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 35833859Sml29623 gcr.value = 0; 35843859Sml29623 gcr.bits.ms_mode_en = 1; 35853859Sml29623 gcr.bits.master = 1; 35863859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 35875125Sjoycey #if defined(__i386) 35885125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 35895125Sjoycey #else 35903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 35915125Sjoycey #endif 35923859Sml29623 gcr.value)) 35933859Sml29623 != NXGE_OK) 35943859Sml29623 goto fail; 35953859Sml29623 bmcr.value = 0; 35963859Sml29623 bmcr.bits.speed_1000_sel = 1; 35973859Sml29623 statsp->mac_stats.link_speed = 1000; 35983859Sml29623 } else if (statsp->port_stats.lb_mode 35993859Sml29623 == nxge_lb_ext100) { 36003859Sml29623 /* BCM5464R 100mbps external loopback mode */ 36013859Sml29623 bmcr.value = 0; 36023859Sml29623 bmcr.bits.speed_sel = 1; 36033859Sml29623 bmcr.bits.duplex_mode = 1; 36043859Sml29623 statsp->mac_stats.link_speed = 100; 36053859Sml29623 } else if (statsp->port_stats.lb_mode 36063859Sml29623 == nxge_lb_ext10) { 36073859Sml29623 /* BCM5464R 10mbps external loopback mode */ 36083859Sml29623 bmcr.value = 0; 36093859Sml29623 bmcr.bits.duplex_mode = 1; 36103859Sml29623 statsp->mac_stats.link_speed = 10; 36113859Sml29623 } 36123859Sml29623 } 36133859Sml29623 } 36143859Sml29623 36153859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 36165125Sjoycey #if defined(__i386) 36175125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 36185125Sjoycey #else 36193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 36205125Sjoycey #endif 36213859Sml29623 bmcr.value)) != NXGE_OK) 36223859Sml29623 goto fail; 36233859Sml29623 36243859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 36255125Sjoycey #if defined(__i386) 36265125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 36275125Sjoycey #else 36283859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 36295125Sjoycey #endif 36303859Sml29623 goto fail; 36313859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 36323859Sml29623 36333859Sml29623 /* 36343859Sml29623 * Initialize the xcvr status kept in the context structure. 36353859Sml29623 */ 36363859Sml29623 nxgep->soft_bmsr.value = 0; 36373859Sml29623 36383859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 36395125Sjoycey #if defined(__i386) 36405125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 36415125Sjoycey #else 36423859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 36435125Sjoycey #endif 36443859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 36453859Sml29623 goto fail; 36463859Sml29623 36473859Sml29623 statsp->mac_stats.xcvr_inits++; 36483859Sml29623 nxgep->bmsr.value = 0; 36493859Sml29623 36503859Sml29623 fail: 36513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36523859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 36533859Sml29623 return (status); 36543859Sml29623 } 36553859Sml29623 36565196Ssbehera nxge_status_t 36575196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 36585196Ssbehera { 36595196Ssbehera p_nxge_param_t param_arr; 36605196Ssbehera p_nxge_stats_t statsp; 36615196Ssbehera uint8_t xcvr_portn; 36625196Ssbehera p_mii_regs_t mii_regs; 36635196Ssbehera mii_bmcr_t bmcr; 36645196Ssbehera mii_bmsr_t bmsr; 36655196Ssbehera mii_gcr_t gcr; 36665196Ssbehera mii_esr_t esr; 36675196Ssbehera mii_aux_ctl_t bcm5464r_aux; 36685196Ssbehera int status = NXGE_OK; 36695196Ssbehera 36705196Ssbehera uint_t delay; 36715196Ssbehera 36725196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 36735196Ssbehera 36745196Ssbehera param_arr = nxgep->param_arr; 36755196Ssbehera statsp = nxgep->statsp; 36765196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 36775196Ssbehera 36785196Ssbehera mii_regs = NULL; 36795196Ssbehera 36805196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36815196Ssbehera "nxge_mii_xcvr_fiber_init: " 36825196Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 36835196Ssbehera 36845196Ssbehera /* 36855196Ssbehera * Reset the transceiver. 36865196Ssbehera */ 36875196Ssbehera delay = 0; 36885196Ssbehera bmcr.value = 0; 36895196Ssbehera bmcr.bits.reset = 1; 36905196Ssbehera 36915196Ssbehera #if defined(__i386) 36925196Ssbehera 36935196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 36945196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 36955196Ssbehera goto fail; 36965196Ssbehera #else 36975196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 36985196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 36995196Ssbehera goto fail; 37005196Ssbehera #endif 37015196Ssbehera do { 37025196Ssbehera drv_usecwait(500); 37035196Ssbehera #if defined(__i386) 37045196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37055196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 37065196Ssbehera != NXGE_OK) 37075196Ssbehera goto fail; 37085196Ssbehera #else 37095196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37105196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 37115196Ssbehera != NXGE_OK) 37125196Ssbehera goto fail; 37135196Ssbehera #endif 37145196Ssbehera delay++; 37155196Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 37165196Ssbehera if (delay == 1000) { 37175196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 37185196Ssbehera goto fail; 37195196Ssbehera } 37205196Ssbehera 37215196Ssbehera #if defined(__i386) 37225196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37235196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 37245196Ssbehera goto fail; 37255196Ssbehera #else 37265196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37275196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 37285196Ssbehera goto fail; 37295196Ssbehera #endif 37305196Ssbehera 37315196Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 37325196Ssbehera param_arr[param_anar_100T4].value = 0; 37335196Ssbehera param_arr[param_anar_100fdx].value = 0; 37345196Ssbehera param_arr[param_anar_100hdx].value = 0; 37355196Ssbehera param_arr[param_anar_10fdx].value = 0; 37365196Ssbehera param_arr[param_anar_10hdx].value = 0; 37375196Ssbehera 37385196Ssbehera /* 37395196Ssbehera * Initialize the xcvr statistics. 37405196Ssbehera */ 37415196Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 37425196Ssbehera statsp->mac_stats.cap_100T4 = 0; 37435196Ssbehera statsp->mac_stats.cap_100fdx = 0; 37445196Ssbehera statsp->mac_stats.cap_100hdx = 0; 37455196Ssbehera statsp->mac_stats.cap_10fdx = 0; 37465196Ssbehera statsp->mac_stats.cap_10hdx = 0; 37475196Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 37485196Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 37495196Ssbehera 37505196Ssbehera /* 37515196Ssbehera * Initialize the xcvr advertised capability statistics. 37525196Ssbehera */ 37535196Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 37545196Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 37555196Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 37565196Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 37575196Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 37585196Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 37595196Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 37605196Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 37615196Ssbehera statsp->mac_stats.adv_cap_asmpause = 37625196Ssbehera param_arr[param_anar_asmpause].value; 37635196Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 37645196Ssbehera 37655196Ssbehera /* 37665196Ssbehera * Check for extended status just in case we're 37675196Ssbehera * running a Gigibit phy. 37685196Ssbehera */ 37695196Ssbehera if (bmsr.bits.extend_status) { 37705196Ssbehera #if defined(__i386) 37715196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37725196Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 37735196Ssbehera NXGE_OK) 37745196Ssbehera goto fail; 37755196Ssbehera #else 37765196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 37775196Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 37785196Ssbehera NXGE_OK) 37795196Ssbehera goto fail; 37805196Ssbehera #endif 37815196Ssbehera param_arr[param_anar_1000fdx].value &= 37825196Ssbehera esr.bits.link_1000fdx; 37835196Ssbehera param_arr[param_anar_1000hdx].value = 0; 37845196Ssbehera 37855196Ssbehera statsp->mac_stats.cap_1000fdx = 37865196Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 37875196Ssbehera statsp->mac_stats.cap_1000hdx = 0; 37885196Ssbehera } else { 37895196Ssbehera param_arr[param_anar_1000fdx].value = 0; 37905196Ssbehera param_arr[param_anar_1000hdx].value = 0; 37915196Ssbehera } 37925196Ssbehera 37935196Ssbehera /* 37945196Ssbehera * Initialize 1G Statistics once the capability is established. 37955196Ssbehera */ 37965196Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 37975196Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 37985196Ssbehera 37995196Ssbehera /* 38005196Ssbehera * Initialize the link statistics. 38015196Ssbehera */ 38025196Ssbehera statsp->mac_stats.link_T4 = 0; 38035196Ssbehera statsp->mac_stats.link_asmpause = 0; 38045196Ssbehera statsp->mac_stats.link_pause = 0; 38055196Ssbehera statsp->mac_stats.link_speed = 0; 38065196Ssbehera statsp->mac_stats.link_duplex = 0; 38075196Ssbehera statsp->mac_stats.link_up = 0; 38085196Ssbehera 38095196Ssbehera /* 38105196Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 38115196Ssbehera */ 38125196Ssbehera bmcr.value = 0; 38135196Ssbehera #if defined(__i386) 38145196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38155196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 38165196Ssbehera goto fail; 38175196Ssbehera #else 38185196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38195196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 38205196Ssbehera goto fail; 38215196Ssbehera #endif 38225196Ssbehera 38235196Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 38245196Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 38255196Ssbehera bmcr.bits.loopback = 1; 38265196Ssbehera bmcr.bits.enable_autoneg = 0; 38275196Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 38285196Ssbehera bmcr.bits.speed_1000_sel = 1; 38295196Ssbehera bmcr.bits.duplex_mode = 1; 38305196Ssbehera param_arr[param_autoneg].value = 0; 38315196Ssbehera } else { 38325196Ssbehera bmcr.bits.loopback = 0; 38335196Ssbehera } 38345196Ssbehera 38355196Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 38365196Ssbehera param_arr[param_autoneg].value = 0; 38375196Ssbehera bcm5464r_aux.value = 0; 38385196Ssbehera bcm5464r_aux.bits.ext_lb = 1; 38395196Ssbehera bcm5464r_aux.bits.write_1 = 1; 38405196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38415196Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 38425196Ssbehera goto fail; 38435196Ssbehera } 38445196Ssbehera 38455196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 38465196Ssbehera bmcr.bits.speed_1000_sel = 1; 38475196Ssbehera bmcr.bits.speed_sel = 0; 38485196Ssbehera bmcr.bits.duplex_mode = 1; 38495196Ssbehera statsp->mac_stats.link_speed = 1000; 38505196Ssbehera statsp->mac_stats.link_duplex = 2; 38515196Ssbehera 38525196Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 38535196Ssbehera /* BCM5464R 1000mbps external loopback mode */ 38545196Ssbehera gcr.value = 0; 38555196Ssbehera gcr.bits.ms_mode_en = 1; 38565196Ssbehera gcr.bits.master = 1; 38575196Ssbehera #if defined(__i386) 38585196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38595196Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 38605196Ssbehera gcr.value)) != NXGE_OK) 38615196Ssbehera goto fail; 38625196Ssbehera #else 38635196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38645196Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 38655196Ssbehera gcr.value)) != NXGE_OK) 38665196Ssbehera goto fail; 38675196Ssbehera #endif 38685196Ssbehera bmcr.value = 0; 38695196Ssbehera bmcr.bits.speed_1000_sel = 1; 38705196Ssbehera statsp->mac_stats.link_speed = 1000; 38715196Ssbehera } 38725196Ssbehera 38735196Ssbehera #if defined(__i386) 38745196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38755196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 38765196Ssbehera bmcr.value)) != NXGE_OK) 38775196Ssbehera goto fail; 38785196Ssbehera #else 38795196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 38805196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 38815196Ssbehera bmcr.value)) != NXGE_OK) 38825196Ssbehera goto fail; 38835196Ssbehera #endif 38845196Ssbehera 38855196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38865196Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 38875196Ssbehera bmcr.value)); 38885196Ssbehera 38895196Ssbehera #if defined(__i386) 38905196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 38915196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 38925196Ssbehera goto fail; 38935196Ssbehera #else 38945196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 38955196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 38965196Ssbehera goto fail; 38975196Ssbehera #endif 38985196Ssbehera 38995196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39005196Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 39015196Ssbehera 39025196Ssbehera /* 39035196Ssbehera * Initialize the xcvr status kept in the context structure. 39045196Ssbehera */ 39055196Ssbehera nxgep->soft_bmsr.value = 0; 39065196Ssbehera #if defined(__i386) 39075196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 39085196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 39095196Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 39105196Ssbehera goto fail; 39115196Ssbehera #else 39125196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 39135196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 39145196Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 39155196Ssbehera goto fail; 39165196Ssbehera #endif 39175196Ssbehera 39185196Ssbehera statsp->mac_stats.xcvr_inits++; 39195196Ssbehera nxgep->bmsr.value = 0; 39205196Ssbehera 39215196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39225196Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 39235196Ssbehera return (status); 39245196Ssbehera 39255196Ssbehera fail: 39265196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39275196Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 39285196Ssbehera return (status); 39295196Ssbehera } 39305196Ssbehera 39313859Sml29623 /* Read from a MII compliant register */ 39323859Sml29623 39333859Sml29623 nxge_status_t 39343859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 39353859Sml29623 uint16_t *value) 39363859Sml29623 { 39373859Sml29623 npi_status_t rs = NPI_SUCCESS; 39383859Sml29623 39393859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 39403859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 39413859Sml29623 39426075Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 39433859Sml29623 39445196Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 39455196Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 39463859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 39473859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 39483859Sml29623 goto fail; 39494977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 39504977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 39513859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 39523859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 39533859Sml29623 goto fail; 39543859Sml29623 } else 39553859Sml29623 goto fail; 39563859Sml29623 39576075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 39583859Sml29623 39593859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 39603859Sml29623 "xcvr_reg<%d> value=0x%x", 39613859Sml29623 xcvr_portn, xcvr_reg, *value)); 39623859Sml29623 return (NXGE_OK); 39633859Sml29623 fail: 39646075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 39653859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39663859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 39673859Sml29623 xcvr_portn)); 39683859Sml29623 39693859Sml29623 return (NXGE_ERROR | rs); 39703859Sml29623 } 39713859Sml29623 39723859Sml29623 /* Write to a MII compliant Register */ 39733859Sml29623 39743859Sml29623 nxge_status_t 39753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 39763859Sml29623 uint16_t value) 39773859Sml29623 { 39783859Sml29623 npi_status_t rs = NPI_SUCCESS; 39793859Sml29623 39803859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 39813859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 39823859Sml29623 value)); 39833859Sml29623 39846075Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 39853859Sml29623 39865196Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 39875196Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 39883859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 39893859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 39903859Sml29623 goto fail; 39914977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 39924977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 39933859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 39943859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 39953859Sml29623 goto fail; 39963859Sml29623 } else 39973859Sml29623 goto fail; 39983859Sml29623 39996075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40003859Sml29623 40013859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 40023859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 40033859Sml29623 return (NXGE_OK); 40043859Sml29623 fail: 40056075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40063859Sml29623 40073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40083859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 40093859Sml29623 xcvr_portn)); 40103859Sml29623 40113859Sml29623 return (NXGE_ERROR | rs); 40123859Sml29623 } 40133859Sml29623 40143859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 40153859Sml29623 40163859Sml29623 nxge_status_t 40173859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 40183859Sml29623 uint16_t xcvr_reg, uint16_t *value) 40193859Sml29623 { 40203859Sml29623 npi_status_t rs = NPI_SUCCESS; 40213859Sml29623 40223859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 40233859Sml29623 xcvr_portn)); 40243859Sml29623 40255780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 40263859Sml29623 40273859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 40283859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 40293859Sml29623 goto fail; 40303859Sml29623 40315780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40323859Sml29623 40333859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 40343859Sml29623 xcvr_portn)); 40353859Sml29623 return (NXGE_OK); 40363859Sml29623 fail: 40375780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40383859Sml29623 40393859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40403859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 40413859Sml29623 xcvr_portn)); 40423859Sml29623 40433859Sml29623 return (NXGE_ERROR | rs); 40443859Sml29623 } 40453859Sml29623 40463859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 40473859Sml29623 40483859Sml29623 nxge_status_t 40493859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 40503859Sml29623 uint16_t xcvr_reg, uint16_t value) 40513859Sml29623 { 40523859Sml29623 npi_status_t rs = NPI_SUCCESS; 40533859Sml29623 40543859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 40553859Sml29623 xcvr_portn)); 40563859Sml29623 40575780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 40583859Sml29623 40593859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 40603859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 40613859Sml29623 goto fail; 40623859Sml29623 40635780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40643859Sml29623 40653859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 40663859Sml29623 xcvr_portn)); 40673859Sml29623 return (NXGE_OK); 40683859Sml29623 fail: 40695780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 40703859Sml29623 40713859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40723859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 40733859Sml29623 xcvr_portn)); 40743859Sml29623 40753859Sml29623 return (NXGE_ERROR | rs); 40763859Sml29623 } 40773859Sml29623 40783859Sml29623 40793859Sml29623 /* Check MII to see if there is any link status change */ 40803859Sml29623 40813859Sml29623 nxge_status_t 40823859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 40833859Sml29623 nxge_link_state_t *link_up) 40843859Sml29623 { 40853859Sml29623 p_nxge_param_t param_arr; 40863859Sml29623 p_nxge_stats_t statsp; 40873859Sml29623 p_mii_regs_t mii_regs; 40883859Sml29623 p_mii_bmsr_t soft_bmsr; 40893859Sml29623 mii_anar_t anar; 40903859Sml29623 mii_anlpar_t anlpar; 40913859Sml29623 mii_anar_t an_common; 40923859Sml29623 mii_aner_t aner; 40933859Sml29623 mii_gsr_t gsr; 40943859Sml29623 nxge_status_t status = NXGE_OK; 40953859Sml29623 40963859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 40973859Sml29623 40983859Sml29623 mii_regs = NULL; 40993859Sml29623 param_arr = nxgep->param_arr; 41003859Sml29623 statsp = nxgep->statsp; 41013859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 41023859Sml29623 *link_up = LINK_NO_CHANGE; 41033859Sml29623 41045196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41055196Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 41065196Ssbehera bmsr.value, bmsr_ints.value)); 41075196Ssbehera 41083859Sml29623 if (bmsr_ints.bits.link_status) { 41095196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41105196Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 41115196Ssbehera bmsr.value, bmsr_ints.value)); 41123859Sml29623 if (bmsr.bits.link_status) { 41133859Sml29623 soft_bmsr->bits.link_status = 1; 41145196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41155196Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 41165196Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 41173859Sml29623 } else { 41183859Sml29623 statsp->mac_stats.link_up = 0; 41193859Sml29623 soft_bmsr->bits.link_status = 0; 41203859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41213859Sml29623 "Link down cable problem")); 41223859Sml29623 *link_up = LINK_IS_DOWN; 41233859Sml29623 } 41243859Sml29623 } 41253859Sml29623 41265196Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 41275196Ssbehera param_arr[param_autoneg].value) { 41283859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 41293859Sml29623 if (bmsr.bits.auto_neg_complete) 41303859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 41313859Sml29623 else 41323859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 41333859Sml29623 } 41343859Sml29623 if (soft_bmsr->bits.link_status == 0) { 41353859Sml29623 statsp->mac_stats.link_T4 = 0; 41363859Sml29623 statsp->mac_stats.link_speed = 0; 41373859Sml29623 statsp->mac_stats.link_duplex = 0; 41383859Sml29623 statsp->mac_stats.link_asmpause = 0; 41393859Sml29623 statsp->mac_stats.link_pause = 0; 41403859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 41413859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 41423859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 41433859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 41443859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 41453859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 41463859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 41473859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 41483859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 41493859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 41503859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 41513859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 41523859Sml29623 } 41533859Sml29623 } else 41543859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 41553859Sml29623 41563859Sml29623 if ((bmsr_ints.bits.link_status || 41573859Sml29623 bmsr_ints.bits.auto_neg_complete) && 41583859Sml29623 soft_bmsr->bits.link_status && 41593859Sml29623 soft_bmsr->bits.auto_neg_complete) { 41603859Sml29623 statsp->mac_stats.link_up = 1; 41615196Ssbehera 41625196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41635196Ssbehera "==> nxge_mii_check " 41645196Ssbehera "(auto negotiation complete or link up) " 41655196Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 41665196Ssbehera bmsr.value, bmsr_ints.value)); 41675196Ssbehera 41685196Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 41695196Ssbehera param_arr[param_autoneg].value) { 41703859Sml29623 if ((status = nxge_mii_read(nxgep, 41713859Sml29623 statsp->mac_stats.xcvr_portn, 41725125Sjoycey #if defined(__i386) 41735125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 41745125Sjoycey #else 41753859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 41765125Sjoycey #endif 41773859Sml29623 &anar.value)) != NXGE_OK) 41783859Sml29623 goto fail; 41793859Sml29623 if ((status = nxge_mii_read(nxgep, 41803859Sml29623 statsp->mac_stats.xcvr_portn, 41815125Sjoycey #if defined(__i386) 41825125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 41835125Sjoycey #else 41843859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 41855125Sjoycey #endif 41863859Sml29623 &anlpar.value)) != NXGE_OK) 41873859Sml29623 goto fail; 41883859Sml29623 if ((status = nxge_mii_read(nxgep, 41893859Sml29623 statsp->mac_stats.xcvr_portn, 41905125Sjoycey #if defined(__i386) 41915125Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 41925125Sjoycey #else 41933859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 41945125Sjoycey #endif 41953859Sml29623 &aner.value)) != NXGE_OK) 41963859Sml29623 goto fail; 41973859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 41983859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 41993859Sml29623 statsp->mac_stats.lp_cap_100fdx = 42003859Sml29623 anlpar.bits.cap_100fdx; 42013859Sml29623 statsp->mac_stats.lp_cap_100hdx = 42023859Sml29623 anlpar.bits.cap_100hdx; 42033859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 42043859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 42053859Sml29623 statsp->mac_stats.lp_cap_asmpause = 42063859Sml29623 anlpar.bits.cap_asmpause; 42073859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 42083859Sml29623 an_common.value = anar.value & anlpar.value; 42093859Sml29623 if (param_arr[param_anar_1000fdx].value || 42103859Sml29623 param_arr[param_anar_1000hdx].value) { 42113859Sml29623 if ((status = nxge_mii_read(nxgep, 42123859Sml29623 statsp->mac_stats.xcvr_portn, 42135125Sjoycey #if defined(__i386) 42145125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 42155125Sjoycey #else 42163859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 42175125Sjoycey #endif 42183859Sml29623 &gsr.value)) 42193859Sml29623 != NXGE_OK) 42203859Sml29623 goto fail; 42213859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 42223859Sml29623 gsr.bits.link_1000fdx; 42233859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 42243859Sml29623 gsr.bits.link_1000hdx; 42253859Sml29623 if (param_arr[param_anar_1000fdx].value && 42263859Sml29623 gsr.bits.link_1000fdx) { 42273859Sml29623 statsp->mac_stats.link_speed = 1000; 42283859Sml29623 statsp->mac_stats.link_duplex = 2; 42293859Sml29623 } else if ( 42303859Sml29623 param_arr[param_anar_1000hdx].value && 42313859Sml29623 gsr.bits.link_1000hdx) { 42323859Sml29623 statsp->mac_stats.link_speed = 1000; 42333859Sml29623 statsp->mac_stats.link_duplex = 1; 42343859Sml29623 } 42353859Sml29623 } 42363859Sml29623 if ((an_common.value != 0) && 42373859Sml29623 !(statsp->mac_stats.link_speed)) { 42383859Sml29623 if (an_common.bits.cap_100T4) { 42393859Sml29623 statsp->mac_stats.link_T4 = 1; 42403859Sml29623 statsp->mac_stats.link_speed = 100; 42413859Sml29623 statsp->mac_stats.link_duplex = 1; 42423859Sml29623 } else if (an_common.bits.cap_100fdx) { 42433859Sml29623 statsp->mac_stats.link_speed = 100; 42443859Sml29623 statsp->mac_stats.link_duplex = 2; 42453859Sml29623 } else if (an_common.bits.cap_100hdx) { 42463859Sml29623 statsp->mac_stats.link_speed = 100; 42473859Sml29623 statsp->mac_stats.link_duplex = 1; 42483859Sml29623 } else if (an_common.bits.cap_10fdx) { 42493859Sml29623 statsp->mac_stats.link_speed = 10; 42503859Sml29623 statsp->mac_stats.link_duplex = 2; 42513859Sml29623 } else if (an_common.bits.cap_10hdx) { 42523859Sml29623 statsp->mac_stats.link_speed = 10; 42533859Sml29623 statsp->mac_stats.link_duplex = 1; 42543859Sml29623 } else { 42553859Sml29623 goto fail; 42563859Sml29623 } 42573859Sml29623 } 42583859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 42593859Sml29623 statsp->mac_stats.link_asmpause = 42603859Sml29623 an_common.bits.cap_asmpause; 42613859Sml29623 if (statsp->mac_stats.link_asmpause) 42623859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 42633859Sml29623 (statsp->mac_stats.lp_cap_pause 42643859Sml29623 == 1)) 42653859Sml29623 statsp->mac_stats.link_pause 42663859Sml29623 = 0; 42673859Sml29623 else 42683859Sml29623 statsp->mac_stats.link_pause 42693859Sml29623 = 1; 42703859Sml29623 else 42713859Sml29623 statsp->mac_stats.link_pause = 42723859Sml29623 an_common.bits.cap_pause; 42733859Sml29623 } 42745196Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 42755196Ssbehera statsp->mac_stats.link_speed = 1000; 42765196Ssbehera statsp->mac_stats.link_duplex = 2; 42773859Sml29623 } 42783859Sml29623 *link_up = LINK_IS_UP; 42793859Sml29623 } 42803859Sml29623 42813859Sml29623 if (nxgep->link_notify) { 42823859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 42833859Sml29623 LINK_IS_DOWN); 42843859Sml29623 nxgep->link_notify = B_FALSE; 42853859Sml29623 } 42863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 42873859Sml29623 return (NXGE_OK); 42883859Sml29623 fail: 42893859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 42903859Sml29623 "nxge_mii_check: Unable to check MII")); 42913859Sml29623 return (status); 42923859Sml29623 } 42933859Sml29623 42944977Sraghus /* Check PCS to see if there is any link status change */ 42954977Sraghus nxge_status_t 42964977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 42974977Sraghus { 42984977Sraghus p_nxge_stats_t statsp; 42994977Sraghus nxge_status_t status = NXGE_OK; 43004977Sraghus boolean_t linkup; 43014977Sraghus 43024977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 43034977Sraghus 43044977Sraghus statsp = nxgep->statsp; 43054977Sraghus *link_up = LINK_NO_CHANGE; 43064977Sraghus 43074977Sraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 43084977Sraghus if (linkup) { 43094977Sraghus if (nxgep->link_notify || 43104977Sraghus nxgep->statsp->mac_stats.link_up == 0) { 43114977Sraghus statsp->mac_stats.link_up = 1; 43124977Sraghus statsp->mac_stats.link_speed = 1000; 43134977Sraghus statsp->mac_stats.link_duplex = 2; 43144977Sraghus *link_up = LINK_IS_UP; 43154977Sraghus nxgep->link_notify = B_FALSE; 43164977Sraghus } 43174977Sraghus } else { 43184977Sraghus if (nxgep->link_notify || 43194977Sraghus nxgep->statsp->mac_stats.link_up == 1) { 43204977Sraghus statsp->mac_stats.link_up = 0; 43214977Sraghus statsp->mac_stats.link_speed = 0; 43224977Sraghus statsp->mac_stats.link_duplex = 0; 43234977Sraghus *link_up = LINK_IS_DOWN; 43244977Sraghus nxgep->link_notify = B_FALSE; 43254977Sraghus } 43264977Sraghus } 43274977Sraghus 43284977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 43294977Sraghus return (NXGE_OK); 43304977Sraghus fail: 43314977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 43324977Sraghus "nxge_pcs_check: Unable to check PCS")); 43334977Sraghus return (status); 43344977Sraghus } 43354977Sraghus 43363859Sml29623 /* Add a multicast address entry into the HW hash table */ 43373859Sml29623 43383859Sml29623 nxge_status_t 43393859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 43403859Sml29623 { 43413859Sml29623 uint32_t mchash; 43423859Sml29623 p_hash_filter_t hash_filter; 43433859Sml29623 uint16_t hash_bit; 43443859Sml29623 boolean_t rx_init = B_FALSE; 43453859Sml29623 uint_t j; 43463859Sml29623 nxge_status_t status = NXGE_OK; 43473859Sml29623 43483859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 43493859Sml29623 43503859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 43513859Sml29623 mchash = crc32_mchash(addrp); 43523859Sml29623 if (nxgep->hash_filter == NULL) { 43533859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 43543859Sml29623 "Allocating hash filter storage.")); 43553859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 43563859Sml29623 KM_SLEEP); 43573859Sml29623 } 43583859Sml29623 hash_filter = nxgep->hash_filter; 43593859Sml29623 j = mchash / HASH_REG_WIDTH; 43603859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 43613859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 43623859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 43633859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 43643859Sml29623 hash_filter->hash_ref_cnt++; 43653859Sml29623 rx_init = B_TRUE; 43663859Sml29623 } 43673859Sml29623 if (rx_init) { 43683859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 43693859Sml29623 goto fail; 43703859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 43713859Sml29623 goto fail; 43723859Sml29623 } 43733859Sml29623 43743859Sml29623 RW_EXIT(&nxgep->filter_lock); 43753859Sml29623 43763859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 43773859Sml29623 43783859Sml29623 return (NXGE_OK); 43793859Sml29623 fail: 43803859Sml29623 RW_EXIT(&nxgep->filter_lock); 43813859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 43823859Sml29623 "Unable to add multicast address")); 43833859Sml29623 return (status); 43843859Sml29623 } 43853859Sml29623 43863859Sml29623 /* Remove a multicast address entry from the HW hash table */ 43873859Sml29623 43883859Sml29623 nxge_status_t 43893859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 43903859Sml29623 { 43913859Sml29623 uint32_t mchash; 43923859Sml29623 p_hash_filter_t hash_filter; 43933859Sml29623 uint16_t hash_bit; 43943859Sml29623 boolean_t rx_init = B_FALSE; 43953859Sml29623 uint_t j; 43963859Sml29623 nxge_status_t status = NXGE_OK; 43973859Sml29623 43983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 43993859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 44003859Sml29623 mchash = crc32_mchash(addrp); 44013859Sml29623 if (nxgep->hash_filter == NULL) { 44023859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 44033859Sml29623 "Hash filter already de_allocated.")); 44043859Sml29623 RW_EXIT(&nxgep->filter_lock); 44053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 44063859Sml29623 return (NXGE_OK); 44073859Sml29623 } 44083859Sml29623 hash_filter = nxgep->hash_filter; 44093859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 44103859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 44113859Sml29623 j = mchash / HASH_REG_WIDTH; 44123859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 44133859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 44143859Sml29623 hash_filter->hash_ref_cnt--; 44153859Sml29623 rx_init = B_TRUE; 44163859Sml29623 } 44173859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 44183859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 44193859Sml29623 "De-allocating hash filter storage.")); 44203859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 44213859Sml29623 nxgep->hash_filter = NULL; 44223859Sml29623 } 44233859Sml29623 44243859Sml29623 if (rx_init) { 44253859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 44263859Sml29623 goto fail; 44273859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 44283859Sml29623 goto fail; 44293859Sml29623 } 44303859Sml29623 RW_EXIT(&nxgep->filter_lock); 44313859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 44323859Sml29623 44333859Sml29623 return (NXGE_OK); 44343859Sml29623 fail: 44353859Sml29623 RW_EXIT(&nxgep->filter_lock); 44363859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 44373859Sml29623 "Unable to remove multicast address")); 44383859Sml29623 44393859Sml29623 return (status); 44403859Sml29623 } 44413859Sml29623 44423859Sml29623 /* Set MAC address into MAC address HW registers */ 44433859Sml29623 44443859Sml29623 nxge_status_t 44453859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 44463859Sml29623 { 44473859Sml29623 nxge_status_t status = NXGE_OK; 44483859Sml29623 44493859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 44503859Sml29623 44513859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 44523859Sml29623 /* 44533859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 44543859Sml29623 */ 44553859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 44563859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 44573859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 44583859Sml29623 goto nxge_set_mac_addr_exit; 44593859Sml29623 } 44603859Sml29623 nxgep->ouraddr = *addrp; 44613859Sml29623 /* 44623859Sml29623 * Set new interface local address and re-init device. 44633859Sml29623 * This is destructive to any other streams attached 44643859Sml29623 * to this device. 44653859Sml29623 */ 44663859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 44673859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 44683859Sml29623 goto fail; 44693859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 44703859Sml29623 goto fail; 44713859Sml29623 44723859Sml29623 RW_EXIT(&nxgep->filter_lock); 44733859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 44743859Sml29623 goto nxge_set_mac_addr_end; 44753859Sml29623 nxge_set_mac_addr_exit: 44763859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 44773859Sml29623 nxge_set_mac_addr_end: 44783859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 44793859Sml29623 44803859Sml29623 return (NXGE_OK); 44813859Sml29623 fail: 44823859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 44833859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 44843859Sml29623 "Unable to set mac address")); 44853859Sml29623 return (status); 44863859Sml29623 } 44873859Sml29623 44884693Stm144005 static 44894693Stm144005 check_link_state_t 44904693Stm144005 nxge_check_link_stop( 44914693Stm144005 nxge_t *nxge) 44924693Stm144005 { 44934693Stm144005 /* If the poll has been cancelled, return STOP. */ 44944693Stm144005 MUTEX_ENTER(&nxge->poll_lock); 44954693Stm144005 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 44964693Stm144005 nxge->poll_state = LINK_MONITOR_STOP; 44974693Stm144005 nxge->nxge_link_poll_timerid = 0; 44984693Stm144005 cv_broadcast(&nxge->poll_cv); 44994693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 45004693Stm144005 45014693Stm144005 NXGE_DEBUG_MSG((nxge, MAC_CTL, 45024693Stm144005 "nxge_check_%s_link(port<%d>) stopped.", 45034693Stm144005 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 45044693Stm144005 nxge->mac.portnum)); 45054693Stm144005 return (CHECK_LINK_STOP); 45064693Stm144005 } 45074693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 45084693Stm144005 45094693Stm144005 return (CHECK_LINK_RESCHEDULE); 45104693Stm144005 } 45114693Stm144005 45123859Sml29623 /* Check status of MII (MIF or PCS) link */ 45133859Sml29623 45144732Sdavemq static nxge_status_t 45153859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 45163859Sml29623 { 45173859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 45183859Sml29623 mii_anlpar_t anlpar; 45193859Sml29623 mii_gsr_t gsr; 45203859Sml29623 p_mii_regs_t mii_regs; 45213859Sml29623 nxge_status_t status = NXGE_OK; 45223859Sml29623 uint8_t portn; 45233859Sml29623 nxge_link_state_t link_up; 45243859Sml29623 45254693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 45264693Stm144005 return (NXGE_ERROR); 45274693Stm144005 45284693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 45294693Stm144005 return (NXGE_OK); 45304693Stm144005 45313859Sml29623 portn = nxgep->mac.portnum; 45323859Sml29623 45333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 45344693Stm144005 portn)); 45353859Sml29623 45363859Sml29623 mii_regs = NULL; 45373859Sml29623 45383859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 45393859Sml29623 45403859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 45413859Sml29623 goto nxge_check_mii_link_exit; 45423859Sml29623 45434977Sraghus switch (nxgep->mac.portmode) { 45444977Sraghus default: 45455196Ssbehera bmsr_data.value = 0; 45463859Sml29623 if ((status = nxge_mii_read(nxgep, 45474977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 45485125Sjoycey #if defined(__i386) 45495125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 45505125Sjoycey #else 45514977Sraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 45525125Sjoycey #endif 45534977Sraghus &bmsr_data.value)) != NXGE_OK) { 45543859Sml29623 goto fail; 45553859Sml29623 } 45564977Sraghus 45575196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45585196Ssbehera "==> nxge_check_mii_link port<0x%x> " 45595196Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 45605572Ssbehera portn, bmsr_data.value, nxgep->bmsr.value)); 45615196Ssbehera 45624977Sraghus if (nxgep->param_arr[param_autoneg].value) { 45634977Sraghus if ((status = nxge_mii_read(nxgep, 45644977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 45655125Sjoycey #if defined(__i386) 45665125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 45675125Sjoycey #else 45684977Sraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 45695125Sjoycey #endif 45704977Sraghus &gsr.value)) != NXGE_OK) 45714977Sraghus goto fail; 45724977Sraghus if ((status = nxge_mii_read(nxgep, 45734977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 45745125Sjoycey #if defined(__i386) 45755125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 45765125Sjoycey #else 45774977Sraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 45785125Sjoycey #endif 45794977Sraghus &anlpar.value)) != NXGE_OK) 45804977Sraghus goto fail; 45815196Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 45825196Ssbehera 45835196Ssbehera if (nxgep->statsp->mac_stats.link_up && 45845196Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 45855196Ssbehera gsr.bits.link_1000fdx) || 45865196Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 45875196Ssbehera gsr.bits.link_1000hdx) || 45885196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 45895196Ssbehera anlpar.bits.cap_100T4) || 45905196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 45915196Ssbehera anlpar.bits.cap_100fdx) || 45925196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 45935196Ssbehera anlpar.bits.cap_100hdx) || 45945196Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 45955196Ssbehera anlpar.bits.cap_10fdx) || 45965196Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 45975196Ssbehera anlpar.bits.cap_10hdx))) { 45985196Ssbehera bmsr_data.bits.link_status = 0; 45995196Ssbehera } 46004977Sraghus } 46014977Sraghus } 46024977Sraghus 46034977Sraghus /* Workaround for link down issue */ 46044977Sraghus if (bmsr_data.value == 0) { 46054977Sraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 46064977Sraghus goto nxge_check_mii_link_exit; 46074977Sraghus } 46084977Sraghus 46095196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46105196Ssbehera "==> nxge_check_mii_link port<0x%x> :" 46115196Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 46125572Ssbehera portn, nxgep->bmsr.value, bmsr_data.value)); 46135196Ssbehera 46144977Sraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 46154977Sraghus nxgep->bmsr.value = bmsr_data.value; 46165196Ssbehera 46175196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46185196Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 46195196Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 46205572Ssbehera portn, bmsr_data.value, bmsr_ints.value)); 46215196Ssbehera 46224977Sraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 46234977Sraghus &link_up)) != NXGE_OK) { 46244977Sraghus goto fail; 46254977Sraghus } 46264977Sraghus break; 46274977Sraghus 46284977Sraghus case PORT_1G_SERDES: 46294977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46304977Sraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 46314977Sraghus if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 46324977Sraghus != NXGE_OK) { 46334977Sraghus goto fail; 46344977Sraghus } 46354977Sraghus break; 46363859Sml29623 } 46373859Sml29623 46383859Sml29623 nxge_check_mii_link_exit: 46393859Sml29623 RW_EXIT(&nxgep->filter_lock); 46403859Sml29623 if (link_up == LINK_IS_UP) { 46413859Sml29623 nxge_link_is_up(nxgep); 46423859Sml29623 } else if (link_up == LINK_IS_DOWN) { 46433859Sml29623 nxge_link_is_down(nxgep); 46443859Sml29623 } 46453859Sml29623 46463859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 46473859Sml29623 46483859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 46494977Sraghus portn)); 46503859Sml29623 return (NXGE_OK); 46513859Sml29623 46523859Sml29623 fail: 46533859Sml29623 RW_EXIT(&nxgep->filter_lock); 46543859Sml29623 46553859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 46563859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 46574977Sraghus "nxge_check_mii_link: Failed to check link port<%d>", 46584977Sraghus portn)); 46593859Sml29623 return (status); 46603859Sml29623 } 46613859Sml29623 46623859Sml29623 46633859Sml29623 /*ARGSUSED*/ 46644732Sdavemq static nxge_status_t 46653859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 46663859Sml29623 { 46673859Sml29623 uint8_t portn; 46683859Sml29623 nxge_status_t status = NXGE_OK; 46695422Ssbehera boolean_t link_up; 46704977Sraghus uint32_t val; 46714977Sraghus npi_status_t rs; 46723859Sml29623 46734693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 46744693Stm144005 return (NXGE_ERROR); 46754693Stm144005 46764693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 46774693Stm144005 return (NXGE_OK); 46784693Stm144005 46793859Sml29623 portn = nxgep->mac.portnum; 46805196Ssbehera val = 0; 46815196Ssbehera rs = NPI_SUCCESS; 46823859Sml29623 46833859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 46844693Stm144005 portn)); 46853859Sml29623 46864977Sraghus switch (nxgep->mac.portmode) { 46874977Sraghus default: 46885572Ssbehera /* 46895572Ssbehera * Check if the phy is present in case of hot swappable phy 46905572Ssbehera */ 46915572Ssbehera if (nxgep->hot_swappable_phy) { 46925572Ssbehera boolean_t phy_present_now = B_FALSE; 46935572Ssbehera 46945572Ssbehera /* 46955572Ssbehera * If this is the 2nd Goa port, then check 2 addresses 46965572Ssbehera * to take care of the Goa NEM card requirements. 46975572Ssbehera */ 46985572Ssbehera if (portn == 1) { 46995572Ssbehera if (nxge_is_phy_present(nxgep, 47005572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR, 47015572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 47025572Ssbehera phy_present_now = B_TRUE; 47035572Ssbehera nxgep->xcvr_addr = 47045572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR; 47055572Ssbehera goto phy_check_done; 47065572Ssbehera } 47075572Ssbehera } 47085572Ssbehera if (nxge_is_phy_present(nxgep, 47095572Ssbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 47105572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 47115572Ssbehera nxgep->xcvr_addr = 47125572Ssbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn; 47135572Ssbehera phy_present_now = B_TRUE; 47145572Ssbehera } 47155572Ssbehera 47165572Ssbehera phy_check_done: 47175572Ssbehera if (nxgep->phy_absent) { 47185572Ssbehera if (phy_present_now) { 47195572Ssbehera /* 47205572Ssbehera * Detect, Initialize phy and do link up 47215572Ssbehera * set xcvr vals, link_init, nxge_init 47225572Ssbehera */ 47235572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 47245572Ssbehera "Hot swappable phy DETECTED!!")); 47255572Ssbehera nxgep->phy_absent = B_FALSE; 47265572Ssbehera (void) nxge_xcvr_find(nxgep); 47275572Ssbehera (void) nxge_link_init(nxgep); 47285572Ssbehera if (!(nxgep->drv_state & 47295572Ssbehera STATE_HW_INITIALIZED)) { 47305572Ssbehera status = nxge_init(nxgep); 47315572Ssbehera if (status != NXGE_OK) { 47325572Ssbehera NXGE_ERROR_MSG((nxgep, 47335572Ssbehera NXGE_ERR_CTL, 47345572Ssbehera "Hot swappable " 47355572Ssbehera "phy present, but" 47365572Ssbehera " driver init" 47375572Ssbehera " failed...")); 47385572Ssbehera goto fail; 47395572Ssbehera } 47405572Ssbehera } 47415572Ssbehera } 47425572Ssbehera 47435572Ssbehera goto start_link_check; 47445572Ssbehera 47455572Ssbehera } else if (!phy_present_now) { 47465572Ssbehera /* 47475572Ssbehera * Phy gone, bring link down reset xcvr vals 47485572Ssbehera */ 47495572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 47505572Ssbehera "Hot swappable phy REMOVED!!")); 47515572Ssbehera nxgep->phy_absent = B_TRUE; 47525572Ssbehera nxgep->statsp->mac_stats.link_up = 0; 47535572Ssbehera nxgep->statsp->mac_stats.link_speed = 0; 47545572Ssbehera nxgep->statsp->mac_stats.link_duplex = 0; 47555572Ssbehera nxge_link_is_down(nxgep); 47565572Ssbehera nxgep->link_notify = B_FALSE; 47575572Ssbehera 47585572Ssbehera (void) nxge_xcvr_find(nxgep); 47595572Ssbehera 47605572Ssbehera goto start_link_check; 47615572Ssbehera 47625572Ssbehera } 47635572Ssbehera } 47646604Ssbehera if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 47656604Ssbehera status = nxge_mrvl88x2011_link(nxgep, &link_up); 47666604Ssbehera } else { 47676604Ssbehera status = nxge_check_bcm8704_link(nxgep, &link_up); 47686604Ssbehera } 47694977Sraghus if (status != NXGE_OK) 47704977Sraghus goto fail; 47714977Sraghus break; 47724977Sraghus case PORT_10G_SERDES: 47734977Sraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 47745422Ssbehera XPCS_REG_STATUS, &val); 47754977Sraghus if (rs != 0) 47764977Sraghus goto fail; 47774977Sraghus 47784977Sraghus link_up = B_FALSE; 47795422Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 47805422Ssbehera link_up = B_TRUE; 47814977Sraghus } 47824977Sraghus 47834977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 47844977Sraghus "==> nxge_check_10g_link port<%d> " 47855422Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 47865422Ssbehera portn, val, link_up)); 47875422Ssbehera 47884977Sraghus break; 47894977Sraghus } 47903859Sml29623 47913859Sml29623 if (link_up) { 47923859Sml29623 if (nxgep->link_notify || 47933859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 47943859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 47953859Sml29623 goto fail; 47963859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 47973859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 47983859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 47993859Sml29623 48003859Sml29623 nxge_link_is_up(nxgep); 48013859Sml29623 nxgep->link_notify = B_FALSE; 48023859Sml29623 } 48033859Sml29623 } else { 48043859Sml29623 if (nxgep->link_notify || 48053859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 48063859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 48073859Sml29623 goto fail; 48083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 48094977Sraghus "Link down cable problem")); 48103859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 48113859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 48123859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 48133859Sml29623 48143859Sml29623 nxge_link_is_down(nxgep); 48153859Sml29623 nxgep->link_notify = B_FALSE; 48163859Sml29623 } 48173859Sml29623 } 48183859Sml29623 48195572Ssbehera start_link_check: 48203859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 48213859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 48224693Stm144005 portn)); 48233859Sml29623 return (NXGE_OK); 48243859Sml29623 48253859Sml29623 fail: 48264693Stm144005 (void) nxge_check_link_stop(nxgep); 48274693Stm144005 48283859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 48294693Stm144005 "nxge_check_10g_link: Failed to check link port<%d>", 48304693Stm144005 portn)); 48313859Sml29623 return (status); 48323859Sml29623 } 48333859Sml29623 48343859Sml29623 48353859Sml29623 /* Declare link down */ 48363859Sml29623 48373859Sml29623 void 48383859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 48393859Sml29623 { 48404732Sdavemq p_nxge_stats_t statsp; 48414732Sdavemq char link_stat_msg[64]; 48424732Sdavemq 48433859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 48443859Sml29623 48454732Sdavemq statsp = nxgep->statsp; 48464732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 48474732Sdavemq statsp->mac_stats.xcvr_portn); 48484732Sdavemq 48494732Sdavemq if (nxge_no_msg == B_FALSE) { 48504732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 48514732Sdavemq } 48524732Sdavemq 48533859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 48543859Sml29623 48553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 48563859Sml29623 } 48573859Sml29623 48583859Sml29623 /* Declare link up */ 48593859Sml29623 48603859Sml29623 void 48613859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 48623859Sml29623 { 48634732Sdavemq p_nxge_stats_t statsp; 48644732Sdavemq char link_stat_msg[64]; 48653859Sml29623 uint32_t val; 48663859Sml29623 48673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 48683859Sml29623 48694732Sdavemq statsp = nxgep->statsp; 48704732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 48714732Sdavemq statsp->mac_stats.xcvr_portn, 48724732Sdavemq statsp->mac_stats.link_speed); 48734732Sdavemq 48744732Sdavemq if (statsp->mac_stats.link_T4) 48754732Sdavemq (void) strcat(link_stat_msg, "T4"); 48764732Sdavemq else if (statsp->mac_stats.link_duplex == 2) 48774732Sdavemq (void) strcat(link_stat_msg, "full duplex"); 48784732Sdavemq else 48794732Sdavemq (void) strcat(link_stat_msg, "half duplex"); 48804732Sdavemq 48813859Sml29623 (void) nxge_xif_init(nxgep); 48823859Sml29623 48833859Sml29623 /* Clean up symbol errors incurred during link transition */ 48844977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 48854977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 48863859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 48873859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 48883859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 48893859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 48903859Sml29623 } 48913859Sml29623 48924732Sdavemq if (nxge_no_msg == B_FALSE) { 48934732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 48944732Sdavemq } 48954732Sdavemq 48963859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 48973859Sml29623 48983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 48993859Sml29623 } 49003859Sml29623 49013859Sml29623 /* 49023859Sml29623 * Calculate the bit in the multicast address filter 49033859Sml29623 * that selects the given * address. 49043859Sml29623 * Note: For GEM, the last 8-bits are used. 49053859Sml29623 */ 49063859Sml29623 uint32_t 49073859Sml29623 crc32_mchash(p_ether_addr_t addr) 49083859Sml29623 { 49093859Sml29623 uint8_t *cp; 49103859Sml29623 uint32_t crc; 49113859Sml29623 uint32_t c; 49123859Sml29623 int byte; 49133859Sml29623 int bit; 49143859Sml29623 49153859Sml29623 cp = (uint8_t *)addr; 49163859Sml29623 crc = (uint32_t)0xffffffff; 49173859Sml29623 for (byte = 0; byte < 6; byte++) { 49183859Sml29623 c = (uint32_t)cp[byte]; 49193859Sml29623 for (bit = 0; bit < 8; bit++) { 49203859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 49213859Sml29623 crc = (crc >> 1)^0xedb88320; 49223859Sml29623 else 49233859Sml29623 crc = (crc >> 1); 49243859Sml29623 c >>= 1; 49253859Sml29623 } 49263859Sml29623 } 49273859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 49283859Sml29623 } 49293859Sml29623 49303859Sml29623 /* Reset serdes */ 49313859Sml29623 49323859Sml29623 nxge_status_t 49333859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 49343859Sml29623 { 49353859Sml29623 npi_handle_t handle; 49363859Sml29623 49373859Sml29623 handle = nxgep->npi_handle; 49383859Sml29623 49393859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 49403859Sml29623 drv_usecwait(500); 49413859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 49423859Sml29623 49433859Sml29623 return (NXGE_OK); 49443859Sml29623 } 49453859Sml29623 49463859Sml29623 /* Monitor link status using interrupt or polling */ 49473859Sml29623 nxge_status_t 49483859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 49493859Sml29623 { 49503859Sml29623 nxge_status_t status = NXGE_OK; 49513859Sml29623 49526495Sspeer /* If we are a guest domain driver, don't bother. */ 49536495Sspeer if (isLDOMguest(nxgep)) 49546495Sspeer return (status); 49556495Sspeer 49563859Sml29623 /* 49574693Stm144005 * Return immediately if this is an imaginary XMAC port. 49584693Stm144005 * (At least, we don't have 4-port XMAC cards yet.) 49593859Sml29623 */ 49604977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 49614977Sraghus nxgep->mac.portmode == PORT_10G_SERDES) && 49624977Sraghus (nxgep->mac.portnum > 1)) 49633859Sml29623 return (NXGE_OK); 49643859Sml29623 49653859Sml29623 if (nxgep->statsp == NULL) { 49663859Sml29623 /* stats has not been allocated. */ 49673859Sml29623 return (NXGE_OK); 49683859Sml29623 } 49696075Ssbehera /* Don't check link if we're in internal loopback mode */ 49706075Ssbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 49713859Sml29623 return (NXGE_OK); 49723859Sml29623 49733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 49744693Stm144005 "==> nxge_link_monitor port<%d> enable=%d", 49754693Stm144005 nxgep->mac.portnum, enable)); 49763859Sml29623 if (enable == LINK_MONITOR_START) { 49773859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 49783859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 49794693Stm144005 != NXGE_OK) 49803859Sml29623 goto fail; 49813859Sml29623 } else { 49824693Stm144005 timeout_id_t timerid; 49834693Stm144005 49844693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 49854693Stm144005 return (NXGE_OK); 49864693Stm144005 49874732Sdavemq if (nxgep->xcvr.check_link) { 49884732Sdavemq timerid = timeout( 49894732Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 49904693Stm144005 nxgep, 49914693Stm144005 drv_usectohz(LINK_MONITOR_PERIOD)); 49924732Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 49934732Sdavemq nxgep->nxge_link_poll_timerid = timerid; 49944732Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 49954732Sdavemq } else { 49964693Stm144005 return (NXGE_ERROR); 49973859Sml29623 } 49983859Sml29623 } 49993859Sml29623 } else { 50003859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 50013859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 50024693Stm144005 != NXGE_OK) 50033859Sml29623 goto fail; 50043859Sml29623 } else { 50054693Stm144005 clock_t rv; 50064693Stm144005 50074693Stm144005 MUTEX_ENTER(&nxgep->poll_lock); 50084693Stm144005 50094693Stm144005 /* If <timerid> == 0, the link monitor has */ 50104693Stm144005 /* never been started, or just now stopped. */ 50114693Stm144005 if (nxgep->nxge_link_poll_timerid == 0) { 50124693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 50134693Stm144005 return (NXGE_OK); 50144693Stm144005 } 50154693Stm144005 50164693Stm144005 nxgep->poll_state = LINK_MONITOR_STOPPING; 50174693Stm144005 rv = cv_timedwait(&nxgep->poll_cv, 50184693Stm144005 &nxgep->poll_lock, 50194693Stm144005 ddi_get_lbolt() + 50204693Stm144005 drv_usectohz(LM_WAIT_MULTIPLIER * 50214693Stm144005 LINK_MONITOR_PERIOD)); 50224693Stm144005 if (rv == -1) { 50234693Stm144005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50244693Stm144005 "==> stopping port %d: " 50254693Stm144005 "cv_timedwait(%d) timed out", 50264693Stm144005 nxgep->mac.portnum, nxgep->poll_state)); 50274693Stm144005 nxgep->poll_state = LINK_MONITOR_STOP; 50283859Sml29623 nxgep->nxge_link_poll_timerid = 0; 50293859Sml29623 } 50304693Stm144005 50314693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 50323859Sml29623 } 50333859Sml29623 } 50343859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50354693Stm144005 "<== nxge_link_monitor port<%d> enable=%d", 50364693Stm144005 nxgep->mac.portnum, enable)); 50376495Sspeer 50383859Sml29623 return (NXGE_OK); 50393859Sml29623 fail: 50403859Sml29623 return (status); 50413859Sml29623 } 50423859Sml29623 50433859Sml29623 /* Set promiscous mode */ 50443859Sml29623 50453859Sml29623 nxge_status_t 50463859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 50473859Sml29623 { 50483859Sml29623 nxge_status_t status = NXGE_OK; 50493859Sml29623 50504732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 50513859Sml29623 50523859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 50533859Sml29623 50543859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 50553859Sml29623 50563859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 50573859Sml29623 goto fail; 50583859Sml29623 } 50593859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 50603859Sml29623 goto fail; 50613859Sml29623 } 50623859Sml29623 50633859Sml29623 RW_EXIT(&nxgep->filter_lock); 50643859Sml29623 50653859Sml29623 if (on) 50663859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 50673859Sml29623 else 50683859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 50693859Sml29623 50703859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 50713859Sml29623 50723859Sml29623 return (NXGE_OK); 50733859Sml29623 fail: 50743859Sml29623 RW_EXIT(&nxgep->filter_lock); 50753859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 50764732Sdavemq "Unable to set promisc (%d)", on)); 50773859Sml29623 50783859Sml29623 return (status); 50793859Sml29623 } 50803859Sml29623 50813859Sml29623 /*ARGSUSED*/ 50823859Sml29623 uint_t 50833859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 50843859Sml29623 { 50853859Sml29623 #ifdef NXGE_DEBUG 50863859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 50873859Sml29623 #endif 50883859Sml29623 #if NXGE_MIF 50893859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 50903859Sml29623 uint32_t status; 50913859Sml29623 npi_handle_t handle; 50923859Sml29623 uint8_t portn; 50933859Sml29623 p_nxge_stats_t statsp; 50943859Sml29623 #endif 50953859Sml29623 50963859Sml29623 #ifdef NXGE_MIF 50973859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 50983859Sml29623 nxgep = ldvp->nxgep; 50993859Sml29623 } 51003859Sml29623 nxgep = ldvp->nxgep; 51013859Sml29623 #endif 51023859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 51033859Sml29623 51043859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 51053859Sml29623 return (DDI_INTR_CLAIMED); 51063859Sml29623 51073859Sml29623 mif_intr_fail: 51083859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 51093859Sml29623 return (DDI_INTR_UNCLAIMED); 51103859Sml29623 } 51113859Sml29623 51123859Sml29623 /*ARGSUSED*/ 51133859Sml29623 uint_t 51143859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 51153859Sml29623 { 51163859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 51173859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 51183859Sml29623 p_nxge_ldg_t ldgp; 51193859Sml29623 uint32_t status; 51203859Sml29623 npi_handle_t handle; 51213859Sml29623 uint8_t portn; 51223859Sml29623 p_nxge_stats_t statsp; 51233859Sml29623 npi_status_t rs = NPI_SUCCESS; 51243859Sml29623 51253859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 51263859Sml29623 nxgep = ldvp->nxgep; 51273859Sml29623 } 51283859Sml29623 51293859Sml29623 ldgp = ldvp->ldgp; 51303859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 51314732Sdavemq "group %d", ldgp->ldg)); 51323859Sml29623 51333859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 51343859Sml29623 /* 51353859Sml29623 * This interrupt handler is for a specific 51363859Sml29623 * mac port. 51373859Sml29623 */ 51383859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 51393859Sml29623 portn = nxgep->mac.portnum; 51403859Sml29623 51413859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 51424732Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 51433859Sml29623 51443859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 51453859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 51463859Sml29623 (xmac_tx_iconfig_t *)&status); 51473859Sml29623 if (rs != NPI_SUCCESS) 51483859Sml29623 goto npi_fail; 51493859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 51503859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 51513859Sml29623 statsp->xmac_stats.tx_underflow_err++; 51523859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 51533859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 51543859Sml29623 } 51553859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 51563859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 51575523Syc148097 /* 51585523Syc148097 * Do not send FMA ereport because this 51595523Syc148097 * error does not indicate HW failure. 51605523Syc148097 */ 51613859Sml29623 } 51623859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 51633859Sml29623 statsp->xmac_stats.tx_overflow_err++; 51643859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 51653859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 51663859Sml29623 } 51673859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 51683859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 51693859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 51703859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 51713859Sml29623 } 51723859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 51733859Sml29623 statsp->xmac_stats.tx_byte_cnt += 51743859Sml29623 XTXMAC_BYTE_CNT_MASK; 51753859Sml29623 } 51763859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 51773859Sml29623 statsp->xmac_stats.tx_frame_cnt += 51783859Sml29623 XTXMAC_FRM_CNT_MASK; 51793859Sml29623 } 51803859Sml29623 } 51813859Sml29623 51823859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 51833859Sml29623 (xmac_rx_iconfig_t *)&status); 51843859Sml29623 if (rs != NPI_SUCCESS) 51853859Sml29623 goto npi_fail; 51863859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 51873859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 51883859Sml29623 statsp->xmac_stats.rx_overflow_err++; 51893859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 51903859Sml29623 statsp->xmac_stats.rx_underflow_err++; 51913859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 51923859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 51933859Sml29623 } 51945523Syc148097 /* 51955523Syc148097 * Do not send FMA ereport for the following 3 errors 51965523Syc148097 * because they do not indicate HW failures. 51975523Syc148097 */ 51983859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 51993859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 52003859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 52013859Sml29623 } 52023859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 52033859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 52043859Sml29623 MAC_LEN_ER_CNT_MASK; 52053859Sml29623 } 52063859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 52073859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 52083859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 52093859Sml29623 } 52103859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 52113859Sml29623 statsp->xmac_stats.rx_byte_cnt += 52123859Sml29623 XRXMAC_BT_CNT_MASK; 52133859Sml29623 } 52143859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 52153859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 52163859Sml29623 XRXMAC_HIST_CNT1_MASK; 52173859Sml29623 } 52183859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 52193859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 52203859Sml29623 XRXMAC_HIST_CNT2_MASK; 52213859Sml29623 } 52223859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 52233859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 52243859Sml29623 XRXMAC_HIST_CNT3_MASK; 52253859Sml29623 } 52263859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 52273859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 52283859Sml29623 XRXMAC_HIST_CNT4_MASK; 52293859Sml29623 } 52303859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 52313859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 52323859Sml29623 XRXMAC_HIST_CNT5_MASK; 52333859Sml29623 } 52343859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 52353859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 52363859Sml29623 XRXMAC_HIST_CNT6_MASK; 52373859Sml29623 } 52383859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 52393859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 52403859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 52413859Sml29623 } 52423859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 52433859Sml29623 statsp->xmac_stats.rx_mult_cnt += 52443859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 52453859Sml29623 } 52465523Syc148097 /* 52475523Syc148097 * Do not send FMA ereport for the following 3 errors 52485523Syc148097 * because they do not indicate HW failures. 52495523Syc148097 */ 52503859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 52513859Sml29623 statsp->xmac_stats.rx_frag_cnt += 52523859Sml29623 XRXMAC_FRAG_CNT_MASK; 52533859Sml29623 } 52543859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 52553859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 52563859Sml29623 XRXMAC_AL_ER_CNT_MASK; 52573859Sml29623 } 52583859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 52593859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 52603859Sml29623 XMAC_LINK_FLT_CNT_MASK; 52613859Sml29623 } 52623859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 52633859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 52643859Sml29623 } 52653859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 52663859Sml29623 statsp->xmac_stats.rx_localfault_err++; 52673859Sml29623 } 52683859Sml29623 } 52693859Sml29623 52703859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 52713859Sml29623 (xmac_ctl_iconfig_t *)&status); 52723859Sml29623 if (rs != NPI_SUCCESS) 52733859Sml29623 goto npi_fail; 52743859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 52753859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 52763859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 52773859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 52783859Sml29623 statsp->xmac_stats.tx_pause_state++; 52793859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 52803859Sml29623 statsp->xmac_stats.tx_nopause_state++; 52813859Sml29623 } 52823859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 52833859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 52843859Sml29623 (bmac_tx_iconfig_t *)&status); 52853859Sml29623 if (rs != NPI_SUCCESS) 52863859Sml29623 goto npi_fail; 52873859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 52883859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 52893859Sml29623 statsp->bmac_stats.tx_underrun_err++; 52903859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 52913859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 52923859Sml29623 } 52933859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 52943859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 52953859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 52963859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 52973859Sml29623 } 52983859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 52993859Sml29623 statsp->bmac_stats.tx_byte_cnt += 53003859Sml29623 BTXMAC_BYTE_CNT_MASK; 53013859Sml29623 } 53023859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 53033859Sml29623 statsp->bmac_stats.tx_frame_cnt += 53043859Sml29623 BTXMAC_FRM_CNT_MASK; 53053859Sml29623 } 53063859Sml29623 } 53073859Sml29623 53083859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 53093859Sml29623 (bmac_rx_iconfig_t *)&status); 53103859Sml29623 if (rs != NPI_SUCCESS) 53113859Sml29623 goto npi_fail; 53123859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 53133859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 53143859Sml29623 statsp->bmac_stats.rx_overflow_err++; 53153859Sml29623 } 53163859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 53173859Sml29623 statsp->bmac_stats.rx_frame_cnt += 53183859Sml29623 RXMAC_FRM_CNT_MASK; 53193859Sml29623 } 53203859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 53213859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 53223859Sml29623 BMAC_CRC_ER_CNT_MASK; 53233859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 53243859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 53253859Sml29623 } 53263859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 53273859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 53283859Sml29623 MAC_LEN_ER_CNT_MASK; 53293859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 53303859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 53313859Sml29623 } 53323859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 53333859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 53343859Sml29623 BMAC_CD_VIO_CNT_MASK; 53353859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 53363859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 53373859Sml29623 } 53383859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 53393859Sml29623 statsp->bmac_stats.rx_byte_cnt += 53403859Sml29623 BRXMAC_BYTE_CNT_MASK; 53413859Sml29623 } 53423859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 53433859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 53443859Sml29623 BMAC_AL_ER_CNT_MASK; 53453859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 53463859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 53473859Sml29623 } 53483859Sml29623 53493859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 53503859Sml29623 (bmac_ctl_iconfig_t *)&status); 53513859Sml29623 if (rs != NPI_SUCCESS) 53523859Sml29623 goto npi_fail; 53533859Sml29623 53543859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 53553859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 53563859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 53573859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 53583859Sml29623 statsp->bmac_stats.tx_pause_state++; 53593859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 53603859Sml29623 statsp->bmac_stats.tx_nopause_state++; 53613859Sml29623 } 53623859Sml29623 } 53633859Sml29623 53643859Sml29623 if (ldgp->nldvs == 1) { 53653859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 53663859Sml29623 B_TRUE, ldgp->ldg_timer); 53673859Sml29623 } 53683859Sml29623 53693859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 53703859Sml29623 return (DDI_INTR_CLAIMED); 53713859Sml29623 53723859Sml29623 npi_fail: 53733859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 53743859Sml29623 return (DDI_INTR_UNCLAIMED); 53753859Sml29623 } 53763859Sml29623 53773859Sml29623 nxge_status_t 53783859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 53793859Sml29623 { 53803859Sml29623 uint8_t phy_port_addr; 53813859Sml29623 nxge_status_t status = NXGE_OK; 53823859Sml29623 boolean_t rx_sig_ok; 53833859Sml29623 boolean_t pcs_blk_lock; 53843859Sml29623 boolean_t link_align; 53853859Sml29623 uint16_t val1, val2, val3; 53863859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 53873859Sml29623 uint16_t val_debug; 53883859Sml29623 uint16_t val; 53893859Sml29623 #endif 53903859Sml29623 53913859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 53923859Sml29623 53933859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 53943859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 53953859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 53963859Sml29623 if ((val_debug & ~0x200) != 0) { 53973859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 53983859Sml29623 nxgep->mac.portnum, val_debug); 53993859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 54003859Sml29623 &val_debug); 54013859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 54023859Sml29623 nxgep->mac.portnum, val_debug); 54033859Sml29623 } 54043859Sml29623 54053859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 54063859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 54073859Sml29623 if (val != 0) 54083859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 54093859Sml29623 54103859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 54113859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 54123859Sml29623 if (val != 0) 54133859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 54143859Sml29623 54153859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 54163859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 54173859Sml29623 if (val != 0) 54183859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 54193859Sml29623 #endif 54203859Sml29623 54213859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 54223859Sml29623 54233859Sml29623 /* Check Device 1 Register 0xA bit0 */ 54243859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 54253859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 54263859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 54273859Sml29623 &val1); 54283859Sml29623 if (status != NXGE_OK) 54293859Sml29623 goto fail; 54303859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 54313859Sml29623 54323859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 54333859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 54343859Sml29623 BCM8704_PCS_DEV_ADDR, 54353859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 54363859Sml29623 &val2)) != NPI_SUCCESS) 54373859Sml29623 goto fail; 54383859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 54393859Sml29623 54403859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 54413859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 54423859Sml29623 BCM8704_PHYXS_ADDR, 54433859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 54443859Sml29623 &val3); 54453859Sml29623 if (status != NXGE_OK) 54463859Sml29623 goto fail; 54475572Ssbehera 54485572Ssbehera switch (nxgep->chip_id) { 54495572Ssbehera case BCM8704_CHIP_ID: 54505572Ssbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 54515572Ssbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 54525572Ssbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 54535572Ssbehera break; 54545572Ssbehera case BCM8706_CHIP_ID: 54555572Ssbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 54565572Ssbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 54575572Ssbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 54585572Ssbehera B_TRUE : B_FALSE; 54595572Ssbehera break; 54605572Ssbehera default: 54615572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 54625572Ssbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 54635572Ssbehera goto fail; 54645572Ssbehera } 54655572Ssbehera 54663859Sml29623 54673859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 54683859Sml29623 /* Temp workaround for link down issue */ 54693859Sml29623 if (pcs_blk_lock == B_FALSE) { 54703859Sml29623 if (val2 != 0x4) { 54713859Sml29623 pcs_blk_lock = B_TRUE; 54723859Sml29623 cmn_err(CE_NOTE, 54733859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 54743859Sml29623 "Reg 0x20 = 0x%x\n", 54753859Sml29623 nxgep->mac.portnum, val2); 54763859Sml29623 } 54773859Sml29623 } 54783859Sml29623 54793859Sml29623 if (link_align == B_FALSE) { 54803859Sml29623 if (val3 != 0x140f) { 54813859Sml29623 link_align = B_TRUE; 54823859Sml29623 cmn_err(CE_NOTE, 54833859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 54843859Sml29623 "Reg 0x18 = 0x%x\n", 54853859Sml29623 nxgep->mac.portnum, val3); 54863859Sml29623 } 54873859Sml29623 } 54883859Sml29623 54893859Sml29623 if (rx_sig_ok == B_FALSE) { 54903859Sml29623 if ((val2 == 0) || (val3 == 0)) { 54913859Sml29623 rx_sig_ok = B_TRUE; 54923859Sml29623 cmn_err(CE_NOTE, 54933859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 54943859Sml29623 nxgep->mac.portnum); 54953859Sml29623 } 54963859Sml29623 } 54973859Sml29623 #endif 54983859Sml29623 54993859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 55003859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 55013859Sml29623 55023859Sml29623 return (NXGE_OK); 55033859Sml29623 fail: 55043859Sml29623 return (status); 55053859Sml29623 } 55063859Sml29623 55076604Ssbehera static nxge_status_t 55086604Ssbehera nxge_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 55096604Ssbehera { 55106604Ssbehera uint8_t phy; 55116604Ssbehera nxge_status_t status = NXGE_OK; 55126604Ssbehera boolean_t pma_status; 55136604Ssbehera boolean_t pcs_status; 55146604Ssbehera boolean_t xgxs_status; 55156604Ssbehera uint16_t val; 55166604Ssbehera 55176604Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 55186604Ssbehera 55196604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 55206604Ssbehera MRVL_88X2011_10G_PMD_STAT_2, &val); 55216604Ssbehera 55226604Ssbehera *link_up = B_FALSE; 55236604Ssbehera 55246604Ssbehera /* Check from Marvell 88X2011 if 10G link is up or down */ 55256604Ssbehera 55266604Ssbehera /* Check PMA/PMD Register: 1.0001.2 == 1 */ 55276604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 55286604Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 55296604Ssbehera 55306604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55316604Ssbehera "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 55326604Ssbehera 55336604Ssbehera pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 55346604Ssbehera 55356604Ssbehera /* Check PMC Register : 3.0001.2 == 1: read twice */ 55366604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 55376604Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 55386604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 55396604Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 55406604Ssbehera 55416604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55426604Ssbehera "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 55436604Ssbehera 55446604Ssbehera pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 55456604Ssbehera 55466604Ssbehera /* Check XGXS Register : 4.0018.[0-3,12] */ 55476604Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 55486604Ssbehera MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 55496604Ssbehera 55506604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55516604Ssbehera "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 55526604Ssbehera 55536604Ssbehera xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 55546604Ssbehera XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 55556604Ssbehera XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 55566604Ssbehera XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 55576604Ssbehera 55586604Ssbehera *link_up = (pma_status && pcs_status && xgxs_status) ? 55596604Ssbehera B_TRUE : B_FALSE; 55606604Ssbehera 55616604Ssbehera fail: 55626604Ssbehera 55636604Ssbehera if (*link_up == B_FALSE) { 55646604Ssbehera /* PCS OFF */ 55656604Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 55666604Ssbehera } else { 55676604Ssbehera /* PCS Activity */ 55686604Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 55696604Ssbehera } 55706604Ssbehera 55716604Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55726604Ssbehera " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 55736604Ssbehera 55746604Ssbehera return (status); 55756604Ssbehera } 55766604Ssbehera 55773859Sml29623 nxge_status_t 55783859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 55793859Sml29623 { 55803859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 55814732Sdavemq != NPI_SUCCESS) 55823859Sml29623 return (NXGE_ERROR); 55833859Sml29623 else 55843859Sml29623 return (NXGE_OK); 55853859Sml29623 } 55863859Sml29623 55873859Sml29623 nxge_status_t 55883859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 55893859Sml29623 { 55903859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 55914732Sdavemq != NPI_SUCCESS) 55923859Sml29623 return (NXGE_ERROR); 55933859Sml29623 else 55943859Sml29623 return (NXGE_OK); 55953859Sml29623 } 55964185Sspeer 55975572Ssbehera static boolean_t 55985572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 55995572Ssbehera { 56005572Ssbehera uint32_t pma_pmd_id = 0; 56015572Ssbehera uint32_t pcs_id = 0; 56025572Ssbehera uint32_t phy_id = 0; 56035572Ssbehera 56045572Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 56055572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56065572Ssbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 56075572Ssbehera if ((pma_pmd_id & mask) == (id & mask)) 56085572Ssbehera goto found_phy; 56095572Ssbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 56105572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56115572Ssbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 56125572Ssbehera if ((pcs_id & mask) == (id & mask)) 56135572Ssbehera goto found_phy; 56145572Ssbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 56155572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56165572Ssbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 56175572Ssbehera if ((phy_id & mask) == (id & mask)) 56185572Ssbehera goto found_phy; 56195572Ssbehera 56205572Ssbehera return (B_FALSE); 56215572Ssbehera 56225572Ssbehera found_phy: 56235572Ssbehera return (B_TRUE); 56245572Ssbehera } 56255572Ssbehera 56264732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 56274732Sdavemq 56284732Sdavemq static boolean_t 56294732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 56304732Sdavemq { 56314732Sdavemq int i; 56324732Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 56334732Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 56344732Sdavemq boolean_t found = B_FALSE; 56354732Sdavemq 56364732Sdavemq switch (type) { 56374732Sdavemq case CLAUSE_45_TYPE: 56384732Sdavemq for (i = 0; i < cl45_arr_len; i++) { 56394782Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 56404782Ssbehera (id & BCM_PHY_ID_MASK)) { 56414732Sdavemq found = B_TRUE; 56424732Sdavemq break; 56434732Sdavemq } 56444732Sdavemq } 56454732Sdavemq break; 56464732Sdavemq case CLAUSE_22_TYPE: 56474732Sdavemq for (i = 0; i < cl22_arr_len; i++) { 56484782Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 56494782Ssbehera (id & BCM_PHY_ID_MASK)) { 56504732Sdavemq found = B_TRUE; 56514732Sdavemq break; 56524732Sdavemq } 56534732Sdavemq } 56544732Sdavemq break; 56554732Sdavemq default: 56564732Sdavemq break; 56574732Sdavemq } 56584732Sdavemq 56594732Sdavemq return (found); 56604732Sdavemq } 56614732Sdavemq 56624977Sraghus static uint32_t 56634977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 56644977Sraghus { 56654977Sraghus uint16_t val1 = 0; 56664977Sraghus uint16_t val2 = 0; 56674977Sraghus uint32_t pma_pmd_dev_id = 0; 56684977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 56694977Sraghus 56705780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 56714977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 56724977Sraghus NXGE_DEV_ID_REG_1, &val1); 56734977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 56744977Sraghus NXGE_DEV_ID_REG_2, &val2); 56755780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 56764977Sraghus 56774977Sraghus pma_pmd_dev_id = val1; 56784977Sraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 56794977Sraghus pma_pmd_dev_id |= val2; 56804977Sraghus 56814977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 56824977Sraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 56834977Sraghus 56844977Sraghus return (pma_pmd_dev_id); 56854977Sraghus } 56864977Sraghus 56874977Sraghus static uint32_t 56884977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 56894977Sraghus { 56904977Sraghus uint16_t val1 = 0; 56914977Sraghus uint16_t val2 = 0; 56924977Sraghus uint32_t pcs_dev_id = 0; 56934977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 56944977Sraghus 56955780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 56964977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 56974977Sraghus NXGE_DEV_ID_REG_1, &val1); 56984977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 56994977Sraghus NXGE_DEV_ID_REG_2, &val2); 57005780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 57014977Sraghus 57024977Sraghus pcs_dev_id = val1; 57034977Sraghus pcs_dev_id = (pcs_dev_id << 16); 57044977Sraghus pcs_dev_id |= val2; 57054977Sraghus 57064977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 57074977Sraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 57084977Sraghus 57094977Sraghus return (pcs_dev_id); 57104977Sraghus } 57114977Sraghus 57124977Sraghus static uint32_t 57134977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 57144977Sraghus { 57154977Sraghus uint16_t val1 = 0; 57164977Sraghus uint16_t val2 = 0; 57174977Sraghus uint32_t phy_id = 0; 57184977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 57194977Sraghus npi_status_t npi_status = NPI_SUCCESS; 57204977Sraghus 57216075Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 57224977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 57234977Sraghus &val1); 57244977Sraghus if (npi_status != NPI_SUCCESS) { 57254977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 57264977Sraghus "clause 22 read to reg 2 failed!!!")); 57274977Sraghus goto exit; 57284977Sraghus } 57294977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 57304977Sraghus &val2); 57314977Sraghus if (npi_status != 0) { 57324977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 57334977Sraghus "clause 22 read to reg 3 failed!!!")); 57344977Sraghus goto exit; 57354977Sraghus } 57364977Sraghus phy_id = val1; 57374977Sraghus phy_id = (phy_id << 16); 57384977Sraghus phy_id |= val2; 57394977Sraghus 57404977Sraghus exit: 57416075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 57424977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 57434977Sraghus phy_port, phy_id)); 57444977Sraghus 57454977Sraghus return (phy_id); 57464977Sraghus } 57474977Sraghus 57484732Sdavemq /* 57494732Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 57504732Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 57514732Sdavemq * read. Then use the values obtained to determine the phy type of each port 57524732Sdavemq * and the Neptune type. 57534732Sdavemq */ 57544732Sdavemq 57554732Sdavemq nxge_status_t 57564732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 57574732Sdavemq { 57586261Sjoycey int i, j, l; 57594732Sdavemq uint32_t pma_pmd_dev_id = 0; 57604732Sdavemq uint32_t pcs_dev_id = 0; 57614732Sdavemq uint32_t phy_id = 0; 57624782Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 57634782Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 57644782Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 57654732Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 57664732Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 57675572Ssbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 57685572Ssbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 57694732Sdavemq uint8_t total_port_fd, total_phy_fd; 57704732Sdavemq nxge_status_t status = NXGE_OK; 57714732Sdavemq 57724732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 57734732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 57744732Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 57754732Sdavemq nxgep->niu_type)); 57764732Sdavemq 57776495Sspeer if (isLDOMguest(nxgep)) { 57786495Sspeer hw_p->niu_type = NIU_TYPE_NONE; 57796495Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 57806495Sspeer return (NXGE_OK); 57816495Sspeer } 57826495Sspeer 57836261Sjoycey j = l = 0; 57844732Sdavemq total_port_fd = total_phy_fd = 0; 57854732Sdavemq /* 57864732Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 57874732Sdavemq * for on chip serdes usages. 57884732Sdavemq */ 57894732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 57904977Sraghus 57914977Sraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 57924732Sdavemq 57934732Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 57944732Sdavemq pma_pmd_dev_fd[i] = 1; 57954732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 57966604Ssbehera "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 57974782Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 57984782Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 57994782Ssbehera BCM_PHY_ID_MASK; 58005572Ssbehera port_fd_arr[j] = (uint8_t)i; 58014732Sdavemq j++; 58024732Sdavemq } 58034732Sdavemq } else { 58044732Sdavemq pma_pmd_dev_fd[i] = 0; 58054732Sdavemq } 58064732Sdavemq 58074977Sraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 58084732Sdavemq 58094732Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 58104732Sdavemq pcs_dev_fd[i] = 1; 58114732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 58126604Ssbehera "dev %x found", i, pcs_dev_id)); 58136261Sjoycey if (pma_pmd_dev_fd[i] == 1) { 58146261Sjoycey port_pcs_dev_id[j - 1] = pcs_dev_id & 58154782Ssbehera BCM_PHY_ID_MASK; 58166261Sjoycey } else { 58176261Sjoycey if (j < NXGE_PORTS_NEPTUNE) { 58186261Sjoycey port_pcs_dev_id[j] = pcs_dev_id & 58196261Sjoycey BCM_PHY_ID_MASK; 58206261Sjoycey port_fd_arr[j] = (uint8_t)i; 58216261Sjoycey j++; 58226261Sjoycey } 58234732Sdavemq } 58244732Sdavemq } else { 58254732Sdavemq pcs_dev_fd[i] = 0; 58264732Sdavemq } 58274732Sdavemq 58285572Ssbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 58295572Ssbehera total_port_fd ++; 58305572Ssbehera } 58314732Sdavemq 58324977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 58334732Sdavemq 58344732Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 58355572Ssbehera total_phy_fd ++; 58364732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 58376604Ssbehera "%x found", i, phy_id)); 58384782Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 58394782Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 58405572Ssbehera phy_fd_arr[l] = (uint8_t)i; 58414732Sdavemq l++; 58424732Sdavemq } 58434732Sdavemq } 58444732Sdavemq } 58454732Sdavemq 58464732Sdavemq switch (total_port_fd) { 58474732Sdavemq case 2: 58484732Sdavemq switch (total_phy_fd) { 58494732Sdavemq case 2: 58506261Sjoycey /* 2 10G, 2 1G RGMII Fiber */ 58516261Sjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 58526261Sjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 58536261Sjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 58546261Sjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 58556261Sjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 58566261Sjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 58576261Sjoycey 58586261Sjoycey hw_p->platform_type = 58596261Sjoycey P_NEPTUNE_GENERIC; 58606261Sjoycey 58616261Sjoycey hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 58626261Sjoycey 58636261Sjoycey hw_p->xcvr_addr[0] = port_fd_arr[0]; 58646261Sjoycey hw_p->xcvr_addr[1] = port_fd_arr[1]; 58656261Sjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 58666261Sjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 58676261Sjoycey 58686261Sjoycey NXGE_DEBUG_MSG((nxgep, MAC_CTL, 58696261Sjoycey "ARTM card with 2 10G, 2 1G")); 58706261Sjoycey } else { 58716261Sjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58726261Sjoycey "Unsupported neptune type 1")); 58736261Sjoycey goto error_exit; 58746261Sjoycey } 58756261Sjoycey break; 58766261Sjoycey 58774732Sdavemq case 1: 58784732Sdavemq /* TODO - 2 10G, 1 1G */ 58794732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 58804732Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 58814732Sdavemq goto error_exit; 58824732Sdavemq case 0: 58834732Sdavemq /* 2 10G */ 58844782Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 58854782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 58864782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 58876604Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 58886604Ssbehera ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 58896604Ssbehera (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 58906604Ssbehera ((port_pma_pmd_dev_id[0] == 58916604Ssbehera MARVELL_88X201X_PHY_ID) && 58926604Ssbehera (port_pma_pmd_dev_id[1] == 58936604Ssbehera MARVELL_88X201X_PHY_ID))) { 58944977Sraghus 58954977Sraghus /* 58964977Sraghus * Check the first phy port address against 58974977Sraghus * the known phy start addresses to determine 58984977Sraghus * the platform type. 58994977Sraghus */ 59005572Ssbehera 59015572Ssbehera switch (port_fd_arr[0]) { 59025572Ssbehera case BCM8704_NEPTUNE_PORT_ADDR_BASE: 59036604Ssbehera /* 59046604Ssbehera * The Marvell case also falls into 59056604Ssbehera * this case as 59066604Ssbehera * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 59076604Ssbehera * == BCM8704_NEPTUNE_PORT_ADDR_BASE. 59086604Ssbehera * This is OK for the 2 10G case. 59096604Ssbehera */ 59104977Sraghus hw_p->niu_type = NEPTUNE_2_10GF; 59114977Sraghus hw_p->platform_type = 59124977Sraghus P_NEPTUNE_ATLAS_2PORT; 59135572Ssbehera break; 59145572Ssbehera case BCM8706_GOA_PORT_ADDR_BASE: 59155572Ssbehera if (hw_p->platform_type != 59165572Ssbehera P_NEPTUNE_NIU) { 59175572Ssbehera hw_p->platform_type = 59185572Ssbehera P_NEPTUNE_GENERIC; 59195572Ssbehera hw_p->niu_type = 59205572Ssbehera NEPTUNE_2_10GF; 59215572Ssbehera } 59225572Ssbehera break; 59235572Ssbehera default: 59245572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59254977Sraghus "Unsupported neptune type 2 - 1")); 59264977Sraghus goto error_exit; 59274977Sraghus } 59285572Ssbehera 59295572Ssbehera for (i = 0; i < 2; i++) { 59305572Ssbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 59315572Ssbehera } 59324732Sdavemq } else { 59334732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 59344732Sdavemq "Unsupported neptune type 2")); 59354732Sdavemq goto error_exit; 59364732Sdavemq } 59374732Sdavemq break; 59384732Sdavemq case 4: 59394732Sdavemq /* Maramba with 2 XAUI */ 59404782Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 59414782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 59424782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 59434782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 59444782Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 59454782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 59464782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 59474782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 59484732Sdavemq 59494732Sdavemq /* 59504732Sdavemq * Check the first phy port address against 59514732Sdavemq * the known phy start addresses to determine 59524732Sdavemq * the platform type. 59534732Sdavemq */ 59545572Ssbehera switch (phy_fd_arr[0]) { 59555572Ssbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 59564732Sdavemq hw_p->platform_type = 59574732Sdavemq P_NEPTUNE_MARAMBA_P0; 59585572Ssbehera break; 59595572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 59604732Sdavemq hw_p->platform_type = 59614732Sdavemq P_NEPTUNE_MARAMBA_P1; 59625572Ssbehera break; 59635572Ssbehera default: 59644732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 59654732Sdavemq "Unknown port %d...Cannot " 59664732Sdavemq "determine platform type", i)); 59674977Sraghus goto error_exit; 59684732Sdavemq } 59695572Ssbehera 59704977Sraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 59714977Sraghus 59725572Ssbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 59735572Ssbehera hw_p->xcvr_addr[1] = port_fd_arr[1]; 59745572Ssbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 59755572Ssbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 59765572Ssbehera 59774732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 59784732Sdavemq "Maramba with 2 XAUI")); 59794732Sdavemq } else { 59804732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 59814732Sdavemq "Unsupported neptune type 3")); 59824732Sdavemq goto error_exit; 59834732Sdavemq } 59844732Sdavemq break; 59854732Sdavemq default: 59864732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 59874732Sdavemq "Unsupported neptune type 5")); 59884732Sdavemq goto error_exit; 59894732Sdavemq } 59904782Ssbehera break; 59914732Sdavemq case 1: 59924732Sdavemq switch (total_phy_fd) { 59934732Sdavemq case 3: 59944977Sraghus /* 59954977Sraghus * TODO 3 1G, 1 10G mode. 59964977Sraghus * Differentiate between 1_1G_1_10G_2_1G and 59974977Sraghus * 1_10G_3_1G 59984977Sraghus */ 59994977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60004977Sraghus "Unsupported neptune type 7")); 60014977Sraghus goto error_exit; 60024732Sdavemq case 2: 60034732Sdavemq /* 60044732Sdavemq * TODO 2 1G, 1 10G mode. 60054732Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 60064732Sdavemq * 1_10G_2_1G 60074732Sdavemq */ 60084732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60094732Sdavemq "Unsupported neptune type 8")); 60104732Sdavemq goto error_exit; 60114732Sdavemq case 1: 60124732Sdavemq /* 60134732Sdavemq * TODO 1 1G, 1 10G mode. 60144732Sdavemq * Differentiate between 1_1G_1_10G and 60154732Sdavemq * 1_10G_1_1G 60164732Sdavemq */ 60174732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60184732Sdavemq "Unsupported neptune type 9")); 60194732Sdavemq goto error_exit; 60204732Sdavemq case 0: 60215572Ssbehera /* 1 10G mode, N2 with 1 XAUI */ 60225572Ssbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 60235572Ssbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 60245572Ssbehera 60255572Ssbehera /* 60265572Ssbehera * Check the first phy port address against 60275572Ssbehera * the known phy start addresses to determine 60285572Ssbehera * the platform type. 60295572Ssbehera */ 60305572Ssbehera 60315572Ssbehera switch (port_fd_arr[0]) { 60325572Ssbehera case BCM8704_N2_PORT_ADDR_BASE: 60335572Ssbehera case (BCM8704_N2_PORT_ADDR_BASE + 1): 60345572Ssbehera case BCM8706_ALT_GOA_PORT1_ADDR: 60355572Ssbehera if (hw_p->platform_type != 60365572Ssbehera P_NEPTUNE_NIU) { 60375572Ssbehera hw_p->platform_type = 60385572Ssbehera P_NEPTUNE_GENERIC; 60395572Ssbehera hw_p->niu_type = 60405572Ssbehera NEPTUNE_2_10GF; 60415572Ssbehera } 60425572Ssbehera break; 60435572Ssbehera default: 60445572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60455572Ssbehera "Unsupported neptune type 10")); 60465572Ssbehera goto error_exit; 60475572Ssbehera } 60486075Ssbehera /* 60496075Ssbehera * For GOA, which is a hot swappable PHY, the 60506075Ssbehera * phy address to function number mapping 60516075Ssbehera * should be preserved, i.e., addr 16 is 60526075Ssbehera * assigned to function 0 and 20 to function 1 60536075Ssbehera * But for Huron XAUI, the assignment should 60546075Ssbehera * be by function number, i.e., whichever 60556075Ssbehera * function number attaches should be 60566075Ssbehera * assigned the available PHY (this is required 60576075Ssbehera * primarily to support pre-production Huron 60586075Ssbehera * boards where function 0 is mapped to addr 17 60596075Ssbehera */ 60606075Ssbehera if (port_fd_arr[0] == 60616075Ssbehera BCM8706_ALT_GOA_PORT1_ADDR) { 60626075Ssbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 60636075Ssbehera } else { 60646075Ssbehera hw_p->xcvr_addr[nxgep->function_num] = 60656075Ssbehera port_fd_arr[0]; 60666075Ssbehera } 60675572Ssbehera } else { 60685572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60695572Ssbehera "Unsupported neptune type 10 - 1")); 60705572Ssbehera goto error_exit; 60715572Ssbehera } 60725572Ssbehera break; 60734732Sdavemq case 4: 60744732Sdavemq /* Maramba with 1 XAUI */ 60754782Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 60764782Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 60774732Sdavemq 60784732Sdavemq /* 60794732Sdavemq * Check the first phy port address against 60804732Sdavemq * the known phy start addresses to determine 60814732Sdavemq * the platform type. 60824732Sdavemq */ 60835572Ssbehera switch (phy_fd_arr[0]) { 60845572Ssbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 60854732Sdavemq hw_p->platform_type = 60864732Sdavemq P_NEPTUNE_MARAMBA_P0; 60875572Ssbehera break; 60885572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 60894732Sdavemq hw_p->platform_type = 60904732Sdavemq P_NEPTUNE_MARAMBA_P1; 60915572Ssbehera break; 60925572Ssbehera default: 60934732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60944732Sdavemq "Unknown port %d...Cannot " 60955572Ssbehera "determine platform type 10 - 2", 60965572Ssbehera i)); 60974977Sraghus goto error_exit; 60984977Sraghus } 60994977Sraghus 61005572Ssbehera /* 61015572Ssbehera * Check the BCM8704 address to determine 61025572Ssbehera * if XAUI is in port 0 or port 1. 61035572Ssbehera */ 61045572Ssbehera switch (port_fd_arr[0]) { 61055572Ssbehera case BCM8704_MARAMBA_PORT_ADDR_BASE: 61065572Ssbehera hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 61075572Ssbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 61085572Ssbehera for (i = 1; i < NXGE_MAX_PORTS; i++) { 61095572Ssbehera hw_p->xcvr_addr[i] = 61105572Ssbehera phy_fd_arr[i]; 61114977Sraghus } 61125572Ssbehera break; 61135572Ssbehera case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1): 61144977Sraghus hw_p->niu_type = 61154977Sraghus NEPTUNE_1_1GC_1_10GF_2_1GC; 61165572Ssbehera hw_p->xcvr_addr[0] = phy_fd_arr[0]; 61175572Ssbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 61185572Ssbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 61195572Ssbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 61205572Ssbehera break; 61215572Ssbehera default: 61224977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61234977Sraghus "Unsupported neptune type 11")); 61244977Sraghus goto error_exit; 61254732Sdavemq } 61264732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61274732Sdavemq "Maramba with 1 XAUI")); 61284732Sdavemq } else { 61294732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61304732Sdavemq "Unsupported neptune type 12")); 61314732Sdavemq goto error_exit; 61324732Sdavemq } 61334732Sdavemq break; 61344732Sdavemq default: 61354732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61364732Sdavemq "Unsupported neptune type 13")); 61374732Sdavemq goto error_exit; 61384732Sdavemq } 61394732Sdavemq break; 61404732Sdavemq case 0: 61414732Sdavemq switch (total_phy_fd) { 61424732Sdavemq case 4: 61434782Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 61444782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 61454782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 61464782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 61474732Sdavemq 61484732Sdavemq /* 61494732Sdavemq * Check the first phy port address against 61504732Sdavemq * the known phy start addresses to determine 61514732Sdavemq * the platform type. 61524732Sdavemq */ 61535572Ssbehera switch (phy_fd_arr[0]) { 61545572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 61554732Sdavemq hw_p->platform_type = 61564732Sdavemq P_NEPTUNE_MARAMBA_P1; 61575572Ssbehera break; 61585572Ssbehera case BCM5464_NEPTUNE_PORT_ADDR_BASE: 61594977Sraghus hw_p->platform_type = 61604977Sraghus P_NEPTUNE_ATLAS_4PORT; 61615572Ssbehera break; 61625572Ssbehera default: 61634977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61644977Sraghus "Unknown port %d...Cannot " 61654977Sraghus "determine platform type", i)); 61664977Sraghus goto error_exit; 61674732Sdavemq } 61684977Sraghus hw_p->niu_type = NEPTUNE_4_1GC; 61695572Ssbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 61705572Ssbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 61715572Ssbehera } 61724732Sdavemq } else { 61734732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61744732Sdavemq "Unsupported neptune type 14")); 61754732Sdavemq goto error_exit; 61764732Sdavemq } 61774732Sdavemq break; 61784732Sdavemq case 3: 61794732Sdavemq /* TODO 3 1G mode */ 61804732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61814732Sdavemq "Unsupported neptune type 15")); 61824732Sdavemq goto error_exit; 61834732Sdavemq case 2: 61844732Sdavemq /* TODO 2 1G mode */ 61856261Sjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 61866261Sjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 61876261Sjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 61886261Sjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 61896261Sjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 61906261Sjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 61916261Sjoycey } else { 61926261Sjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 61936261Sjoycey "Unsupported neptune type 16")); 61946261Sjoycey goto error_exit; 61956261Sjoycey } 61964732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61976261Sjoycey "2 RGMII Fiber ports - RTM")); 61986261Sjoycey break; 61996261Sjoycey 62004732Sdavemq case 1: 62014732Sdavemq /* TODO 1 1G mode */ 62024732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62034732Sdavemq "Unsupported neptune type 17")); 62044732Sdavemq goto error_exit; 62054732Sdavemq default: 62064732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62074732Sdavemq "Unsupported neptune type 18, total phy fd %d", 62084732Sdavemq total_phy_fd)); 62094732Sdavemq goto error_exit; 62104732Sdavemq } 62114732Sdavemq break; 62124732Sdavemq default: 62134732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 62144732Sdavemq "Unsupported neptune type 19")); 62154732Sdavemq goto error_exit; 62164732Sdavemq } 62174732Sdavemq 62184732Sdavemq scan_exit: 62194732Sdavemq 62204732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 62214732Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 62224732Sdavemq return (status); 62234732Sdavemq 62244732Sdavemq error_exit: 62254732Sdavemq return (NXGE_ERROR); 62264732Sdavemq } 62274732Sdavemq 62284185Sspeer boolean_t 62294185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 62304185Sspeer { 62314185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 62324185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 62334185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 62344185Sspeer return (B_FALSE); 62354185Sspeer else 62364185Sspeer return (B_TRUE); 62374185Sspeer } 62384732Sdavemq 62394732Sdavemq static void 62404732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 62414732Sdavemq 62424732Sdavemq npi_status_t rs = NPI_SUCCESS; 62434732Sdavemq uint8_t xcvr_portn; 62444732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 62454732Sdavemq 62464732Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 62474732Sdavemq 62484732Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 62494732Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 62504732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 62514732Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 62524732Sdavemq } 62534732Sdavemq /* 62544732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 62554732Sdavemq * swapped with ethernet port number. This is 62564732Sdavemq * designed for better signal integrity in routing. 62574732Sdavemq */ 62584732Sdavemq switch (portn) { 62594732Sdavemq case 0: 62604732Sdavemq xcvr_portn += 3; 62614732Sdavemq break; 62624732Sdavemq case 1: 62634732Sdavemq xcvr_portn += 2; 62644732Sdavemq break; 62654732Sdavemq case 2: 62664732Sdavemq xcvr_portn += 1; 62674732Sdavemq break; 62684732Sdavemq case 3: 62694732Sdavemq default: 62704732Sdavemq break; 62714732Sdavemq } 62724732Sdavemq 62736075Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 62744732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 62754732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 62764732Sdavemq if (rs != NPI_SUCCESS) { 62774732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62784732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 62794732Sdavemq "returned error 0x[%x]", rs)); 62806075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 62814732Sdavemq return; 62824732Sdavemq } 62834732Sdavemq 62844732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 62854732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 62864732Sdavemq if (rs != NPI_SUCCESS) { 62874732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 62884732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 62894732Sdavemq "returned error 0x[%x]", rs)); 62904732Sdavemq } 62914732Sdavemq 62926075Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 62934732Sdavemq } 62945196Ssbehera 62955196Ssbehera static nxge_status_t 62965196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 62975196Ssbehera { 62985196Ssbehera p_nxge_stats_t statsp; 62995196Ssbehera uint8_t xcvr_portn; 63005196Ssbehera p_mii_regs_t mii_regs; 63015196Ssbehera mii_mode_control_stat_t mode; 63025196Ssbehera int status = NXGE_OK; 63035196Ssbehera 63045196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 63055196Ssbehera 63065196Ssbehera statsp = nxgep->statsp; 63075196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 63085196Ssbehera mii_regs = NULL; 63095196Ssbehera mode.value = 0; 63105203Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 63115196Ssbehera #if defined(__i386) 63125196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 63135196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 63145196Ssbehera mode.value)) != NXGE_OK) { 63155196Ssbehera goto fail; 63165196Ssbehera #else 63175196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 63185196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 63195196Ssbehera mode.value)) != NXGE_OK) { 63205196Ssbehera goto fail; 63215196Ssbehera #endif 63225196Ssbehera } 63235196Ssbehera #if defined(__i386) 63245196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 63255196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 63265196Ssbehera &mode.value)) != NXGE_OK) { 63275196Ssbehera goto fail; 63285196Ssbehera } 63295196Ssbehera #else 63305196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 63315196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 63325196Ssbehera &mode.value)) != NXGE_OK) { 63335196Ssbehera goto fail; 63345196Ssbehera } 63355196Ssbehera #endif 63365196Ssbehera 63375196Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 63385196Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 63395196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63405196Ssbehera "nxge_mii_get_link_mode: fiber mode")); 63415196Ssbehera } 63425196Ssbehera 63435196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63445196Ssbehera "nxge_mii_get_link_mode: " 63455196Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 63465203Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 63475196Ssbehera mode.value, nxgep->mac.portmode)); 63485196Ssbehera 63495196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63505196Ssbehera "<== nxge_mii_get_link_mode")); 63515196Ssbehera return (status); 63525196Ssbehera fail: 63535196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 63545196Ssbehera "<== nxge_mii_get_link_mode (failed)")); 63555196Ssbehera return (NXGE_ERROR); 63565196Ssbehera } 63575196Ssbehera 63586439Sml29623 nxge_status_t 63596439Sml29623 nxge_mac_set_framesize(p_nxge_t nxgep) 63606439Sml29623 { 63616439Sml29623 npi_attr_t ap; 63626439Sml29623 uint8_t portn; 63636439Sml29623 npi_handle_t handle; 63646439Sml29623 npi_status_t rs = NPI_SUCCESS; 63656439Sml29623 63666439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 63676439Sml29623 63686439Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 63696439Sml29623 handle = nxgep->npi_handle; 63706439Sml29623 63716439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63726439Sml29623 "==> nxge_mac_sec_framesize: port<%d> " 63736439Sml29623 "min framesize %d max framesize %d ", 63746439Sml29623 portn, 63756439Sml29623 nxgep->mac.minframesize, 63766439Sml29623 nxgep->mac.maxframesize)); 63776439Sml29623 63786439Sml29623 SET_MAC_ATTR2(handle, ap, portn, 63796439Sml29623 MAC_PORT_FRAME_SIZE, 63806439Sml29623 nxgep->mac.minframesize, 63816439Sml29623 nxgep->mac.maxframesize, 63826439Sml29623 rs); 63836439Sml29623 if (rs != NPI_SUCCESS) { 63846439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63856439Sml29623 "<== nxge_mac_set_framesize: failed to configure " 63866439Sml29623 "max/min frame size port %d", portn)); 63876439Sml29623 63886439Sml29623 return (NXGE_ERROR | rs); 63896439Sml29623 } 63906439Sml29623 63916439Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63926439Sml29623 "<== nxge_mac_set_framesize: port<%d>", portn)); 63936439Sml29623 63946439Sml29623 return (NXGE_OK); 63956439Sml29623 } 63966439Sml29623 63975196Ssbehera #ifdef NXGE_DEBUG 63985196Ssbehera static void 63995196Ssbehera nxge_mii_dump(p_nxge_t nxgep) 64005196Ssbehera { 64015196Ssbehera p_nxge_stats_t statsp; 64025196Ssbehera uint8_t xcvr_portn; 64035196Ssbehera p_mii_regs_t mii_regs; 64045196Ssbehera mii_bmcr_t bmcr; 64055196Ssbehera mii_bmsr_t bmsr; 64065196Ssbehera mii_idr1_t idr1; 64075196Ssbehera mii_idr2_t idr2; 64085196Ssbehera mii_mode_control_stat_t mode; 64096495Sspeer p_nxge_param_t param_arr; 64105196Ssbehera 64115196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 64125196Ssbehera 64135196Ssbehera statsp = nxgep->statsp; 64145196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 64155196Ssbehera 64165196Ssbehera mii_regs = NULL; 64175196Ssbehera 64185196Ssbehera #if defined(__i386) 64195196Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 64205196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 64215196Ssbehera #else 64225196Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 64235196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 64245196Ssbehera #endif 64255196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 64265196Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 64275196Ssbehera xcvr_portn, bmcr.value)); 64285196Ssbehera 64295196Ssbehera #if defined(__i386) 64305196Ssbehera (void) nxge_mii_read(nxgep, 64315196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64325196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 64335196Ssbehera #else 64345196Ssbehera (void) nxge_mii_read(nxgep, 64355196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64365196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 64375196Ssbehera #endif 64385196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 64395196Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 64405196Ssbehera xcvr_portn, bmsr.value)); 64415196Ssbehera 64425196Ssbehera #if defined(__i386) 64435196Ssbehera (void) nxge_mii_read(nxgep, 64445196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64455196Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 64465196Ssbehera #else 64475196Ssbehera (void) nxge_mii_read(nxgep, 64485196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64495196Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 64505196Ssbehera #endif 64515196Ssbehera 64525196Ssbehera 64535196Ssbehera #if defined(__i386) 64545196Ssbehera (void) nxge_mii_read(nxgep, 64555196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64565196Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 64575196Ssbehera #else 64585196Ssbehera (void) nxge_mii_read(nxgep, 64595196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 64605196Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 64615196Ssbehera #endif 64625196Ssbehera 64635196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 64645196Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 64655196Ssbehera xcvr_portn, idr1.value)); 64665196Ssbehera 64675196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 64685196Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 64695196Ssbehera xcvr_portn, idr2.value)); 64705196Ssbehera 64715196Ssbehera mode.value = 0; 64725203Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 64735196Ssbehera 64745196Ssbehera #if defined(__i386) 64755196Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 64765196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 64775196Ssbehera 64785196Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 64795196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 64805196Ssbehera #else 64815196Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 64825196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 64835196Ssbehera 64845196Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 64855196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 64865196Ssbehera #endif 64875196Ssbehera 64885196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 64895196Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 64905196Ssbehera xcvr_portn, mode.value)); 64915196Ssbehera } 64925196Ssbehera #endif 6493