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> 303859Sml29623 314693Stm144005 #define LINK_MONITOR_PERIOD (1000 * 1000) 324693Stm144005 #define LM_WAIT_MULTIPLIER 8 334693Stm144005 343859Sml29623 extern uint32_t nxge_no_link_notify; 354732Sdavemq extern boolean_t nxge_no_msg; 363859Sml29623 extern uint32_t nxge_lb_dbg; 373859Sml29623 extern boolean_t nxge_jumbo_enable; 38*6028Ssbehera extern uint32_t nxge_jumbo_mtu; 393859Sml29623 404693Stm144005 typedef enum { 414693Stm144005 CHECK_LINK_RESCHEDULE, 424693Stm144005 CHECK_LINK_STOP 434693Stm144005 } check_link_state_t; 444693Stm144005 454693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *); 464693Stm144005 473859Sml29623 /* 483859Sml29623 * Ethernet broadcast address definition. 493859Sml29623 */ 503859Sml29623 static ether_addr_st etherbroadcastaddr = 513859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 524732Sdavemq /* 534732Sdavemq * Ethernet zero address definition. 544732Sdavemq */ 554185Sspeer static ether_addr_st etherzeroaddr = 564185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 574732Sdavemq /* 584732Sdavemq * Supported chip types 594732Sdavemq */ 605572Ssbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID}; 614732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 624732Sdavemq 634732Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 644732Sdavemq sizeof (uint32_t)) 654732Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 664732Sdavemq sizeof (uint32_t)) 674732Sdavemq /* 684732Sdavemq * static functions 694732Sdavemq */ 704977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 714977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 724977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 734732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 745572Ssbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 754732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 764732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 774732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 784732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 794732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 804732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 814732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 824732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 834732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 844732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 854732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 864732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 875572Ssbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 885572Ssbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 894732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 904732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 914732Sdavemq 924732Sdavemq /* 934732Sdavemq * xcvr tables for supported transceivers 944732Sdavemq */ 954732Sdavemq 964977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 974732Sdavemq nxge_n2_serdes_init, 984732Sdavemq nxge_10G_xcvr_init, 994732Sdavemq nxge_10G_link_intr_stop, 1004732Sdavemq nxge_10G_link_intr_start, 1014732Sdavemq nxge_check_10g_link, 1025572Ssbehera PCS_XCVR 1034732Sdavemq }; 1044732Sdavemq 1054977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1064977Sraghus nxge_n2_serdes_init, 1074977Sraghus nxge_1G_xcvr_init, 1084977Sraghus nxge_1G_fiber_link_intr_stop, 1094977Sraghus nxge_1G_fiber_link_intr_start, 1104977Sraghus nxge_check_mii_link, 1115572Ssbehera PCS_XCVR 1124977Sraghus }; 1134977Sraghus 1144732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 1154732Sdavemq nxge_neptune_10G_serdes_init, 1164732Sdavemq nxge_10G_xcvr_init, 1174732Sdavemq nxge_10G_link_intr_stop, 1184732Sdavemq nxge_10G_link_intr_start, 1194732Sdavemq nxge_check_10g_link, 1205572Ssbehera PCS_XCVR 1214732Sdavemq }; 1224732Sdavemq 1234732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 1244732Sdavemq NULL, 1254732Sdavemq nxge_1G_xcvr_init, 1264732Sdavemq nxge_1G_copper_link_intr_stop, 1274732Sdavemq nxge_1G_copper_link_intr_start, 1284732Sdavemq nxge_check_mii_link, 1295572Ssbehera INT_MII_XCVR 1304732Sdavemq }; 1314732Sdavemq 1324732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 1334732Sdavemq nxge_1G_serdes_init, 1344732Sdavemq nxge_1G_xcvr_init, 1354732Sdavemq nxge_1G_fiber_link_intr_stop, 1364732Sdavemq nxge_1G_fiber_link_intr_start, 1374732Sdavemq nxge_check_mii_link, 1385572Ssbehera PCS_XCVR 1394732Sdavemq }; 1404732Sdavemq 1414732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 1424732Sdavemq nxge_neptune_10G_serdes_init, 1434732Sdavemq NULL, 1444732Sdavemq NULL, 1454732Sdavemq NULL, 1464977Sraghus NULL, 1475572Ssbehera PCS_XCVR 1484732Sdavemq }; 1493859Sml29623 1503859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 1513859Sml29623 1525196Ssbehera #ifdef NXGE_DEBUG 1535196Ssbehera static void nxge_mii_dump(p_nxge_t); 1545196Ssbehera #endif 1555196Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 1565196Ssbehera 1574977Sraghus nxge_status_t 1584977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep) 1594977Sraghus { 1604977Sraghus nxge_status_t status = NXGE_OK; 1614977Sraghus char *phy_type; 1624977Sraghus char *prop_val; 1634977Sraghus 1644977Sraghus nxgep->mac.portmode = 0; 1655572Ssbehera nxgep->xcvr_addr = 0; 1665572Ssbehera 1675572Ssbehera /* 1685572Ssbehera * First check for hot swappable phy property. 1695572Ssbehera */ 1705572Ssbehera if (nxgep->hot_swappable_phy == B_TRUE) { 1715572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1725572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 1735572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 1745572Ssbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 1755572Ssbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1765572Ssbehera "hot-swappable-phy") == 1) { 1775572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1785572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 1795572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 1805572Ssbehera } else if (nxgep->niu_type == N2_NIU && 1815572Ssbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 1825572Ssbehera "hot-swappable-phy") == 1) { 1835572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1845572Ssbehera nxgep->mac.portmode = PORT_HSP_MODE; 1855572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 1865572Ssbehera } 1875572Ssbehera 1885572Ssbehera /* 1895572Ssbehera * MDIO polling support for Monza RTM card, Goa NEM card 1905572Ssbehera */ 1915572Ssbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 1925572Ssbehera 1935572Ssbehera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1945572Ssbehera 1955572Ssbehera nxgep->hot_swappable_phy = B_TRUE; 1965572Ssbehera /* 1975572Ssbehera * If this is the 2nd NIU port, then check 2 addresses 1985572Ssbehera * to take care of the Goa NEM card. Port 1 can have addr 17 1995572Ssbehera * (in the eval board) or 20 (in the P0 board). 2005572Ssbehera */ 2015572Ssbehera if (portn == 1) { 2025572Ssbehera if (nxge_is_phy_present(nxgep, 2035572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID, 2045572Ssbehera BCM_PHY_ID_MASK)) { 2055572Ssbehera nxgep->xcvr_addr = 2065572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR; 2075572Ssbehera goto found_phy; 2085572Ssbehera } 2095572Ssbehera } 2105572Ssbehera if (nxge_is_phy_present(nxgep, 2115572Ssbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 2125572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 2135572Ssbehera nxgep->xcvr_addr = (BCM8706_GOA_PORT_ADDR_BASE) + 2145572Ssbehera portn; 2155572Ssbehera goto found_phy; 2165572Ssbehera } 2175572Ssbehera 2185572Ssbehera nxgep->phy_absent = B_TRUE; 2195572Ssbehera goto check_phy_done; 2205572Ssbehera found_phy: 2215572Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2225572Ssbehera nxgep->mac.portmode = PORT_10G_FIBER; 2235572Ssbehera nxgep->phy_absent = B_FALSE; 2245572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 2255572Ssbehera "found for hot swappable phy")); 2265572Ssbehera check_phy_done: 2275572Ssbehera return (status); 2285572Ssbehera } 2295572Ssbehera 2305572Ssbehera /* Get phy-type property from the driver conf. file */ 2314977Sraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 2324977Sraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2334977Sraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 2344977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2354977Sraghus "found conf file: phy-type %s", prop_val)); 2364977Sraghus if (strcmp("xgsd", prop_val) == 0) { 2374977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2384977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 2394977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2404977Sraghus "found: 10G Serdes")); 2414977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 2424977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2434977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 2444977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 2454977Sraghus } else if (strcmp("mif", prop_val) == 0) { 2464977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 2474977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 2484977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 2494977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 2504977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2514977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 2524977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 2534977Sraghus } 2544977Sraghus 2554977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 2564977Sraghus "phy-type", prop_val); 2574977Sraghus ddi_prop_free(prop_val); 2584977Sraghus 2594977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 2604977Sraghus "Got phy type [0x%x] from conf file", 2614977Sraghus nxgep->mac.portmode)); 2624977Sraghus 2634977Sraghus return (NXGE_OK); 2644977Sraghus } 2655572Ssbehera 2665572Ssbehera /* Get phy-type property from OBP */ 2674977Sraghus if (nxgep->niu_type == N2_NIU) { 2684977Sraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 2694977Sraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 2704977Sraghus if (strcmp("xgf", prop_val) == 0) { 2714977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2724977Sraghus XPCS_XCVR; 2734977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 2744977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2754977Sraghus "10G Fiber Xcvr")); 2764977Sraghus } else if (strcmp("mif", prop_val) == 0) { 2774977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2784977Sraghus INT_MII_XCVR; 2794977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 2804977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2814977Sraghus "1G Copper Xcvr")); 2824977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 2834977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2844977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 2854977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2864977Sraghus "1G Fiber Xcvr")); 2874977Sraghus } else if (strcmp("xgc", prop_val) == 0) { 2884977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2894977Sraghus XPCS_XCVR; 2904977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 2914977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2924977Sraghus "10G Copper Xcvr")); 2934977Sraghus } else if (strcmp("xgsd", prop_val) == 0) { 2944977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2954977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 2964977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2974977Sraghus "OBP: 10G Serdes")); 2984977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 2994977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3004977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 3014977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3024977Sraghus "OBP: 1G Serdes")); 3034977Sraghus } else { 3044977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3054977Sraghus "Unknown phy-type: %s", prop_val)); 3064977Sraghus ddi_prop_free(prop_val); 3074977Sraghus return (NXGE_ERROR); 3084977Sraghus } 3094977Sraghus status = NXGE_OK; 3104977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3114977Sraghus nxgep->dip, "phy-type", prop_val); 3124977Sraghus ddi_prop_free(prop_val); 3134977Sraghus 3144977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3154977Sraghus "Got phy type [0x%x] from OBP", 3164977Sraghus nxgep->mac.portmode)); 3174977Sraghus 3184977Sraghus return (status); 3194977Sraghus } else { 3204977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3214977Sraghus "Exiting...phy-type property not found")); 3224977Sraghus return (NXGE_ERROR); 3234977Sraghus } 3244977Sraghus } 3254977Sraghus 3264977Sraghus 3274977Sraghus if (!nxgep->vpd_info.present) { 3284977Sraghus return (NXGE_OK); 3294977Sraghus } 3304977Sraghus 3314977Sraghus if (!nxgep->vpd_info.ver_valid) { 3324977Sraghus goto read_seeprom; 3334977Sraghus } 3344977Sraghus 3354977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3364977Sraghus "Reading phy type from expansion ROM")); 3374977Sraghus /* 3384977Sraghus * Try to read the phy type from the vpd data read off the 3394977Sraghus * expansion ROM. 3404977Sraghus */ 3414977Sraghus phy_type = nxgep->vpd_info.phy_type; 3424977Sraghus 3435196Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 3444977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 3454977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3465196Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 3474977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 3484977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3495196Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 3504977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 3514977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3525196Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 3534977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 3544977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3555196Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 3565196Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 3575196Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3585196Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 3595196Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 3605196Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3614977Sraghus } else { 3625196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3634977Sraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3644977Sraghus phy_type[0], phy_type[1], phy_type[2])); 3654977Sraghus goto read_seeprom; 3664977Sraghus } 3674977Sraghus 3684977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3694977Sraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 3704977Sraghus 3714977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3724977Sraghus return (status); 3734977Sraghus 3744977Sraghus read_seeprom: 3754977Sraghus /* 3764977Sraghus * read the phy type from the SEEPROM - NCR registers 3774977Sraghus */ 3784977Sraghus status = nxge_espc_phy_type_get(nxgep); 3794977Sraghus if (status != NXGE_OK) { 3804977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3814977Sraghus "Failed to get phy type")); 3824977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3834977Sraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 3844977Sraghus } 3854977Sraghus 3864977Sraghus return (status); 3874977Sraghus 3884977Sraghus } 3894977Sraghus 3904732Sdavemq /* Set up the PHY specific values. */ 3914732Sdavemq 3924732Sdavemq nxge_status_t 3934732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 3944732Sdavemq { 3954732Sdavemq nxge_status_t status = NXGE_OK; 3964732Sdavemq uint32_t port_type; 3974732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3984977Sraghus uint32_t pcs_id = 0; 3994977Sraghus uint32_t pma_pmd_id = 0; 4004977Sraghus uint32_t phy_id = 0; 4015572Ssbehera uint16_t chip_id = 0; 4024732Sdavemq 4034732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 4044732Sdavemq portn)); 4054732Sdavemq 4064977Sraghus switch (nxgep->niu_type) { 4074977Sraghus case N2_NIU: 4084977Sraghus switch (nxgep->mac.portmode) { 4094977Sraghus case PORT_1G_FIBER: 4104977Sraghus case PORT_1G_SERDES: 4114977Sraghus nxgep->xcvr = nxge_n2_1G_table; 4125572Ssbehera nxgep->xcvr_addr = portn; 4134977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 4144977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 4154977Sraghus "Serdes")); 4164977Sraghus break; 4174977Sraghus case PORT_10G_FIBER: 4184977Sraghus case PORT_10G_SERDES: 4194977Sraghus nxgep->xcvr = nxge_n2_10G_table; 4205572Ssbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 4215572Ssbehera nxgep->xcvr_addr = 4225572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 4235572Ssbehera } 4244977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 4254977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 4264977Sraghus "Serdes")); 4274977Sraghus break; 4285572Ssbehera case PORT_HSP_MODE: 4295572Ssbehera nxgep->xcvr = nxge_n2_10G_table; 4305572Ssbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 4315572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 4325572Ssbehera "Swappable Xcvr (not present)")); 4335572Ssbehera break; 4344977Sraghus default: 4354977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4364977Sraghus "<== nxge_setup_xcvr_table: " 4374977Sraghus "Unable to determine NIU portmode")); 4384977Sraghus return (NXGE_ERROR); 4394977Sraghus } 4404977Sraghus break; 4414977Sraghus default: 4424977Sraghus if (nxgep->mac.portmode == 0) { 4434977Sraghus /* 4444977Sraghus * Would be the case for platforms like Maramba 4454977Sraghus * in which the phy type could not be got from conf 4464977Sraghus * file, OBP, VPD or Serial PROM. 4474977Sraghus */ 4484977Sraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 4494977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4504977Sraghus "<== nxge_setup_xcvr_table:" 4514977Sraghus " Invalid Neptune type [0x%x]", 4524977Sraghus nxgep->niu_type)); 4534977Sraghus return (NXGE_ERROR); 4544977Sraghus } 4554977Sraghus 4564977Sraghus port_type = nxgep->niu_type >> 4574977Sraghus (NXGE_PORT_TYPE_SHIFT * portn); 4584977Sraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 4594977Sraghus 4604977Sraghus switch (port_type) { 4614977Sraghus 4624977Sraghus case NXGE_PORT_1G_COPPER: 4634977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 4644977Sraghus break; 4654977Sraghus case NXGE_PORT_10G_COPPER: 4664977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 4674977Sraghus break; 4684977Sraghus case NXGE_PORT_1G_FIBRE: 4694977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 4704977Sraghus break; 4714977Sraghus case NXGE_PORT_10G_FIBRE: 4724977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 4734977Sraghus break; 4744977Sraghus case NXGE_PORT_1G_SERDES: 4754977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 4764977Sraghus break; 4774977Sraghus case NXGE_PORT_10G_SERDES: 4784977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 4794977Sraghus break; 4804977Sraghus case NXGE_PORT_1G_RGMII_FIBER: 4814977Sraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 4824977Sraghus break; 4834977Sraghus default: 4844977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4854977Sraghus "<== nxge_setup_xcvr_table: " 4864977Sraghus "Unknown port-type: 0x%x", port_type)); 4874977Sraghus return (NXGE_ERROR); 4884977Sraghus } 4894977Sraghus } 4904977Sraghus 4914977Sraghus switch (nxgep->mac.portmode) { 4924977Sraghus case PORT_1G_COPPER: 4934977Sraghus case PORT_1G_RGMII_FIBER: 4944732Sdavemq nxgep->xcvr = nxge_1G_copper_table; 4955572Ssbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 4964732Sdavemq /* 4974732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 4984732Sdavemq * swapped with ethernet port number. This is 4994977Sraghus * designed for better signal integrity in 5004977Sraghus * routing. This is also the case for the 5014977Sraghus * on-board Neptune copper ports on the Maramba 5024977Sraghus * platform. 5034732Sdavemq */ 5044977Sraghus switch (nxgep->platform_type) { 5054977Sraghus case P_NEPTUNE_ATLAS_4PORT: 5064977Sraghus case P_NEPTUNE_MARAMBA_P0: 5074977Sraghus case P_NEPTUNE_MARAMBA_P1: 5084977Sraghus switch (portn) { 5094977Sraghus case 0: 5105572Ssbehera nxgep->xcvr_addr += 3; 5114977Sraghus break; 5124977Sraghus case 1: 5135572Ssbehera nxgep->xcvr_addr += 1; 5144977Sraghus break; 5154977Sraghus case 2: 5165572Ssbehera nxgep->xcvr_addr -= 1; 5174977Sraghus break; 5184977Sraghus case 3: 5195572Ssbehera nxgep->xcvr_addr -= 3; 5204977Sraghus break; 5214977Sraghus default: 5224977Sraghus return (NXGE_ERROR); 5234977Sraghus } 5244732Sdavemq break; 5255196Ssbehera case P_NEPTUNE_ALONSO: 5265196Ssbehera /* 5275196Ssbehera * The Alonso Neptune, xcvr port numbers for 5285196Ssbehera * ports 2 and 3 are not swapped. Port 2 has 5295196Ssbehera * the BCM5464_PORT_BASE_ADDR and port 3 has 5305196Ssbehera * next address. 5315196Ssbehera */ 5325572Ssbehera nxgep->xcvr_addr = 5335572Ssbehera BCM5464_NEPTUNE_PORT_ADDR_BASE; 5345196Ssbehera if (portn == 3) { 5355572Ssbehera nxgep->xcvr_addr += 1; 5365196Ssbehera } 5375196Ssbehera break; 5384732Sdavemq default: 5394977Sraghus break; 5404732Sdavemq } 5415196Ssbehera 5424977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5434977Sraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 5444977Sraghus "Copper" : "RGMII Fiber")); 5454732Sdavemq break; 5464977Sraghus case PORT_10G_COPPER: 5474732Sdavemq nxgep->xcvr = nxge_10G_copper_table; 5484732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 5494732Sdavemq break; 5504977Sraghus case PORT_1G_FIBER: 5514977Sraghus case PORT_1G_SERDES: 5524732Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 5535572Ssbehera nxgep->xcvr_addr = portn; 5544977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5554977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 5564977Sraghus "Fiber" : "Serdes")); 5574732Sdavemq break; 5584977Sraghus case PORT_10G_FIBER: 5594977Sraghus case PORT_10G_SERDES: 5604732Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 5615572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 5625572Ssbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 5635572Ssbehera "nxgep->xcvr_addr = [%d]", 5645572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn], 5655572Ssbehera nxgep->xcvr_addr)); 5665572Ssbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5675572Ssbehera nxgep->xcvr_addr = 5685572Ssbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 5695572Ssbehera } 5704977Sraghus switch (nxgep->platform_type) { 5714977Sraghus case P_NEPTUNE_MARAMBA_P0: 5724977Sraghus case P_NEPTUNE_MARAMBA_P1: 5734732Sdavemq /* 5744732Sdavemq * Switch off LED for corresponding copper 5754732Sdavemq * port 5764732Sdavemq */ 5774732Sdavemq nxge_bcm5464_link_led_off(nxgep); 5784977Sraghus break; 5794977Sraghus default: 5804977Sraghus break; 5814732Sdavemq } 5824977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 5834977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 5844977Sraghus "Fiber" : "Serdes")); 5854732Sdavemq break; 5865572Ssbehera 5875572Ssbehera case PORT_HSP_MODE: 5885572Ssbehera nxgep->xcvr = nxge_10G_fiber_table; 5895572Ssbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 5905572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 5915572Ssbehera "Swappable Xcvr (not present)")); 5925572Ssbehera break; 5934732Sdavemq default: 5944732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5954732Sdavemq "Unknown port-type: 0x%x", port_type)); 5964732Sdavemq return (NXGE_ERROR); 5974732Sdavemq } 5984732Sdavemq } 5994732Sdavemq 6005572Ssbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 6015572Ssbehera if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6025572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 6035572Ssbehera &chip_id)) == NXGE_OK) { 6045572Ssbehera 6055572Ssbehera switch (chip_id) { 6065572Ssbehera case BCM8704_CHIP_ID: 6075572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6085572Ssbehera "nxge_setup_xcvr_table: " 6095572Ssbehera "Chip ID 8704 [0x%x] for 10G xcvr", 6105572Ssbehera chip_id)); 6115572Ssbehera break; 6125572Ssbehera case BCM8706_CHIP_ID: 6135572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6145572Ssbehera "nxge_setup_xcvr_table: " 6155572Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", 6165572Ssbehera chip_id)); 6175572Ssbehera break; 6185572Ssbehera default: 6195572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6205572Ssbehera "nxge_setup_xcvr_table: " 6215572Ssbehera "Unknown Chip ID [0x%x] for 10G xcvr", 6225572Ssbehera chip_id)); 6235572Ssbehera break; 6245572Ssbehera } 6255572Ssbehera } 6265572Ssbehera } 6275572Ssbehera 6284732Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 6295572Ssbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 6305572Ssbehera nxgep->chip_id = chip_id; 6314977Sraghus 6324977Sraghus /* 6334977Sraghus * Get the actual device ID value returned by MDIO read. 6344977Sraghus */ 6354977Sraghus nxgep->statsp->mac_stats.xcvr_id = 0; 6364977Sraghus 6375572Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 6384977Sraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 6394977Sraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 6404977Sraghus } else { 6415572Ssbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 6424977Sraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 6434977Sraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 6444977Sraghus } else { 6454977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, 6465572Ssbehera nxgep->xcvr_addr); 6474977Sraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6484977Sraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 6494977Sraghus } 6504977Sraghus } 6514977Sraghus } 6524977Sraghus 6534732Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 6544732Sdavemq 6554977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 6565572Ssbehera "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type, 6575572Ssbehera nxgep->platform_type, nxgep->xcvr_addr)); 6584977Sraghus 6594732Sdavemq return (status); 6604732Sdavemq } 6614732Sdavemq 6623859Sml29623 /* Initialize the entire MAC and physical layer */ 6633859Sml29623 6643859Sml29623 nxge_status_t 6653859Sml29623 nxge_mac_init(p_nxge_t nxgep) 6663859Sml29623 { 6673859Sml29623 uint8_t portn; 6683859Sml29623 nxge_status_t status = NXGE_OK; 6693859Sml29623 6703859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6713859Sml29623 6723859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 6733859Sml29623 6743859Sml29623 nxgep->mac.portnum = portn; 6753859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 6763859Sml29623 6773859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 6783859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 6793859Sml29623 6803859Sml29623 /* Initialize XIF to configure a network mode */ 6813859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 6823859Sml29623 goto fail; 6833859Sml29623 } 6843859Sml29623 6853859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 6863859Sml29623 goto fail; 6873859Sml29623 } 6883859Sml29623 6893859Sml29623 /* Initialize TX and RX MACs */ 6903859Sml29623 /* 6913859Sml29623 * Always perform XIF init first, before TX and RX MAC init 6923859Sml29623 */ 6933859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 6943859Sml29623 goto fail; 6953859Sml29623 6963859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 6973859Sml29623 goto fail; 6983859Sml29623 6993859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 7003859Sml29623 goto fail; 7013859Sml29623 7023859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 7033859Sml29623 goto fail; 7043859Sml29623 7053859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 7063859Sml29623 goto fail; 7073859Sml29623 7083859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 7093859Sml29623 goto fail; 7103859Sml29623 7115553Smisaki /* Initialize MAC control configuration */ 7125553Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 7135553Smisaki goto fail; 7145553Smisaki } 7155553Smisaki 7163859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 7173859Sml29623 7185196Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 7195196Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 7205196Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 7215196Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 7225196Ssbehera ((portn == 0) || (portn == 1))) { 7235196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7245196Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 7255196Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 7265196Ssbehera goto fail; 7275196Ssbehera } 7285196Ssbehera } 7295196Ssbehera 7304977Sraghus 7313859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 7323859Sml29623 7333859Sml29623 return (NXGE_OK); 7343859Sml29623 fail: 7353859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7363859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 7373859Sml29623 portn)); 7383859Sml29623 return (status); 7393859Sml29623 } 7403859Sml29623 7413859Sml29623 /* Initialize the Ethernet Link */ 7423859Sml29623 7433859Sml29623 nxge_status_t 7443859Sml29623 nxge_link_init(p_nxge_t nxgep) 7453859Sml29623 { 7463859Sml29623 nxge_status_t status = NXGE_OK; 7474977Sraghus nxge_port_mode_t portmode; 7483859Sml29623 #ifdef NXGE_DEBUG 7493859Sml29623 uint8_t portn; 7503859Sml29623 7513859Sml29623 portn = nxgep->mac.portnum; 7523859Sml29623 7533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 7543859Sml29623 #endif 7555572Ssbehera if (nxgep->hot_swappable_phy && nxgep->phy_absent) { 7565572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: " 7575572Ssbehera "Phy not present, cannot initialize link")); 7585572Ssbehera return (status); 7595572Ssbehera } 7603859Sml29623 7614977Sraghus portmode = nxgep->mac.portmode; 7625572Ssbehera 7634977Sraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 7644977Sraghus (portmode != PORT_1G_SERDES)) { 7653859Sml29623 /* Workaround to get link up in both NIU ports */ 7664977Sraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 7673859Sml29623 goto fail; 7684977Sraghus } 7693859Sml29623 } 7703859Sml29623 NXGE_DELAY(200000); 7713859Sml29623 /* Initialize internal serdes */ 7723859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 7733859Sml29623 goto fail; 7743859Sml29623 NXGE_DELAY(200000); 7753859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 7763859Sml29623 goto fail; 7773859Sml29623 7783859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 7793859Sml29623 7803859Sml29623 return (NXGE_OK); 7813859Sml29623 7823859Sml29623 fail: 7833859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7843859Sml29623 "nxge_link_init: ", 7853859Sml29623 "failed to initialize Ethernet link on port<%d>", 7863859Sml29623 portn)); 7873859Sml29623 7883859Sml29623 return (status); 7893859Sml29623 } 7903859Sml29623 7913859Sml29623 7923859Sml29623 /* Initialize the XIF sub-block within the MAC */ 7933859Sml29623 7943859Sml29623 nxge_status_t 7953859Sml29623 nxge_xif_init(p_nxge_t nxgep) 7963859Sml29623 { 7973859Sml29623 uint32_t xif_cfg = 0; 7983859Sml29623 npi_attr_t ap; 7993859Sml29623 uint8_t portn; 8003859Sml29623 nxge_port_t portt; 8013859Sml29623 nxge_port_mode_t portmode; 8023859Sml29623 p_nxge_stats_t statsp; 8033859Sml29623 npi_status_t rs = NPI_SUCCESS; 8043859Sml29623 npi_handle_t handle; 8053859Sml29623 8063859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8073859Sml29623 8083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 8093859Sml29623 8103859Sml29623 handle = nxgep->npi_handle; 8113859Sml29623 portmode = nxgep->mac.portmode; 8123859Sml29623 portt = nxgep->mac.porttype; 8133859Sml29623 statsp = nxgep->statsp; 8143859Sml29623 8155196Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 8165196Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 8175196Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 8185196Ssbehera ((portn == 0) || (portn == 1))) { 8195196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8205196Ssbehera "nxge_xcvr_init: set ATCA mode")); 8215196Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 8225196Ssbehera } 8235196Ssbehera 8243859Sml29623 if (portt == PORT_TYPE_XMAC) { 8253859Sml29623 8263859Sml29623 /* Setup XIF Configuration for XMAC */ 8273859Sml29623 8283859Sml29623 if ((portmode == PORT_10G_FIBER) || 8294977Sraghus (portmode == PORT_10G_COPPER) || 8304977Sraghus (portmode == PORT_10G_SERDES)) 8313859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 8323859Sml29623 8333859Sml29623 if (portmode == PORT_1G_COPPER) { 8343859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 8353859Sml29623 } 8363859Sml29623 8373859Sml29623 /* Set MAC Internal Loopback if necessary */ 8383859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 8393859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 8403859Sml29623 8413859Sml29623 if (statsp->mac_stats.link_speed == 100) 8423859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 8433859Sml29623 8443859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 8453859Sml29623 8464977Sraghus if ((portmode == PORT_10G_FIBER) || 8474977Sraghus (portmode == PORT_10G_SERDES)) { 8483859Sml29623 if (statsp->mac_stats.link_up) { 8493859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 8503859Sml29623 } else { 8513859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 8523859Sml29623 } 8533859Sml29623 } 8543859Sml29623 8553859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 8563859Sml29623 if (rs != NPI_SUCCESS) 8573859Sml29623 goto fail; 8583859Sml29623 8593859Sml29623 nxgep->mac.xif_config = xif_cfg; 8603859Sml29623 8613859Sml29623 /* Set Port Mode */ 8623859Sml29623 if ((portmode == PORT_10G_FIBER) || 8634977Sraghus (portmode == PORT_10G_COPPER) || 8644977Sraghus (portmode == PORT_10G_SERDES)) { 8653859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 8663859Sml29623 MAC_XGMII_MODE, rs); 8673859Sml29623 if (rs != NPI_SUCCESS) 8683859Sml29623 goto fail; 8693859Sml29623 if (statsp->mac_stats.link_up) { 8703859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 8713859Sml29623 goto fail; 8723859Sml29623 } else { 8733859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 8743859Sml29623 goto fail; 8753859Sml29623 } 8763859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 8774977Sraghus (portmode == PORT_1G_COPPER) || 8785196Ssbehera (portmode == PORT_1G_SERDES) || 8795196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 8805196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8815196Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 8825196Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 8833859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 8843859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 8853859Sml29623 MAC_GMII_MODE, rs); 8863859Sml29623 } else { 8873859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 8883859Sml29623 MAC_MII_MODE, rs); 8893859Sml29623 } 8903859Sml29623 if (rs != NPI_SUCCESS) 8913859Sml29623 goto fail; 8923859Sml29623 } else { 8933859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8943859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 8953859Sml29623 " for port<%d>", portmode, portn)); 8963859Sml29623 goto fail; 8973859Sml29623 } 8983859Sml29623 8995196Ssbehera /* Enable ATCA mode */ 9005196Ssbehera 9013859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 9023859Sml29623 9033859Sml29623 /* Setup XIF Configuration for BMAC */ 9043859Sml29623 9055196Ssbehera if ((portmode == PORT_1G_COPPER) || 9065196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 9073859Sml29623 if (statsp->mac_stats.link_speed == 100) 9083859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 9093859Sml29623 } 9103859Sml29623 9113859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 9123859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 9133859Sml29623 9143859Sml29623 if (statsp->mac_stats.link_speed == 1000) 9153859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 9163859Sml29623 9173859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 9183859Sml29623 9193859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 9203859Sml29623 if (rs != NPI_SUCCESS) 9213859Sml29623 goto fail; 9223859Sml29623 nxgep->mac.xif_config = xif_cfg; 9233859Sml29623 } 9243859Sml29623 9253859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 9263859Sml29623 return (NXGE_OK); 9273859Sml29623 fail: 9283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9293859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 9303859Sml29623 portn)); 9313859Sml29623 return (NXGE_ERROR | rs); 9323859Sml29623 } 9333859Sml29623 9343859Sml29623 /* Initialize the PCS sub-block in the MAC */ 9353859Sml29623 9363859Sml29623 nxge_status_t 9373859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 9383859Sml29623 { 9393859Sml29623 pcs_cfg_t pcs_cfg; 9403859Sml29623 uint32_t val; 9413859Sml29623 uint8_t portn; 9423859Sml29623 nxge_port_mode_t portmode; 9433859Sml29623 npi_handle_t handle; 9443859Sml29623 p_nxge_stats_t statsp; 9453859Sml29623 npi_status_t rs = NPI_SUCCESS; 9463859Sml29623 9473859Sml29623 handle = nxgep->npi_handle; 9483859Sml29623 portmode = nxgep->mac.portmode; 9493859Sml29623 portn = nxgep->mac.portnum; 9503859Sml29623 statsp = nxgep->statsp; 9513859Sml29623 9523859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 9533859Sml29623 9544977Sraghus if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 9554977Sraghus if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 9564977Sraghus goto fail; 9574977Sraghus } 9584977Sraghus 9593859Sml29623 /* Initialize port's PCS */ 9603859Sml29623 pcs_cfg.value = 0; 9613859Sml29623 pcs_cfg.bits.w0.enable = 1; 9623859Sml29623 pcs_cfg.bits.w0.mask = 1; 9633859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 9643859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 9654977Sraghus 9664977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9674977Sraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 9684977Sraghus portn, pcs_cfg.value)); 9693859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 9704977Sraghus (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 9713859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 9723859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 9733859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 9743859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 9753859Sml29623 9763859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 9773859Sml29623 goto fail; 9783859Sml29623 9793859Sml29623 /* Set XPCS Internal Loopback if necessary */ 9803859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 9813859Sml29623 XPCS_REG_CONTROL1, &val)) 9823859Sml29623 != NPI_SUCCESS) 9833859Sml29623 goto fail; 9843859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 9853859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 9863859Sml29623 val |= XPCS_CTRL1_LOOPBK; 9873859Sml29623 else 9883859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 9893859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 9903859Sml29623 XPCS_REG_CONTROL1, val)) 9913859Sml29623 != NPI_SUCCESS) 9923859Sml29623 goto fail; 9933859Sml29623 9943859Sml29623 /* Clear descw errors */ 9953859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 9963859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 9973859Sml29623 != NPI_SUCCESS) 9983859Sml29623 goto fail; 9993859Sml29623 /* Clear symbol errors */ 10003859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 10013859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 10023859Sml29623 != NPI_SUCCESS) 10033859Sml29623 goto fail; 10043859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 10053859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 10063859Sml29623 != NPI_SUCCESS) 10073859Sml29623 goto fail; 10083859Sml29623 10095196Ssbehera } else if ((portmode == PORT_1G_COPPER) || 10105196Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 10115196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10125196Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 10133859Sml29623 if (portn < 4) { 10143859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 10153859Sml29623 PCS_DATAPATH_MODE_MII); 10163859Sml29623 } 10173859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 10183859Sml29623 goto fail; 10193859Sml29623 10203859Sml29623 } else { 10213859Sml29623 goto fail; 10223859Sml29623 } 10233859Sml29623 pass: 10243859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 10253859Sml29623 return (NXGE_OK); 10263859Sml29623 fail: 10273859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10283859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 10293859Sml29623 portn)); 10303859Sml29623 return (NXGE_ERROR | rs); 10313859Sml29623 } 10323859Sml29623 10335553Smisaki /* 10345553Smisaki * Initialize the MAC CTRL sub-block within the MAC 10355553Smisaki * Only the receive-pause-cap is supported. 10365553Smisaki */ 10375553Smisaki nxge_status_t 10385553Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 10395553Smisaki { 10405553Smisaki uint8_t portn; 10415553Smisaki nxge_port_t portt; 10425553Smisaki p_nxge_stats_t statsp; 10435553Smisaki npi_handle_t handle; 10445553Smisaki uint32_t val; 10455553Smisaki 10465553Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 10475553Smisaki 10485553Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 10495553Smisaki portn)); 10505553Smisaki 10515553Smisaki handle = nxgep->npi_handle; 10525553Smisaki portt = nxgep->mac.porttype; 10535553Smisaki statsp = nxgep->statsp; 10545553Smisaki 10555553Smisaki if (portt == PORT_TYPE_XMAC) { 10565553Smisaki /* Readin the current XMAC Config Register for XMAC */ 10575553Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 10585553Smisaki 10595553Smisaki /* 10605553Smisaki * Setup XMAC Configuration for XMAC 10615553Smisaki * XMAC only supports receive-pause 10625553Smisaki */ 10635553Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 10645553Smisaki if (!statsp->mac_stats.adv_cap_pause) { 10655553Smisaki /* 10665553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 10675553Smisaki * is 0, enable receive pause. 10685553Smisaki */ 10695553Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 10705553Smisaki } else { 10715553Smisaki /* 10725553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 10735553Smisaki * is 1, disable receive pause. Send pause is 10745553Smisaki * not supported. 10755553Smisaki */ 10765553Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 10775553Smisaki } 10785553Smisaki } else { 10795553Smisaki if (statsp->mac_stats.adv_cap_pause) { 10805553Smisaki /* 10815553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 10825553Smisaki * is 1, enable receive pause. 10835553Smisaki */ 10845553Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 10855553Smisaki } else { 10865553Smisaki /* 10875553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 10885553Smisaki * is 0, disable receive pause. Send pause is 10895553Smisaki * not supported 10905553Smisaki */ 10915553Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 10925553Smisaki } 10935553Smisaki } 10945553Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 10955553Smisaki } else if (portt == PORT_TYPE_BMAC) { 10965553Smisaki /* Readin the current MAC CTRL Config Register for BMAC */ 10975553Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 10985553Smisaki 10995553Smisaki /* Setup MAC CTRL Configuration for BMAC */ 11005553Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 11015553Smisaki if (statsp->mac_stats.adv_cap_pause) { 11025553Smisaki /* 11035553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 11045553Smisaki * is 1, disable receive pause. Send pause 11055553Smisaki * is not supported 11065553Smisaki */ 11075553Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 11085553Smisaki } else { 11095553Smisaki /* 11105553Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 11115553Smisaki * is 0, enable receive pause and disable 11125553Smisaki * send pause. 11135553Smisaki */ 11145553Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 11155553Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 11165553Smisaki } 11175553Smisaki } else { 11185553Smisaki if (statsp->mac_stats.adv_cap_pause) { 11195553Smisaki /* 11205553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11215553Smisaki * is 1, enable receive pause. Send pause is 11225553Smisaki * not supported. 11235553Smisaki */ 11245553Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 11255553Smisaki } else { 11265553Smisaki /* 11275553Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 11285553Smisaki * is 0, pause capability is not available in 11295553Smisaki * either direction. 11305553Smisaki */ 11315553Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 11325553Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 11335553Smisaki } 11345553Smisaki } 11355553Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 11365553Smisaki } 11375553Smisaki 11385553Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 11395553Smisaki portn)); 11405553Smisaki 11415553Smisaki return (NXGE_OK); 11425553Smisaki } 11435553Smisaki 11443859Sml29623 /* Initialize the Internal Serdes */ 11453859Sml29623 11463859Sml29623 nxge_status_t 11473859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 11483859Sml29623 { 11493859Sml29623 p_nxge_stats_t statsp; 11503859Sml29623 #ifdef NXGE_DEBUG 11513859Sml29623 uint8_t portn; 11523859Sml29623 #endif 11533859Sml29623 nxge_status_t status = NXGE_OK; 11543859Sml29623 11553859Sml29623 #ifdef NXGE_DEBUG 11563859Sml29623 portn = nxgep->mac.portnum; 11573859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11584732Sdavemq "==> nxge_serdes_init port<%d>", portn)); 11593859Sml29623 #endif 11603859Sml29623 11614732Sdavemq if (nxgep->xcvr.serdes_init) { 11624732Sdavemq statsp = nxgep->statsp; 11634732Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 11644732Sdavemq if (status != NXGE_OK) 11653859Sml29623 goto fail; 11664732Sdavemq statsp->mac_stats.serdes_inits++; 11673859Sml29623 } 11683859Sml29623 11693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 11704732Sdavemq portn)); 11713859Sml29623 11723859Sml29623 return (NXGE_OK); 11733859Sml29623 11743859Sml29623 fail: 11753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11764732Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 11774732Sdavemq portn)); 11783859Sml29623 11793859Sml29623 return (status); 11803859Sml29623 } 11813859Sml29623 11823859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 11833859Sml29623 11844732Sdavemq static nxge_status_t 11853859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 11863859Sml29623 { 11873859Sml29623 uint8_t portn; 11883859Sml29623 int chan; 11893859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 11904977Sraghus esr_ti_cfgpll_l_t pll_sts_l; 11913859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 11923859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 11933859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 11943859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 11954977Sraghus #ifdef NXGE_DEBUG 11964977Sraghus esr_ti_testcfg_t cfg; 11974977Sraghus #endif 11983859Sml29623 esr_ti_testcfg_t test_cfg; 11993859Sml29623 nxge_status_t status = NXGE_OK; 12003859Sml29623 12013859Sml29623 portn = nxgep->mac.portnum; 12023859Sml29623 12033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 12043859Sml29623 portn)); 12053859Sml29623 12063859Sml29623 tx_cfg_l.value = 0; 12073859Sml29623 tx_cfg_h.value = 0; 12083859Sml29623 rx_cfg_l.value = 0; 12093859Sml29623 rx_cfg_h.value = 0; 12103859Sml29623 pll_cfg_l.value = 0; 12114977Sraghus pll_sts_l.value = 0; 12123859Sml29623 test_cfg.value = 0; 12133859Sml29623 12144977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 12154977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 12163859Sml29623 /* 0x0E01 */ 12173859Sml29623 tx_cfg_l.bits.entx = 1; 12183859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 12193859Sml29623 12203859Sml29623 /* 0x9101 */ 12213859Sml29623 rx_cfg_l.bits.enrx = 1; 12223859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 12233859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 12243859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 12253859Sml29623 12263859Sml29623 /* 0x0008 */ 12273859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12283859Sml29623 12293859Sml29623 /* Set loopback mode if necessary */ 12303859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 12313859Sml29623 tx_cfg_l.bits.entest = 1; 12323859Sml29623 rx_cfg_l.bits.entest = 1; 12333859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 12343859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 12353859Sml29623 ESR_N2_DEV_ADDR, 12363859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 12373859Sml29623 != NXGE_OK) 12383859Sml29623 goto fail; 12393859Sml29623 } 12403859Sml29623 12413859Sml29623 /* Use default PLL value */ 12423859Sml29623 12434977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 12444977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 12453859Sml29623 12463859Sml29623 /* 0x0E21 */ 12473859Sml29623 tx_cfg_l.bits.entx = 1; 12483859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 12493859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 12503859Sml29623 12513859Sml29623 /* 0x9121 */ 12523859Sml29623 rx_cfg_l.bits.enrx = 1; 12533859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 12543859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 12553859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 12563859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 12573859Sml29623 12584977Sraghus if (portn == 0) { 12594977Sraghus /* 0x8 */ 12604977Sraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12614977Sraghus } 12623859Sml29623 12633859Sml29623 /* MPY = 0x100 */ 12643859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 12653859Sml29623 12663859Sml29623 /* Set PLL */ 12673859Sml29623 pll_cfg_l.bits.enpll = 1; 12684977Sraghus pll_sts_l.bits.enpll = 1; 12693859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 12703859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 12713859Sml29623 != NXGE_OK) 12723859Sml29623 goto fail; 12734977Sraghus 12744977Sraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 12754977Sraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 12764977Sraghus goto fail; 12774977Sraghus 12784977Sraghus #ifdef NXGE_DEBUG 12794977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12804977Sraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 12814977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12824977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 12834977Sraghus portn, pll_cfg_l.value, cfg.value)); 12844977Sraghus 12854977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12864977Sraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 12874977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12884977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 12894977Sraghus portn, pll_sts_l.value, cfg.value)); 12904977Sraghus #endif 12914977Sraghus 12924977Sraghus /* Set loopback mode if necessary */ 12934977Sraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 12944977Sraghus tx_cfg_l.bits.entest = 1; 12954977Sraghus rx_cfg_l.bits.entest = 1; 12964977Sraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 12974977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12984977Sraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 12994977Sraghus portn, test_cfg.value)); 13004977Sraghus if ((status = nxge_mdio_write(nxgep, portn, 13014977Sraghus ESR_N2_DEV_ADDR, 13024977Sraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 13034977Sraghus goto fail; 13044977Sraghus } 13054977Sraghus } 13063859Sml29623 } else { 13073859Sml29623 goto fail; 13083859Sml29623 } 13093859Sml29623 13103859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 13113859Sml29623 13123859Sml29623 NXGE_DELAY(20); 13133859Sml29623 13143859Sml29623 /* init TX channels */ 13153859Sml29623 for (chan = 0; chan < 4; chan++) { 13163859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13173859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 13183859Sml29623 != NXGE_OK) 13193859Sml29623 goto fail; 13203859Sml29623 13213859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13223859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 13233859Sml29623 != NXGE_OK) 13243859Sml29623 goto fail; 13254977Sraghus 13264977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13274977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 13284977Sraghus portn, chan, tx_cfg_l.value)); 13294977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13304977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 13314977Sraghus portn, chan, tx_cfg_h.value)); 13323859Sml29623 } 13333859Sml29623 13343859Sml29623 /* init RX channels */ 13353859Sml29623 for (chan = 0; chan < 4; chan++) { 13363859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13373859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 13383859Sml29623 != NXGE_OK) 13393859Sml29623 goto fail; 13403859Sml29623 13413859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 13423859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 13433859Sml29623 != NXGE_OK) 13443859Sml29623 goto fail; 13454977Sraghus 13464977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13474977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 13484977Sraghus portn, chan, rx_cfg_l.value)); 13494977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13504977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 13514977Sraghus portn, chan, rx_cfg_h.value)); 13523859Sml29623 } 13533859Sml29623 13543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 13553859Sml29623 portn)); 13563859Sml29623 13573859Sml29623 return (NXGE_OK); 13583859Sml29623 fail: 13595572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13605572Ssbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 13615572Ssbehera portn)); 13623859Sml29623 13633859Sml29623 return (status); 13643859Sml29623 } 13653859Sml29623 13664732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 13674732Sdavemq 13684732Sdavemq static nxge_status_t 13694732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 13703859Sml29623 { 13713859Sml29623 npi_handle_t handle; 13723859Sml29623 uint8_t portn; 13733859Sml29623 int chan; 13743859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 13753859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 13763859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 13773859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 13783859Sml29623 uint64_t val; 13793859Sml29623 uint16_t val16l; 13803859Sml29623 uint16_t val16h; 13813859Sml29623 nxge_status_t status = NXGE_OK; 13823859Sml29623 13833859Sml29623 portn = nxgep->mac.portnum; 13843859Sml29623 13853859Sml29623 if ((portn != 0) && (portn != 1)) 13863859Sml29623 return (NXGE_OK); 13873859Sml29623 13884732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13894732Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 13903859Sml29623 13913859Sml29623 handle = nxgep->npi_handle; 13924732Sdavemq switch (portn) { 13934732Sdavemq case 0: 1394*6028Ssbehera /* Reset Serdes */ 1395*6028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 1396*6028Ssbehera NXGE_DELAY(20); 1397*6028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 1398*6028Ssbehera NXGE_DELAY(2000); 1399*6028Ssbehera 1400*6028Ssbehera /* Configure Serdes to 10G mode */ 1401*6028Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1402*6028Ssbehera ESR_PLL_CFG_10G_SERDES); 1403*6028Ssbehera 14044732Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 14054732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 14064732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 14074732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 14084732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 14094732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 14104732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14114732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14124732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 14134732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 14144732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 14154732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 14164732Sdavemq 14174732Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 14184732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 14194732Sdavemq ESR_REG_WR(handle, 14204732Sdavemq ESR_0_TEST_CONFIG_REG, 14214732Sdavemq ESR_PAD_LOOPBACK_CH3 | 14224732Sdavemq ESR_PAD_LOOPBACK_CH2 | 14234732Sdavemq ESR_PAD_LOOPBACK_CH1 | 14244732Sdavemq ESR_PAD_LOOPBACK_CH0); 14254732Sdavemq } else { 14264732Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 14273859Sml29623 } 14284732Sdavemq break; 14294732Sdavemq case 1: 1430*6028Ssbehera /* Reset Serdes */ 1431*6028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 1432*6028Ssbehera NXGE_DELAY(20); 1433*6028Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 1434*6028Ssbehera NXGE_DELAY(2000); 1435*6028Ssbehera 1436*6028Ssbehera /* Configure Serdes to 10G mode */ 1437*6028Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1438*6028Ssbehera ESR_PLL_CFG_10G_SERDES); 1439*6028Ssbehera 14404732Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 14414732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 14424732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 14434732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 14444732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 14454732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 14464732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14474732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 14484732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 14494732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 14504732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 14514732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 14524732Sdavemq 14534732Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 14544732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 14554732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 14564732Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 14574732Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 14584732Sdavemq } else { 14594732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 14603859Sml29623 } 14614732Sdavemq break; 14624732Sdavemq default: 14634732Sdavemq /* Nothing to do here */ 14644732Sdavemq goto done; 14654732Sdavemq } 14664732Sdavemq 14674732Sdavemq /* init TX RX channels */ 14684732Sdavemq for (chan = 0; chan < 4; chan++) { 14694732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 14704732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 14714732Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 14723859Sml29623 goto fail; 14734732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 14744732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 14754732Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 14763859Sml29623 goto fail; 14773859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 14784732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 14794732Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 14803859Sml29623 goto fail; 14813859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 14824732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 14834732Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 14844732Sdavemq goto fail; 14854732Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 14864732Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 14874732Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 14884732Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 14894732Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 14904732Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 14914732Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 14924732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 14934732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 14944732Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 14954732Sdavemq goto fail; 14964732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 14974732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 14984732Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 14994732Sdavemq goto fail; 15004732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15014732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 15024732Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 15034732Sdavemq goto fail; 15044732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15054732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 15064732Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 15073859Sml29623 goto fail; 15083859Sml29623 } 15093859Sml29623 15104732Sdavemq /* Apply Tx core reset */ 15114732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 15124732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 15134732Sdavemq (uint16_t)0)) != NXGE_OK) 15144732Sdavemq goto fail; 15154732Sdavemq 15164732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15174732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 15184732Sdavemq NXGE_OK) 15194732Sdavemq goto fail; 15204732Sdavemq 15214732Sdavemq NXGE_DELAY(200); 15224732Sdavemq 15234732Sdavemq /* Apply Rx core reset */ 15244732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15254732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 15264732Sdavemq NXGE_OK) 15274732Sdavemq goto fail; 15284732Sdavemq 15294732Sdavemq NXGE_DELAY(200); 15304732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15314732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 15324732Sdavemq goto fail; 15334732Sdavemq 15344732Sdavemq NXGE_DELAY(200); 15354732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 15364732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 15374732Sdavemq &val16l)) != NXGE_OK) 15384732Sdavemq goto fail; 15394732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 15404732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 15414732Sdavemq goto fail; 15424732Sdavemq if ((val16l != 0) || (val16h != 0)) { 15434732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15445196Ssbehera "Failed to reset port<%d> XAUI Serdes " 15455196Ssbehera "(val16l 0x%x val16h 0x%x)", 15465196Ssbehera portn, val16l, val16h)); 15474732Sdavemq } 15484732Sdavemq 15494732Sdavemq ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 15504732Sdavemq 15514732Sdavemq if (portn == 0) { 15524732Sdavemq if ((val & ESR_SIG_P0_BITS_MASK) != 15533859Sml29623 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 15543859Sml29623 ESR_SIG_XSERDES_RDY_P0 | 15553859Sml29623 ESR_SIG_XDETECT_P0_CH3 | 15563859Sml29623 ESR_SIG_XDETECT_P0_CH2 | 15573859Sml29623 ESR_SIG_XDETECT_P0_CH1 | 15583859Sml29623 ESR_SIG_XDETECT_P0_CH0)) { 15594732Sdavemq goto fail; 15604732Sdavemq } 15614732Sdavemq } else if (portn == 1) { 15624732Sdavemq if ((val & ESR_SIG_P1_BITS_MASK) != 15633859Sml29623 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 15643859Sml29623 ESR_SIG_XSERDES_RDY_P1 | 15653859Sml29623 ESR_SIG_XDETECT_P1_CH3 | 15663859Sml29623 ESR_SIG_XDETECT_P1_CH2 | 15673859Sml29623 ESR_SIG_XDETECT_P1_CH1 | 15683859Sml29623 ESR_SIG_XDETECT_P1_CH0)) { 15693859Sml29623 goto fail; 15703859Sml29623 } 15713859Sml29623 } 15723859Sml29623 15733859Sml29623 done: 15744732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15754732Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 15764732Sdavemq 15773859Sml29623 return (NXGE_OK); 15783859Sml29623 fail: 15795572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15804732Sdavemq "nxge_neptune_10G_serdes_init: " 15814732Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 15823859Sml29623 15833859Sml29623 return (status); 15843859Sml29623 } 15853859Sml29623 15864732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 15874732Sdavemq 15884732Sdavemq static nxge_status_t 15894732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 15903859Sml29623 { 15914732Sdavemq npi_handle_t handle; 15924732Sdavemq uint8_t portn; 15935196Ssbehera int chan; 15945196Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 15955196Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 15965196Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 15975196Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 15984732Sdavemq uint64_t val; 15995196Ssbehera uint16_t val16l; 16005196Ssbehera uint16_t val16h; 16015196Ssbehera nxge_status_t status = NXGE_OK; 16023859Sml29623 16033859Sml29623 portn = nxgep->mac.portnum; 16044732Sdavemq 16054732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16064732Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 16074732Sdavemq 16084732Sdavemq handle = nxgep->npi_handle; 16094732Sdavemq 16104732Sdavemq switch (portn) { 16114732Sdavemq case 0: 16125196Ssbehera /* Assert the reset register */ 16135196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16145196Ssbehera val |= ESR_RESET_0; 16155196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16165196Ssbehera 16175196Ssbehera /* Set the PLL register to 0x79 */ 16185196Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 16195196Ssbehera ESR_PLL_CFG_1G_SERDES); 16205196Ssbehera 16215196Ssbehera /* Set the control register to 0x249249f */ 16225196Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 16235196Ssbehera 16245196Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 16255196Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16265196Ssbehera /* Set pad loopback modes 0xaa */ 16275196Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 16285196Ssbehera ESR_TSTCFG_LBTEST_PAD); 16295196Ssbehera } else { 16305196Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 16315196Ssbehera } 16325196Ssbehera 16335196Ssbehera /* Deassert the reset register */ 16345196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16355196Ssbehera val &= ~ESR_RESET_0; 16365196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16374732Sdavemq break; 16385196Ssbehera 16394732Sdavemq case 1: 16405196Ssbehera /* Assert the reset register */ 16415196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16425196Ssbehera val |= ESR_RESET_1; 16435196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16445196Ssbehera 16455196Ssbehera /* Set PLL register to 0x79 */ 16465196Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 16475196Ssbehera ESR_PLL_CFG_1G_SERDES); 16485196Ssbehera 16495196Ssbehera /* Set the control register to 0x249249f */ 16505196Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 16515196Ssbehera 16525196Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 16535196Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16545196Ssbehera /* Set pad loopback mode 0xaa */ 16555196Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 16565196Ssbehera ESR_TSTCFG_LBTEST_PAD); 16575196Ssbehera } else { 16585196Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 16595196Ssbehera } 16605196Ssbehera 16615196Ssbehera /* Deassert the reset register */ 16625196Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 16635196Ssbehera val &= ~ESR_RESET_1; 16645196Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 16654732Sdavemq break; 16665196Ssbehera 16674732Sdavemq default: 16685196Ssbehera /* Nothing to do here */ 16695196Ssbehera goto done; 16705196Ssbehera } 16715196Ssbehera 16725196Ssbehera /* init TX RX channels */ 16735196Ssbehera for (chan = 0; chan < 4; chan++) { 16745196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 16755196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 16765196Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 16775196Ssbehera goto fail; 16785196Ssbehera } 16795196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 16805196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 16815196Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 16825196Ssbehera goto fail; 16835196Ssbehera } 16845196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 16855196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 16865196Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 16875196Ssbehera goto fail; 16885196Ssbehera } 16895196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 16905196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 16915196Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 16925196Ssbehera goto fail; 16935196Ssbehera } 16945196Ssbehera 16955196Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 16965196Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 16975196Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 16985196Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 16995196Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 17005196Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 17015196Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 17025196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17035196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 17045196Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 17055196Ssbehera goto fail; 17065196Ssbehera } 17075196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17085196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 17095196Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 17105196Ssbehera goto fail; 17115196Ssbehera } 17125196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17135196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 17145196Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 17155196Ssbehera goto fail; 17165196Ssbehera } 17175196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 17185196Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 17195196Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 17205196Ssbehera goto fail; 17215196Ssbehera } 17225196Ssbehera } 17235196Ssbehera 17245196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17255196Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 17264732Sdavemq goto fail; 17273859Sml29623 } 17285196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17295196Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 17305196Ssbehera goto fail; 17315196Ssbehera } 17325196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17335196Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 17345196Ssbehera goto fail; 17355196Ssbehera } 17365196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17375196Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 17385196Ssbehera goto fail; 17395196Ssbehera } 17405196Ssbehera 17415196Ssbehera /* Apply Tx core reset */ 17425196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17435196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 17445196Ssbehera goto fail; 17455196Ssbehera } 17465196Ssbehera 17475196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17485196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 17495196Ssbehera NXGE_OK) { 17505196Ssbehera goto fail; 17515196Ssbehera } 17525196Ssbehera 17535196Ssbehera NXGE_DELAY(200); 17545196Ssbehera 17555196Ssbehera /* Apply Rx core reset */ 17565196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17575196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 17585196Ssbehera NXGE_OK) { 17595196Ssbehera goto fail; 17605196Ssbehera } 17615196Ssbehera 17625196Ssbehera NXGE_DELAY(200); 17635196Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17645196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 17655196Ssbehera goto fail; 17665196Ssbehera } 17675196Ssbehera 17685196Ssbehera NXGE_DELAY(200); 17695196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17705196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 17715196Ssbehera goto fail; 17725196Ssbehera } 17735196Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 17745196Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 17755196Ssbehera goto fail; 17765196Ssbehera } 17775196Ssbehera if ((val16l != 0) || (val16h != 0)) { 17785196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17795196Ssbehera "Failed to reset port<%d> XAUI Serdes " 17805196Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 17815196Ssbehera status = NXGE_ERROR; 17825196Ssbehera goto fail; 17835196Ssbehera } 17845196Ssbehera 17855196Ssbehera NXGE_DELAY(200); 17865196Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 17875196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17885196Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 17895196Ssbehera "val 0x%x", portn, val)); 17905196Ssbehera if (portn == 0) { 17915196Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 17925196Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 17935196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17945196Ssbehera "nxge_neptune_serdes_init: " 17955196Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 17965196Ssbehera portn, (val & ESR_SIG_P0_BITS_MASK))); 17975196Ssbehera status = NXGE_ERROR; 17985196Ssbehera goto fail; 17995196Ssbehera } 18005196Ssbehera } else if (portn == 1) { 18015196Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 18025196Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 18035196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18045196Ssbehera "nxge_neptune_serdes_init: " 18055196Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 18065196Ssbehera portn, (val & ESR_SIG_P1_BITS_MASK))); 18075196Ssbehera status = NXGE_ERROR; 18085196Ssbehera goto fail; 18095196Ssbehera } 18105196Ssbehera } 18115196Ssbehera done: 18124732Sdavemq 18134732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18144732Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 18153859Sml29623 return (NXGE_OK); 18164732Sdavemq fail: 18175196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18184732Sdavemq "nxge_1G_serdes_init: " 18194732Sdavemq "Failed to initialize Neptune serdes for port<%d>", 18204732Sdavemq portn)); 18214732Sdavemq 18225196Ssbehera return (status); 18233859Sml29623 } 18243859Sml29623 18255572Ssbehera /* Initialize the BCM 8704 xcvr */ 18264732Sdavemq 18274732Sdavemq static nxge_status_t 18285572Ssbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 18293859Sml29623 { 18303859Sml29623 uint16_t val; 18313859Sml29623 #ifdef NXGE_DEBUG 18323859Sml29623 uint8_t portn; 18333859Sml29623 uint16_t val1; 18343859Sml29623 #endif 18353859Sml29623 uint8_t phy_port_addr; 18363859Sml29623 pmd_tx_control_t tx_ctl; 18373859Sml29623 control_t ctl; 18383859Sml29623 phyxs_control_t phyxs_ctl; 18393859Sml29623 pcs_control_t pcs_ctl; 18403859Sml29623 uint32_t delay = 0; 18413859Sml29623 optics_dcntr_t op_ctr; 18423859Sml29623 nxge_status_t status = NXGE_OK; 18433859Sml29623 #ifdef NXGE_DEBUG 18443859Sml29623 portn = nxgep->mac.portnum; 18453859Sml29623 #endif 18465572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 18474732Sdavemq portn)); 18484732Sdavemq 18494732Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 18504732Sdavemq 18514732Sdavemq /* Reset the transceiver */ 18524732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 18534732Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 18544732Sdavemq goto fail; 18554732Sdavemq 18564732Sdavemq phyxs_ctl.bits.reset = 1; 18574732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 18584732Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 18594732Sdavemq goto fail; 18604732Sdavemq 18614732Sdavemq do { 18624732Sdavemq drv_usecwait(500); 18634732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 18644732Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 18654732Sdavemq &phyxs_ctl.value)) != NXGE_OK) 18664732Sdavemq goto fail; 18674732Sdavemq delay++; 18684732Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 18694732Sdavemq if (delay == 100) { 18704732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 18714732Sdavemq "failed to reset Transceiver on port<%d>", portn)); 18724732Sdavemq status = NXGE_ERROR; 18734732Sdavemq goto fail; 18744732Sdavemq } 18754732Sdavemq 18764732Sdavemq /* Set to 0x7FBF */ 18774732Sdavemq ctl.value = 0; 18784732Sdavemq ctl.bits.res1 = 0x3F; 18794732Sdavemq ctl.bits.optxon_lvl = 1; 18804732Sdavemq ctl.bits.oprxflt_lvl = 1; 18814732Sdavemq ctl.bits.optrxlos_lvl = 1; 18824732Sdavemq ctl.bits.optxflt_lvl = 1; 18834732Sdavemq ctl.bits.opprflt_lvl = 1; 18844732Sdavemq ctl.bits.obtmpflt_lvl = 1; 18854732Sdavemq ctl.bits.opbiasflt_lvl = 1; 18864732Sdavemq ctl.bits.optxrst_lvl = 1; 18874732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 18884732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 18894732Sdavemq != NXGE_OK) 18904732Sdavemq goto fail; 18914732Sdavemq 18924732Sdavemq /* Set to 0x164 */ 18934732Sdavemq tx_ctl.value = 0; 18944732Sdavemq tx_ctl.bits.tsck_lpwren = 1; 18954732Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 18964732Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 18974732Sdavemq tx_ctl.bits.xfp_clken = 1; 18984732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 18994732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 19004732Sdavemq tx_ctl.value)) != NXGE_OK) 19014732Sdavemq goto fail; 19024732Sdavemq /* 19034732Sdavemq * According to Broadcom's instruction, SW needs to read 19044732Sdavemq * back these registers twice after written. 19054732Sdavemq */ 19064732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19074732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 19084732Sdavemq != NXGE_OK) 19094732Sdavemq goto fail; 19104732Sdavemq 19114732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19124732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 19134732Sdavemq != NXGE_OK) 19144732Sdavemq goto fail; 19154732Sdavemq 19164732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19174732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 19184732Sdavemq != NXGE_OK) 19194732Sdavemq goto fail; 19204732Sdavemq 19214732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19224732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 19234732Sdavemq != NXGE_OK) 19244732Sdavemq goto fail; 19254732Sdavemq 19264732Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 19274732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19284732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 19294732Sdavemq &op_ctr.value)) != NXGE_OK) 19304732Sdavemq goto fail; 19315553Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 19325553Smisaki op_ctr.bits.gpio_sel = 0x1; 19335553Smisaki } else { 19345553Smisaki op_ctr.bits.gpio_sel = 0x3; 19355553Smisaki } 19364732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 19374732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 19384732Sdavemq op_ctr.value)) != NXGE_OK) 19394732Sdavemq goto fail; 19404732Sdavemq 19414732Sdavemq NXGE_DELAY(1000000); 19424732Sdavemq 19434732Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 19444732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 19454732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 19464732Sdavemq != NXGE_OK) 19474732Sdavemq goto fail; 19484732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 19494732Sdavemq pcs_ctl.bits.loopback = 1; 19504732Sdavemq else 19514732Sdavemq pcs_ctl.bits.loopback = 0; 19524732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 19534732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 19544732Sdavemq != NXGE_OK) 19554732Sdavemq goto fail; 19564732Sdavemq 19574732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 19584732Sdavemq if (status != NXGE_OK) 19594732Sdavemq goto fail; 19604732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19614732Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 19624732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 19634732Sdavemq if (status != NXGE_OK) 19644732Sdavemq goto fail; 19654732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19664732Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 19674732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 19684732Sdavemq if (status != NXGE_OK) 19694732Sdavemq goto fail; 19704732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19714732Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 19724732Sdavemq 19734732Sdavemq #ifdef NXGE_DEBUG 19744732Sdavemq /* Diagnose link issue if link is not up */ 19754732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 19764732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 19774732Sdavemq &val); 19784732Sdavemq if (status != NXGE_OK) 19794732Sdavemq goto fail; 19804732Sdavemq 19814732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 19824732Sdavemq BCM8704_USER_DEV3_ADDR, 19834732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 19844732Sdavemq &val); 19854732Sdavemq if (status != NXGE_OK) 19864732Sdavemq goto fail; 19874732Sdavemq 19884732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 19894732Sdavemq BCM8704_USER_DEV3_ADDR, 19904732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 19914732Sdavemq &val1); 19924732Sdavemq if (status != NXGE_OK) 19934732Sdavemq goto fail; 19944732Sdavemq 19954732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 19964732Sdavemq BCM8704_USER_DEV3_ADDR, 19974732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 19984732Sdavemq &val1); 19994732Sdavemq if (status != NXGE_OK) 20004732Sdavemq goto fail; 20014732Sdavemq 20024732Sdavemq if (val != 0x3FC) { 20034732Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 20044732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20054732Sdavemq "Cable not connected to peer or bad" 20064732Sdavemq " cable on port<%d>\n", portn)); 20074732Sdavemq } else if (val == 0x639C) { 20084732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20094732Sdavemq "Optical module (XFP) is bad or absent" 20104732Sdavemq " on port<%d>\n", portn)); 20114732Sdavemq } 20124732Sdavemq } 20134732Sdavemq #endif 20144732Sdavemq 20155572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 20165572Ssbehera portn)); 20175572Ssbehera return (NXGE_OK); 20185572Ssbehera 20195572Ssbehera fail: 20205572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20215572Ssbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 20225572Ssbehera "port<%d>", nxgep->mac.portnum)); 20235572Ssbehera return (NXGE_ERROR); 20245572Ssbehera } 20255572Ssbehera 20265572Ssbehera /* Initialize the BCM 8706 Transceiver */ 20275572Ssbehera 20285572Ssbehera static nxge_status_t 20295572Ssbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 20305572Ssbehera { 20315572Ssbehera uint8_t phy_port_addr; 20325572Ssbehera phyxs_control_t phyxs_ctl; 20335572Ssbehera pcs_control_t pcs_ctl; 20345572Ssbehera uint32_t delay = 0; 20355572Ssbehera optics_dcntr_t op_ctr; 20365572Ssbehera nxge_status_t status = NXGE_OK; 20375572Ssbehera #ifdef NXGE_DEBUG 20385572Ssbehera uint8_t portn = nxgep->mac.portnum; 20395572Ssbehera #endif 20405572Ssbehera 20415572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 20425572Ssbehera portn)); 20435572Ssbehera 20445572Ssbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 20455572Ssbehera 20465572Ssbehera /* Reset the transceiver */ 20475572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20485572Ssbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 20495572Ssbehera goto fail; 20505572Ssbehera 20515572Ssbehera phyxs_ctl.bits.reset = 1; 20525572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20535572Ssbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 20545572Ssbehera goto fail; 20555572Ssbehera do { 20565572Ssbehera drv_usecwait(500); 20575572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20585572Ssbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 20595572Ssbehera &phyxs_ctl.value)) != NXGE_OK) 20605572Ssbehera goto fail; 20615572Ssbehera delay++; 20625572Ssbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 20635572Ssbehera 20645572Ssbehera if (delay == 100) { 20655572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 20665572Ssbehera "failed to reset Transceiver on port<%d>", portn)); 20675572Ssbehera status = NXGE_ERROR; 20685572Ssbehera goto fail; 20695572Ssbehera } 20705572Ssbehera 20715572Ssbehera NXGE_DELAY(1000000); 20725572Ssbehera 20735572Ssbehera /* Set BCM8706 Internal Loopback mode if necessary */ 20745572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20755572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 20765572Ssbehera != NXGE_OK) 20775572Ssbehera goto fail; 20785572Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 20795572Ssbehera pcs_ctl.bits.loopback = 1; 20805572Ssbehera else 20815572Ssbehera pcs_ctl.bits.loopback = 0; 20825572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 20835572Ssbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 20845572Ssbehera != NXGE_OK) 20855572Ssbehera goto fail; 20865572Ssbehera 20875572Ssbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 20885572Ssbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20895572Ssbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 20905572Ssbehera &op_ctr.value)) != NXGE_OK) 20915572Ssbehera goto fail; 20925572Ssbehera op_ctr.bits.gpio_sel = 0x3; 20935572Ssbehera op_ctr.bits.res2 = 0x1; 20945572Ssbehera 20955572Ssbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 20965572Ssbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 20975572Ssbehera op_ctr.value)) != NXGE_OK) 20985572Ssbehera goto fail; 20995572Ssbehera 21005572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 21015572Ssbehera portn)); 21025572Ssbehera return (NXGE_OK); 21035572Ssbehera 21045572Ssbehera fail: 21055572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21065572Ssbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 21075572Ssbehera "port<%d>", nxgep->mac.portnum)); 21085572Ssbehera return (status); 21095572Ssbehera } 21105572Ssbehera 21115572Ssbehera /* Initialize the 10G Transceiver */ 21125572Ssbehera 21135572Ssbehera static nxge_status_t 21145572Ssbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 21155572Ssbehera { 21165572Ssbehera p_nxge_stats_t statsp; 21175572Ssbehera nxge_status_t status = NXGE_OK; 21185572Ssbehera #ifdef NXGE_DEBUG 21195572Ssbehera uint8_t portn = nxgep->mac.portnum; 21205572Ssbehera #endif 21215572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 21225572Ssbehera portn)); 21235572Ssbehera 21245572Ssbehera statsp = nxgep->statsp; 21255572Ssbehera 21265572Ssbehera if (nxgep->mac.portmode == PORT_10G_SERDES) { 21275572Ssbehera goto done; 21285572Ssbehera } 21295572Ssbehera 21305572Ssbehera /* Disable Link LEDs */ 21315572Ssbehera if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 21325572Ssbehera goto fail; 21335572Ssbehera 21345572Ssbehera /* Set Clause 45 */ 21355572Ssbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 21365572Ssbehera 21375572Ssbehera switch (nxgep->chip_id) { 21385572Ssbehera case BCM8704_CHIP_ID: 21395572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21405572Ssbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 21415572Ssbehera status = nxge_BCM8704_xcvr_init(nxgep); 21425572Ssbehera break; 21435572Ssbehera case BCM8706_CHIP_ID: 21445572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21455572Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 21465572Ssbehera status = nxge_BCM8706_xcvr_init(nxgep); 21475572Ssbehera break; 21485572Ssbehera default: 21495572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 21505572Ssbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 21515572Ssbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 21525572Ssbehera goto fail; 21535572Ssbehera } 21545572Ssbehera 21555572Ssbehera if (status != NXGE_OK) { 21565572Ssbehera goto fail; 21575572Ssbehera } 21584977Sraghus done: 21594732Sdavemq statsp->mac_stats.cap_10gfdx = 1; 21604732Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 21614732Sdavemq 21624732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 21634732Sdavemq portn)); 21644732Sdavemq return (NXGE_OK); 21654732Sdavemq 21664732Sdavemq fail: 21675572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21684732Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 21695572Ssbehera "port<%d>", nxgep->mac.portnum)); 21705572Ssbehera return (NXGE_ERROR); 21714732Sdavemq } 21724732Sdavemq 21734732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 21744732Sdavemq 21754732Sdavemq static nxge_status_t 21764732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 21774732Sdavemq { 21784732Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 21794732Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 21804732Sdavemq nxge_status_t status = NXGE_OK; 21814732Sdavemq 21824977Sraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 21834977Sraghus statsp->mac_stats.cap_1000fdx = 21844977Sraghus param_arr[param_anar_1000fdx].value; 21854977Sraghus goto done; 21864977Sraghus } 21874977Sraghus 21884732Sdavemq /* Set Clause 22 */ 21894732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 21904732Sdavemq 21914732Sdavemq /* Set capability flags */ 21924732Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 21934977Sraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 21944977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 21954977Sraghus statsp->mac_stats.cap_100fdx = 21964977Sraghus param_arr[param_anar_100fdx].value; 21974977Sraghus statsp->mac_stats.cap_10fdx = 21984977Sraghus param_arr[param_anar_10fdx].value; 21994977Sraghus } 22004732Sdavemq 22014732Sdavemq status = nxge_mii_xcvr_init(nxgep); 22024977Sraghus done: 22034732Sdavemq return (status); 22044732Sdavemq } 22054732Sdavemq 22064732Sdavemq /* Initialize transceiver */ 22074732Sdavemq 22084732Sdavemq nxge_status_t 22094732Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 22104732Sdavemq { 22114732Sdavemq p_nxge_stats_t statsp; 22124732Sdavemq #ifdef NXGE_DEBUG 22134732Sdavemq uint8_t portn; 22144732Sdavemq #endif 22154732Sdavemq 22164732Sdavemq nxge_status_t status = NXGE_OK; 22174732Sdavemq #ifdef NXGE_DEBUG 22184732Sdavemq portn = nxgep->mac.portnum; 22194732Sdavemq #endif 22203859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 22213859Sml29623 statsp = nxgep->statsp; 22223859Sml29623 22233859Sml29623 /* 22243859Sml29623 * Initialize the xcvr statistics. 22253859Sml29623 */ 22263859Sml29623 statsp->mac_stats.cap_autoneg = 0; 22273859Sml29623 statsp->mac_stats.cap_100T4 = 0; 22283859Sml29623 statsp->mac_stats.cap_100fdx = 0; 22293859Sml29623 statsp->mac_stats.cap_100hdx = 0; 22303859Sml29623 statsp->mac_stats.cap_10fdx = 0; 22313859Sml29623 statsp->mac_stats.cap_10hdx = 0; 22323859Sml29623 statsp->mac_stats.cap_asmpause = 0; 22333859Sml29623 statsp->mac_stats.cap_pause = 0; 22343859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 22353859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 22363859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 22373859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 22383859Sml29623 22393859Sml29623 /* 22403859Sml29623 * Initialize the link statistics. 22413859Sml29623 */ 22423859Sml29623 statsp->mac_stats.link_T4 = 0; 22433859Sml29623 statsp->mac_stats.link_asmpause = 0; 22443859Sml29623 statsp->mac_stats.link_pause = 0; 22453859Sml29623 22464732Sdavemq if (nxgep->xcvr.xcvr_init) { 22474732Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 22483859Sml29623 if (status != NXGE_OK) 22493859Sml29623 goto fail; 22504732Sdavemq statsp->mac_stats.xcvr_inits++; 22513859Sml29623 } 22523859Sml29623 22534732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 22544732Sdavemq portn)); 22553859Sml29623 return (NXGE_OK); 22563859Sml29623 22573859Sml29623 fail: 22583859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 22594732Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 22604732Sdavemq portn)); 22613859Sml29623 return (status); 22623859Sml29623 } 22633859Sml29623 22644977Sraghus /* Look for transceiver type */ 22654977Sraghus 22664977Sraghus nxge_status_t 22674977Sraghus nxge_xcvr_find(p_nxge_t nxgep) 22684977Sraghus { 22695196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 22705196Ssbehera nxgep->mac.portnum)); 22714977Sraghus 22724977Sraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 22734977Sraghus return (NXGE_ERROR); 22744977Sraghus 22754977Sraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 22764977Sraghus return (NXGE_ERROR); 22774977Sraghus 22784977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 22794977Sraghus nxgep->statsp->mac_stats.xcvr_inuse)); 22804977Sraghus return (NXGE_OK); 22814977Sraghus } 22823859Sml29623 22833859Sml29623 /* Initialize the TxMAC sub-block */ 22843859Sml29623 22853859Sml29623 nxge_status_t 22863859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 22873859Sml29623 { 22883859Sml29623 npi_attr_t ap; 22893859Sml29623 uint8_t portn; 22903859Sml29623 nxge_port_mode_t portmode; 22913859Sml29623 nxge_port_t portt; 22923859Sml29623 npi_handle_t handle; 22933859Sml29623 npi_status_t rs = NPI_SUCCESS; 22943859Sml29623 22953859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 22963859Sml29623 portt = nxgep->mac.porttype; 22973859Sml29623 handle = nxgep->npi_handle; 22983859Sml29623 portmode = nxgep->mac.portmode; 22993859Sml29623 23003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 23013859Sml29623 portn)); 23023859Sml29623 23033859Sml29623 /* Set Max and Min Frame Size */ 23043859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 23053859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 2306*6028Ssbehera MAC_PORT_FRAME_SIZE, 64, nxge_jumbo_mtu, rs); 23073859Sml29623 } else { 2308*6028Ssbehera /* 2309*6028Ssbehera * Set the maxframe size to 1522 (1518 + 4) to account for 2310*6028Ssbehera * VLAN tagged packets 2311*6028Ssbehera */ 23123859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 2313*6028Ssbehera MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 23143859Sml29623 } 23153859Sml29623 23163859Sml29623 if (rs != NPI_SUCCESS) 23173859Sml29623 goto fail; 23183859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || 23193859Sml29623 nxgep->mac.is_jumbo == B_TRUE) 2320*6028Ssbehera nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu; 23213859Sml29623 else 23223859Sml29623 nxgep->mac.maxframesize = 0x5EE + 4; 23233859Sml29623 nxgep->mac.minframesize = 64; 23243859Sml29623 23253859Sml29623 if (portt == PORT_TYPE_XMAC) { 23263859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 23273859Sml29623 0)) != NPI_SUCCESS) 23283859Sml29623 goto fail; 23293859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 23303859Sml29623 if ((portmode == PORT_10G_FIBER) || 23314977Sraghus (portmode == PORT_10G_COPPER) || 23324977Sraghus (portmode == PORT_10G_SERDES)) { 23333859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 23343859Sml29623 XGMII_IPG_12_15, rs); 23353859Sml29623 if (rs != NPI_SUCCESS) 23363859Sml29623 goto fail; 23373859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 23383859Sml29623 } else { 23393859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 23403859Sml29623 MII_GMII_IPG_12, rs); 23413859Sml29623 if (rs != NPI_SUCCESS) 23423859Sml29623 goto fail; 23433859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 23443859Sml29623 } 23453859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 23463859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 23473859Sml29623 goto fail; 23483859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 23493859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 23503859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 23513859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 23523859Sml29623 23533859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 23543859Sml29623 != NPI_SUCCESS) 23553859Sml29623 goto fail; 23563859Sml29623 23573859Sml29623 } else { 23583859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 23593859Sml29623 0)) != NPI_SUCCESS) 23603859Sml29623 goto fail; 23613859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 23623859Sml29623 23633859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 23643859Sml29623 rs); 23653859Sml29623 if (rs != NPI_SUCCESS) 23663859Sml29623 goto fail; 23673859Sml29623 nxgep->mac.ctrltype = 0x8808; 23683859Sml29623 23693859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 23703859Sml29623 if (rs != NPI_SUCCESS) 23713859Sml29623 goto fail; 23723859Sml29623 nxgep->mac.pa_size = 0x7; 23733859Sml29623 23743859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 23753859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 23763859Sml29623 goto fail; 23773859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 23783859Sml29623 } 23793859Sml29623 23803859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 23813859Sml29623 portn)); 23823859Sml29623 23833859Sml29623 return (NXGE_OK); 23843859Sml29623 fail: 23853859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 23863859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 23873859Sml29623 portn)); 23883859Sml29623 23893859Sml29623 return (NXGE_ERROR | rs); 23903859Sml29623 } 23913859Sml29623 23923859Sml29623 /* Initialize the RxMAC sub-block */ 23933859Sml29623 23943859Sml29623 nxge_status_t 23953859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 23963859Sml29623 { 23973859Sml29623 npi_attr_t ap; 23983859Sml29623 uint32_t i; 23993859Sml29623 uint16_t hashtab_e; 24003859Sml29623 p_hash_filter_t hash_filter; 24013859Sml29623 nxge_port_t portt; 24023859Sml29623 uint8_t portn; 24033859Sml29623 npi_handle_t handle; 24043859Sml29623 npi_status_t rs = NPI_SUCCESS; 24053859Sml29623 uint16_t *addr16p; 24063859Sml29623 uint16_t addr0, addr1, addr2; 24073859Sml29623 xmac_rx_config_t xconfig; 24083859Sml29623 bmac_rx_config_t bconfig; 24093859Sml29623 24103859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 24113859Sml29623 24123859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 24133859Sml29623 portn)); 24143859Sml29623 handle = nxgep->npi_handle; 24153859Sml29623 portt = nxgep->mac.porttype; 24163859Sml29623 24173859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 24183859Sml29623 addr0 = ntohs(addr16p[2]); 24193859Sml29623 addr1 = ntohs(addr16p[1]); 24203859Sml29623 addr2 = ntohs(addr16p[0]); 24213859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 24223859Sml29623 rs); 24233859Sml29623 24243859Sml29623 if (rs != NPI_SUCCESS) 24253859Sml29623 goto fail; 24263859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 24273859Sml29623 if (rs != NPI_SUCCESS) 24283859Sml29623 goto fail; 24293859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 24303859Sml29623 if (rs != NPI_SUCCESS) 24313859Sml29623 goto fail; 24323859Sml29623 24333859Sml29623 /* 24343859Sml29623 * Load the multicast hash filter bits. 24353859Sml29623 */ 24363859Sml29623 hash_filter = nxgep->hash_filter; 24373859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 24383859Sml29623 if (hash_filter != NULL) { 24393859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 24403859Sml29623 (NMCFILTER_REGS - 1) - i]; 24413859Sml29623 } else { 24423859Sml29623 hashtab_e = 0; 24433859Sml29623 } 24443859Sml29623 24453859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 24463859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 24473859Sml29623 goto fail; 24483859Sml29623 } 24493859Sml29623 24503859Sml29623 if (portt == PORT_TYPE_XMAC) { 24513859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 24523859Sml29623 0)) != NPI_SUCCESS) 24533859Sml29623 goto fail; 24543859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 24553859Sml29623 24563859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 24573859Sml29623 24583859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 24593859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 24603859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 24613859Sml29623 24623859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 24633859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 24643859Sml29623 24653859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 24663859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 24673859Sml29623 24683859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 24693859Sml29623 24703859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 24713859Sml29623 xconfig)) != NPI_SUCCESS) 24723859Sml29623 goto fail; 24733859Sml29623 nxgep->mac.rx_config = xconfig; 24743859Sml29623 24753859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 24763859Sml29623 24773859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 24783859Sml29623 != NPI_SUCCESS) 24793859Sml29623 goto fail; 24803859Sml29623 } else { 24813859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 24823859Sml29623 24833859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 24843859Sml29623 0) != NPI_SUCCESS) 24853859Sml29623 goto fail; 24863859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 24873859Sml29623 24883859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 24893859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 24903859Sml29623 24913859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 24923859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 24933859Sml29623 24943859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 24953859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 24963859Sml29623 24973859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 24983859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 24993859Sml29623 bconfig)) != NPI_SUCCESS) 25003859Sml29623 goto fail; 25013859Sml29623 nxgep->mac.rx_config = bconfig; 25023859Sml29623 25033859Sml29623 /* Always enable comparison of mac unique address */ 25043859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 25053859Sml29623 != NPI_SUCCESS) 25063859Sml29623 goto fail; 25073859Sml29623 } 25083859Sml29623 25093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 25103859Sml29623 portn)); 25113859Sml29623 25123859Sml29623 return (NXGE_OK); 25133859Sml29623 25143859Sml29623 fail: 25153859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 25163859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 25173859Sml29623 portn)); 25183859Sml29623 25193859Sml29623 return (NXGE_ERROR | rs); 25203859Sml29623 } 25213859Sml29623 25223859Sml29623 /* Enable TXMAC */ 25233859Sml29623 25243859Sml29623 nxge_status_t 25253859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 25263859Sml29623 { 25273859Sml29623 npi_handle_t handle; 25283859Sml29623 npi_status_t rs = NPI_SUCCESS; 25293859Sml29623 nxge_status_t status = NXGE_OK; 25303859Sml29623 25313859Sml29623 handle = nxgep->npi_handle; 25323859Sml29623 25333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 25343859Sml29623 nxgep->mac.portnum)); 25353859Sml29623 25363859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 25373859Sml29623 goto fail; 25383859Sml29623 25393859Sml29623 /* based on speed */ 25403859Sml29623 nxgep->msg_min = ETHERMIN; 25413859Sml29623 25423859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 25433859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 25443859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 25453859Sml29623 goto fail; 25463859Sml29623 } else { 25473859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 25483859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 25493859Sml29623 goto fail; 25503859Sml29623 } 25513859Sml29623 25523859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 25533859Sml29623 nxgep->mac.portnum)); 25543859Sml29623 25553859Sml29623 return (NXGE_OK); 25563859Sml29623 fail: 25573859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 25583859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 25593859Sml29623 nxgep->mac.portnum)); 25603859Sml29623 if (rs != NPI_SUCCESS) 25613859Sml29623 return (NXGE_ERROR | rs); 25623859Sml29623 else 25633859Sml29623 return (status); 25643859Sml29623 } 25653859Sml29623 25663859Sml29623 /* Disable TXMAC */ 25673859Sml29623 25683859Sml29623 nxge_status_t 25693859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 25703859Sml29623 { 25713859Sml29623 npi_handle_t handle; 25723859Sml29623 npi_status_t rs = NPI_SUCCESS; 25733859Sml29623 25743859Sml29623 handle = nxgep->npi_handle; 25753859Sml29623 25763859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 25773859Sml29623 nxgep->mac.portnum)); 25783859Sml29623 25793859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 25803859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 25813859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 25823859Sml29623 goto fail; 25833859Sml29623 } else { 25843859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 25853859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 25863859Sml29623 goto fail; 25873859Sml29623 } 25883859Sml29623 25893859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 25903859Sml29623 nxgep->mac.portnum)); 25913859Sml29623 return (NXGE_OK); 25923859Sml29623 fail: 25933859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 25943859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 25953859Sml29623 nxgep->mac.portnum)); 25963859Sml29623 return (NXGE_ERROR | rs); 25973859Sml29623 } 25983859Sml29623 25993859Sml29623 /* Enable RXMAC */ 26003859Sml29623 26013859Sml29623 nxge_status_t 26023859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 26033859Sml29623 { 26043859Sml29623 npi_handle_t handle; 26053859Sml29623 uint8_t portn; 26063859Sml29623 npi_status_t rs = NPI_SUCCESS; 26073859Sml29623 nxge_status_t status = NXGE_OK; 26083859Sml29623 26093859Sml29623 handle = nxgep->npi_handle; 26103859Sml29623 portn = nxgep->mac.portnum; 26113859Sml29623 26123859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 26133859Sml29623 portn)); 26143859Sml29623 26153859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 26163859Sml29623 goto fail; 26173859Sml29623 26183859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 26193859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 26203859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 26213859Sml29623 goto fail; 26223859Sml29623 } else { 26233859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 26243859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 26253859Sml29623 goto fail; 26263859Sml29623 } 26273859Sml29623 26283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 26293859Sml29623 portn)); 26303859Sml29623 26313859Sml29623 return (NXGE_OK); 26323859Sml29623 fail: 26333859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 26343859Sml29623 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 26353859Sml29623 portn)); 26363859Sml29623 26373859Sml29623 if (rs != NPI_SUCCESS) 26383859Sml29623 return (NXGE_ERROR | rs); 26393859Sml29623 else 26403859Sml29623 return (status); 26413859Sml29623 } 26423859Sml29623 26433859Sml29623 /* Disable RXMAC */ 26443859Sml29623 26453859Sml29623 nxge_status_t 26463859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 26473859Sml29623 { 26483859Sml29623 npi_handle_t handle; 26493859Sml29623 uint8_t portn; 26503859Sml29623 npi_status_t rs = NPI_SUCCESS; 26513859Sml29623 26523859Sml29623 handle = nxgep->npi_handle; 26533859Sml29623 portn = nxgep->mac.portnum; 26543859Sml29623 26553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 26563859Sml29623 portn)); 26573859Sml29623 26583859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 26593859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 26603859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 26613859Sml29623 goto fail; 26623859Sml29623 } else { 26633859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 26643859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 26653859Sml29623 goto fail; 26663859Sml29623 } 26673859Sml29623 26683859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 26693859Sml29623 portn)); 26703859Sml29623 return (NXGE_OK); 26713859Sml29623 fail: 26723859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 26733859Sml29623 "nxgep_rx_mac_disable: ", 26743859Sml29623 "Failed to disable port<%d> RxMAC", 26753859Sml29623 portn)); 26763859Sml29623 26773859Sml29623 return (NXGE_ERROR | rs); 26783859Sml29623 } 26793859Sml29623 26803859Sml29623 /* Reset TXMAC */ 26813859Sml29623 26823859Sml29623 nxge_status_t 26833859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 26843859Sml29623 { 26853859Sml29623 npi_handle_t handle; 26863859Sml29623 uint8_t portn; 26873859Sml29623 npi_status_t rs = NPI_SUCCESS; 26883859Sml29623 26893859Sml29623 handle = nxgep->npi_handle; 26903859Sml29623 portn = nxgep->mac.portnum; 26913859Sml29623 26923859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 26933859Sml29623 portn)); 26943859Sml29623 26953859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 26963859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 26973859Sml29623 != NPI_SUCCESS) 26983859Sml29623 goto fail; 26993859Sml29623 } else { 27003859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 27013859Sml29623 != NPI_SUCCESS) 27023859Sml29623 goto fail; 27033859Sml29623 } 27043859Sml29623 27053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 27063859Sml29623 portn)); 27073859Sml29623 27083859Sml29623 return (NXGE_OK); 27093859Sml29623 fail: 27103859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27113859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 27123859Sml29623 portn)); 27133859Sml29623 27143859Sml29623 return (NXGE_ERROR | rs); 27153859Sml29623 } 27163859Sml29623 27173859Sml29623 /* Reset RXMAC */ 27183859Sml29623 27193859Sml29623 nxge_status_t 27203859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 27213859Sml29623 { 27223859Sml29623 npi_handle_t handle; 27233859Sml29623 uint8_t portn; 27243859Sml29623 npi_status_t rs = NPI_SUCCESS; 27253859Sml29623 27263859Sml29623 handle = nxgep->npi_handle; 27273859Sml29623 portn = nxgep->mac.portnum; 27283859Sml29623 27293859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 27303859Sml29623 portn)); 27313859Sml29623 27323859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 27333859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 27343859Sml29623 != NPI_SUCCESS) 27353859Sml29623 goto fail; 27363859Sml29623 } else { 27373859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 27383859Sml29623 != NPI_SUCCESS) 27393859Sml29623 goto fail; 27403859Sml29623 } 27413859Sml29623 27423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 27433859Sml29623 portn)); 27443859Sml29623 27453859Sml29623 return (NXGE_OK); 27463859Sml29623 fail: 27473859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27483859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 27493859Sml29623 portn)); 27503859Sml29623 return (NXGE_ERROR | rs); 27513859Sml29623 } 27523859Sml29623 27534732Sdavemq /* 10G fiber link interrupt start routine */ 27544732Sdavemq 27554732Sdavemq static nxge_status_t 27564732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 27574732Sdavemq { 27584732Sdavemq npi_status_t rs = NPI_SUCCESS; 27594732Sdavemq uint8_t portn = nxgep->mac.portnum; 27604732Sdavemq 27614732Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 27624732Sdavemq 27634732Sdavemq if (rs != NPI_SUCCESS) 27644732Sdavemq return (NXGE_ERROR | rs); 27654732Sdavemq else 27664732Sdavemq return (NXGE_OK); 27674732Sdavemq } 27684732Sdavemq 27694732Sdavemq /* 10G fiber link interrupt stop routine */ 27704732Sdavemq 27714732Sdavemq static nxge_status_t 27724732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 27734732Sdavemq { 27744732Sdavemq npi_status_t rs = NPI_SUCCESS; 27754732Sdavemq uint8_t portn = nxgep->mac.portnum; 27764732Sdavemq 27774732Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 27784732Sdavemq 27794732Sdavemq if (rs != NPI_SUCCESS) 27804732Sdavemq return (NXGE_ERROR | rs); 27814732Sdavemq else 27824732Sdavemq return (NXGE_OK); 27834732Sdavemq } 27844732Sdavemq 27854732Sdavemq /* 1G fiber link interrupt start routine */ 27864732Sdavemq 27874732Sdavemq static nxge_status_t 27884732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 27894732Sdavemq { 27904732Sdavemq npi_status_t rs = NPI_SUCCESS; 27914732Sdavemq uint8_t portn = nxgep->mac.portnum; 27924732Sdavemq 27934732Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 27944732Sdavemq if (rs != NPI_SUCCESS) 27954732Sdavemq return (NXGE_ERROR | rs); 27964732Sdavemq else 27974732Sdavemq return (NXGE_OK); 27984732Sdavemq } 27994732Sdavemq 28004732Sdavemq /* 1G fiber link interrupt stop routine */ 28014732Sdavemq 28024732Sdavemq static nxge_status_t 28034732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 28044732Sdavemq { 28054732Sdavemq npi_status_t rs = NPI_SUCCESS; 28064732Sdavemq uint8_t portn = nxgep->mac.portnum; 28074732Sdavemq 28084732Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 28094732Sdavemq 28104732Sdavemq if (rs != NPI_SUCCESS) 28114732Sdavemq return (NXGE_ERROR | rs); 28124732Sdavemq else 28134732Sdavemq return (NXGE_OK); 28144732Sdavemq } 28154732Sdavemq 28164732Sdavemq /* 1G copper link interrupt start routine */ 28174732Sdavemq 28184732Sdavemq static nxge_status_t 28194732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 28204732Sdavemq { 28214732Sdavemq npi_status_t rs = NPI_SUCCESS; 28224732Sdavemq uint8_t portn = nxgep->mac.portnum; 28234732Sdavemq 28244732Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 28255203Ssbehera MII_STATUS, MII_STATUS_LINKUP); 28264732Sdavemq 28274732Sdavemq if (rs != NPI_SUCCESS) 28284732Sdavemq return (NXGE_ERROR | rs); 28294732Sdavemq else 28304732Sdavemq return (NXGE_OK); 28314732Sdavemq } 28324732Sdavemq 28334732Sdavemq /* 1G copper link interrupt stop routine */ 28344732Sdavemq 28354732Sdavemq static nxge_status_t 28364732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 28374732Sdavemq { 28384732Sdavemq npi_status_t rs = NPI_SUCCESS; 28394732Sdavemq uint8_t portn = nxgep->mac.portnum; 28404732Sdavemq 28414732Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 28424732Sdavemq 28434732Sdavemq if (rs != NPI_SUCCESS) 28444732Sdavemq return (NXGE_ERROR | rs); 28454732Sdavemq else 28464732Sdavemq return (NXGE_OK); 28474732Sdavemq } 28484732Sdavemq 28494732Sdavemq /* Enable/Disable Link Status change interrupt */ 28503859Sml29623 28513859Sml29623 nxge_status_t 28523859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 28533859Sml29623 { 28544732Sdavemq uint8_t portn; 28554732Sdavemq nxge_status_t status = NXGE_OK; 28563859Sml29623 28573859Sml29623 portn = nxgep->mac.portnum; 28583859Sml29623 28593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 28604732Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 28614732Sdavemq return (NXGE_OK); 28624732Sdavemq 28634732Sdavemq if (enable == LINK_INTR_START) 28644732Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 28654732Sdavemq else if (enable == LINK_INTR_STOP) 28664732Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 28674732Sdavemq if (status != NXGE_OK) 28684732Sdavemq goto fail; 28693859Sml29623 28703859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 28713859Sml29623 28723859Sml29623 return (NXGE_OK); 28733859Sml29623 fail: 28743859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28753859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 28763859Sml29623 portn)); 28773859Sml29623 28784732Sdavemq return (status); 28793859Sml29623 } 28803859Sml29623 28813859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 28823859Sml29623 28833859Sml29623 nxge_status_t 28843859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 28853859Sml29623 { 28863859Sml29623 p_nxge_param_t param_arr; 28873859Sml29623 p_nxge_stats_t statsp; 28883859Sml29623 uint8_t xcvr_portn; 28893859Sml29623 p_mii_regs_t mii_regs; 28903859Sml29623 mii_bmcr_t bmcr; 28913859Sml29623 mii_bmsr_t bmsr; 28923859Sml29623 mii_anar_t anar; 28933859Sml29623 mii_gcr_t gcr; 28943859Sml29623 mii_esr_t esr; 28953859Sml29623 mii_aux_ctl_t bcm5464r_aux; 28963859Sml29623 int status = NXGE_OK; 28973859Sml29623 28983859Sml29623 uint_t delay; 28993859Sml29623 29003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 29013859Sml29623 29023859Sml29623 param_arr = nxgep->param_arr; 29033859Sml29623 statsp = nxgep->statsp; 29043859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 29053859Sml29623 29063859Sml29623 mii_regs = NULL; 29073859Sml29623 29083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 29093859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 29103859Sml29623 29113859Sml29623 /* 29125196Ssbehera * The mif phy mode may be connected to either a copper link 29135196Ssbehera * or fiber link. Read the mode control register to get the fiber 29145196Ssbehera * configuration if it is hard-wired to fiber link. 29155196Ssbehera */ 29165196Ssbehera (void) nxge_mii_get_link_mode(nxgep); 29175196Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 29185196Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 29195196Ssbehera } 29205196Ssbehera 29215196Ssbehera /* 29223859Sml29623 * Reset the transceiver. 29233859Sml29623 */ 29243859Sml29623 delay = 0; 29253859Sml29623 bmcr.value = 0; 29263859Sml29623 bmcr.bits.reset = 1; 29273859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 29285125Sjoycey #if defined(__i386) 29295125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 29305125Sjoycey #else 29313859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 29325125Sjoycey #endif 29333859Sml29623 goto fail; 29343859Sml29623 do { 29353859Sml29623 drv_usecwait(500); 29363859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 29375125Sjoycey #if defined(__i386) 29385125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 29395125Sjoycey #else 29403859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 29415125Sjoycey #endif 29423859Sml29623 != NXGE_OK) 29433859Sml29623 goto fail; 29443859Sml29623 delay++; 29453859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 29463859Sml29623 if (delay == 1000) { 29473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 29483859Sml29623 goto fail; 29493859Sml29623 } 29503859Sml29623 29513859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 29525125Sjoycey #if defined(__i386) 29535125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 29545125Sjoycey #else 29553859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 29565125Sjoycey #endif 29573859Sml29623 &bmsr.value)) != NXGE_OK) 29583859Sml29623 goto fail; 29593859Sml29623 29603859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 29613859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 29623859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 29633859Sml29623 param_arr[param_anar_100hdx].value = 0; 29643859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 29653859Sml29623 param_arr[param_anar_10hdx].value = 0; 29663859Sml29623 29673859Sml29623 /* 29683859Sml29623 * Initialize the xcvr statistics. 29693859Sml29623 */ 29703859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 29713859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 29723859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 29733859Sml29623 statsp->mac_stats.cap_100hdx = 0; 29743859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 29753859Sml29623 statsp->mac_stats.cap_10hdx = 0; 29763859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 29773859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 29783859Sml29623 29793859Sml29623 /* 29803859Sml29623 * Initialise the xcvr advertised capability statistics. 29813859Sml29623 */ 29823859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 29833859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 29843859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 29853859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 29863859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 29873859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 29883859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 29893859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 29903859Sml29623 statsp->mac_stats.adv_cap_asmpause = 29913859Sml29623 param_arr[param_anar_asmpause].value; 29923859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 29933859Sml29623 29943859Sml29623 29953859Sml29623 /* 29963859Sml29623 * Check for extended status just in case we're 29973859Sml29623 * running a Gigibit phy. 29983859Sml29623 */ 29993859Sml29623 if (bmsr.bits.extend_status) { 30003859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 30015125Sjoycey #if defined(__i386) 30025125Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 30035125Sjoycey #else 30043859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 30055125Sjoycey #endif 30063859Sml29623 != NXGE_OK) 30073859Sml29623 goto fail; 30083859Sml29623 param_arr[param_anar_1000fdx].value &= 30093859Sml29623 esr.bits.link_1000fdx; 30103859Sml29623 param_arr[param_anar_1000hdx].value = 0; 30113859Sml29623 30123859Sml29623 statsp->mac_stats.cap_1000fdx = 30133859Sml29623 (esr.bits.link_1000Xfdx || 30143859Sml29623 esr.bits.link_1000fdx); 30153859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 30163859Sml29623 } else { 30173859Sml29623 param_arr[param_anar_1000fdx].value = 0; 30183859Sml29623 param_arr[param_anar_1000hdx].value = 0; 30193859Sml29623 } 30203859Sml29623 30213859Sml29623 /* 30223859Sml29623 * Initialize 1G Statistics once the capability is established. 30233859Sml29623 */ 30243859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 30253859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 30263859Sml29623 30273859Sml29623 /* 30283859Sml29623 * Initialise the link statistics. 30293859Sml29623 */ 30303859Sml29623 statsp->mac_stats.link_T4 = 0; 30313859Sml29623 statsp->mac_stats.link_asmpause = 0; 30323859Sml29623 statsp->mac_stats.link_pause = 0; 30333859Sml29623 statsp->mac_stats.link_speed = 0; 30343859Sml29623 statsp->mac_stats.link_duplex = 0; 30353859Sml29623 statsp->mac_stats.link_up = 0; 30363859Sml29623 30373859Sml29623 /* 30383859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 30393859Sml29623 */ 30403859Sml29623 bmcr.value = 0; 30413859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 30425125Sjoycey #if defined(__i386) 30435125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 30445125Sjoycey #else 30453859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 30465125Sjoycey #endif 30473859Sml29623 goto fail; 30483859Sml29623 30493859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 30503859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 30513859Sml29623 bmcr.bits.loopback = 1; 30523859Sml29623 bmcr.bits.enable_autoneg = 0; 30533859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 30543859Sml29623 bmcr.bits.speed_1000_sel = 1; 30553859Sml29623 bmcr.bits.duplex_mode = 1; 30563859Sml29623 param_arr[param_autoneg].value = 0; 30573859Sml29623 } else { 30583859Sml29623 bmcr.bits.loopback = 0; 30593859Sml29623 } 30603859Sml29623 30613859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 30623859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 30633859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 30643859Sml29623 param_arr[param_autoneg].value = 0; 30653859Sml29623 bcm5464r_aux.value = 0; 30663859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 30673859Sml29623 bcm5464r_aux.bits.write_1 = 1; 30683859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 30693859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 30703859Sml29623 != NXGE_OK) 30713859Sml29623 goto fail; 30723859Sml29623 } 30733859Sml29623 30743859Sml29623 if (param_arr[param_autoneg].value) { 30753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30763859Sml29623 "Restarting Auto-negotiation.")); 30773859Sml29623 /* 30783859Sml29623 * Setup our Auto-negotiation advertisement register. 30793859Sml29623 */ 30803859Sml29623 anar.value = 0; 30813859Sml29623 anar.bits.selector = 1; 30823859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 30833859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 30843859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 30853859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 30863859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 30873859Sml29623 anar.bits.cap_asmpause = 0; 30883859Sml29623 anar.bits.cap_pause = 0; 30893859Sml29623 if (param_arr[param_anar_1000fdx].value || 30903859Sml29623 param_arr[param_anar_100fdx].value || 30913859Sml29623 param_arr[param_anar_10fdx].value) { 30923859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 30933859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 30943859Sml29623 } 30953859Sml29623 30963859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 30975125Sjoycey #if defined(__i386) 30985125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 30995125Sjoycey #else 31003859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 31015125Sjoycey #endif 31023859Sml29623 != NXGE_OK) 31033859Sml29623 goto fail; 31043859Sml29623 if (bmsr.bits.extend_status) { 31053859Sml29623 gcr.value = 0; 31063859Sml29623 gcr.bits.ms_mode_en = 31073859Sml29623 param_arr[param_master_cfg_enable].value; 31083859Sml29623 gcr.bits.master = 31093859Sml29623 param_arr[param_master_cfg_value].value; 31103859Sml29623 gcr.bits.link_1000fdx = 31113859Sml29623 param_arr[param_anar_1000fdx].value; 31123859Sml29623 gcr.bits.link_1000hdx = 31133859Sml29623 param_arr[param_anar_1000hdx].value; 31143859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 31155125Sjoycey #if defined(__i386) 31165125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 31175125Sjoycey #else 31183859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 31195125Sjoycey #endif 31203859Sml29623 != NXGE_OK) 31213859Sml29623 goto fail; 31223859Sml29623 } 31233859Sml29623 31243859Sml29623 bmcr.bits.enable_autoneg = 1; 31253859Sml29623 bmcr.bits.restart_autoneg = 1; 31263859Sml29623 31273859Sml29623 } else { 31283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 31293859Sml29623 bmcr.bits.speed_1000_sel = 31303859Sml29623 param_arr[param_anar_1000fdx].value | 31313859Sml29623 param_arr[param_anar_1000hdx].value; 31323859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 31333859Sml29623 (param_arr[param_anar_100fdx].value | 31343859Sml29623 param_arr[param_anar_100hdx].value); 31353859Sml29623 if (bmcr.bits.speed_1000_sel) { 31363859Sml29623 statsp->mac_stats.link_speed = 1000; 31373859Sml29623 gcr.value = 0; 31383859Sml29623 gcr.bits.ms_mode_en = 31393859Sml29623 param_arr[param_master_cfg_enable].value; 31403859Sml29623 gcr.bits.master = 31413859Sml29623 param_arr[param_master_cfg_value].value; 31423859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 31435125Sjoycey #if defined(__i386) 31445125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 31455125Sjoycey #else 31463859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 31475125Sjoycey #endif 31483859Sml29623 gcr.value)) 31493859Sml29623 != NXGE_OK) 31503859Sml29623 goto fail; 31513859Sml29623 if (param_arr[param_anar_1000fdx].value) { 31523859Sml29623 bmcr.bits.duplex_mode = 1; 31533859Sml29623 statsp->mac_stats.link_duplex = 2; 31543859Sml29623 } else 31553859Sml29623 statsp->mac_stats.link_duplex = 1; 31563859Sml29623 } else if (bmcr.bits.speed_sel) { 31573859Sml29623 statsp->mac_stats.link_speed = 100; 31583859Sml29623 if (param_arr[param_anar_100fdx].value) { 31593859Sml29623 bmcr.bits.duplex_mode = 1; 31603859Sml29623 statsp->mac_stats.link_duplex = 2; 31613859Sml29623 } else 31623859Sml29623 statsp->mac_stats.link_duplex = 1; 31633859Sml29623 } else { 31643859Sml29623 statsp->mac_stats.link_speed = 10; 31653859Sml29623 if (param_arr[param_anar_10fdx].value) { 31663859Sml29623 bmcr.bits.duplex_mode = 1; 31673859Sml29623 statsp->mac_stats.link_duplex = 2; 31683859Sml29623 } else 31693859Sml29623 statsp->mac_stats.link_duplex = 1; 31703859Sml29623 } 31713859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 31723859Sml29623 statsp->mac_stats.link_asmpause = 31733859Sml29623 statsp->mac_stats.cap_asmpause; 31743859Sml29623 statsp->mac_stats.link_pause = 31753859Sml29623 statsp->mac_stats.cap_pause; 31763859Sml29623 } 31773859Sml29623 31783859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 31793859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 31803859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 31813859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 31823859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 31833859Sml29623 gcr.value = 0; 31843859Sml29623 gcr.bits.ms_mode_en = 1; 31853859Sml29623 gcr.bits.master = 1; 31863859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 31875125Sjoycey #if defined(__i386) 31885125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 31895125Sjoycey #else 31903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 31915125Sjoycey #endif 31923859Sml29623 gcr.value)) 31933859Sml29623 != NXGE_OK) 31943859Sml29623 goto fail; 31953859Sml29623 bmcr.value = 0; 31963859Sml29623 bmcr.bits.speed_1000_sel = 1; 31973859Sml29623 statsp->mac_stats.link_speed = 1000; 31983859Sml29623 } else if (statsp->port_stats.lb_mode 31993859Sml29623 == nxge_lb_ext100) { 32003859Sml29623 /* BCM5464R 100mbps external loopback mode */ 32013859Sml29623 bmcr.value = 0; 32023859Sml29623 bmcr.bits.speed_sel = 1; 32033859Sml29623 bmcr.bits.duplex_mode = 1; 32043859Sml29623 statsp->mac_stats.link_speed = 100; 32053859Sml29623 } else if (statsp->port_stats.lb_mode 32063859Sml29623 == nxge_lb_ext10) { 32073859Sml29623 /* BCM5464R 10mbps external loopback mode */ 32083859Sml29623 bmcr.value = 0; 32093859Sml29623 bmcr.bits.duplex_mode = 1; 32103859Sml29623 statsp->mac_stats.link_speed = 10; 32113859Sml29623 } 32123859Sml29623 } 32133859Sml29623 } 32143859Sml29623 32153859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 32165125Sjoycey #if defined(__i386) 32175125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 32185125Sjoycey #else 32193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 32205125Sjoycey #endif 32213859Sml29623 bmcr.value)) != NXGE_OK) 32223859Sml29623 goto fail; 32233859Sml29623 32243859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 32255125Sjoycey #if defined(__i386) 32265125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 32275125Sjoycey #else 32283859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 32295125Sjoycey #endif 32303859Sml29623 goto fail; 32313859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 32323859Sml29623 32333859Sml29623 /* 32343859Sml29623 * Initialize the xcvr status kept in the context structure. 32353859Sml29623 */ 32363859Sml29623 nxgep->soft_bmsr.value = 0; 32373859Sml29623 32383859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 32395125Sjoycey #if defined(__i386) 32405125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 32415125Sjoycey #else 32423859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 32435125Sjoycey #endif 32443859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 32453859Sml29623 goto fail; 32463859Sml29623 32473859Sml29623 statsp->mac_stats.xcvr_inits++; 32483859Sml29623 nxgep->bmsr.value = 0; 32493859Sml29623 32503859Sml29623 fail: 32513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 32523859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 32533859Sml29623 return (status); 32543859Sml29623 } 32553859Sml29623 32565196Ssbehera nxge_status_t 32575196Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 32585196Ssbehera { 32595196Ssbehera p_nxge_param_t param_arr; 32605196Ssbehera p_nxge_stats_t statsp; 32615196Ssbehera uint8_t xcvr_portn; 32625196Ssbehera p_mii_regs_t mii_regs; 32635196Ssbehera mii_bmcr_t bmcr; 32645196Ssbehera mii_bmsr_t bmsr; 32655196Ssbehera mii_gcr_t gcr; 32665196Ssbehera mii_esr_t esr; 32675196Ssbehera mii_aux_ctl_t bcm5464r_aux; 32685196Ssbehera int status = NXGE_OK; 32695196Ssbehera 32705196Ssbehera uint_t delay; 32715196Ssbehera 32725196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 32735196Ssbehera 32745196Ssbehera param_arr = nxgep->param_arr; 32755196Ssbehera statsp = nxgep->statsp; 32765196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 32775196Ssbehera 32785196Ssbehera mii_regs = NULL; 32795196Ssbehera 32805196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 32815196Ssbehera "nxge_mii_xcvr_fiber_init: " 32825196Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 32835196Ssbehera 32845196Ssbehera /* 32855196Ssbehera * Reset the transceiver. 32865196Ssbehera */ 32875196Ssbehera delay = 0; 32885196Ssbehera bmcr.value = 0; 32895196Ssbehera bmcr.bits.reset = 1; 32905196Ssbehera 32915196Ssbehera #if defined(__i386) 32925196Ssbehera 32935196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 32945196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 32955196Ssbehera goto fail; 32965196Ssbehera #else 32975196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 32985196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 32995196Ssbehera goto fail; 33005196Ssbehera #endif 33015196Ssbehera do { 33025196Ssbehera drv_usecwait(500); 33035196Ssbehera #if defined(__i386) 33045196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33055196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 33065196Ssbehera != NXGE_OK) 33075196Ssbehera goto fail; 33085196Ssbehera #else 33095196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33105196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 33115196Ssbehera != NXGE_OK) 33125196Ssbehera goto fail; 33135196Ssbehera #endif 33145196Ssbehera delay++; 33155196Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 33165196Ssbehera if (delay == 1000) { 33175196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 33185196Ssbehera goto fail; 33195196Ssbehera } 33205196Ssbehera 33215196Ssbehera #if defined(__i386) 33225196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33235196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 33245196Ssbehera goto fail; 33255196Ssbehera #else 33265196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33275196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 33285196Ssbehera goto fail; 33295196Ssbehera #endif 33305196Ssbehera 33315196Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 33325196Ssbehera param_arr[param_anar_100T4].value = 0; 33335196Ssbehera param_arr[param_anar_100fdx].value = 0; 33345196Ssbehera param_arr[param_anar_100hdx].value = 0; 33355196Ssbehera param_arr[param_anar_10fdx].value = 0; 33365196Ssbehera param_arr[param_anar_10hdx].value = 0; 33375196Ssbehera 33385196Ssbehera /* 33395196Ssbehera * Initialize the xcvr statistics. 33405196Ssbehera */ 33415196Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 33425196Ssbehera statsp->mac_stats.cap_100T4 = 0; 33435196Ssbehera statsp->mac_stats.cap_100fdx = 0; 33445196Ssbehera statsp->mac_stats.cap_100hdx = 0; 33455196Ssbehera statsp->mac_stats.cap_10fdx = 0; 33465196Ssbehera statsp->mac_stats.cap_10hdx = 0; 33475196Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 33485196Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 33495196Ssbehera 33505196Ssbehera /* 33515196Ssbehera * Initialize the xcvr advertised capability statistics. 33525196Ssbehera */ 33535196Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 33545196Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 33555196Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 33565196Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 33575196Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 33585196Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 33595196Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 33605196Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 33615196Ssbehera statsp->mac_stats.adv_cap_asmpause = 33625196Ssbehera param_arr[param_anar_asmpause].value; 33635196Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 33645196Ssbehera 33655196Ssbehera /* 33665196Ssbehera * Check for extended status just in case we're 33675196Ssbehera * running a Gigibit phy. 33685196Ssbehera */ 33695196Ssbehera if (bmsr.bits.extend_status) { 33705196Ssbehera #if defined(__i386) 33715196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33725196Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 33735196Ssbehera NXGE_OK) 33745196Ssbehera goto fail; 33755196Ssbehera #else 33765196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 33775196Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 33785196Ssbehera NXGE_OK) 33795196Ssbehera goto fail; 33805196Ssbehera #endif 33815196Ssbehera param_arr[param_anar_1000fdx].value &= 33825196Ssbehera esr.bits.link_1000fdx; 33835196Ssbehera param_arr[param_anar_1000hdx].value = 0; 33845196Ssbehera 33855196Ssbehera statsp->mac_stats.cap_1000fdx = 33865196Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 33875196Ssbehera statsp->mac_stats.cap_1000hdx = 0; 33885196Ssbehera } else { 33895196Ssbehera param_arr[param_anar_1000fdx].value = 0; 33905196Ssbehera param_arr[param_anar_1000hdx].value = 0; 33915196Ssbehera } 33925196Ssbehera 33935196Ssbehera /* 33945196Ssbehera * Initialize 1G Statistics once the capability is established. 33955196Ssbehera */ 33965196Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 33975196Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 33985196Ssbehera 33995196Ssbehera /* 34005196Ssbehera * Initialize the link statistics. 34015196Ssbehera */ 34025196Ssbehera statsp->mac_stats.link_T4 = 0; 34035196Ssbehera statsp->mac_stats.link_asmpause = 0; 34045196Ssbehera statsp->mac_stats.link_pause = 0; 34055196Ssbehera statsp->mac_stats.link_speed = 0; 34065196Ssbehera statsp->mac_stats.link_duplex = 0; 34075196Ssbehera statsp->mac_stats.link_up = 0; 34085196Ssbehera 34095196Ssbehera /* 34105196Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 34115196Ssbehera */ 34125196Ssbehera bmcr.value = 0; 34135196Ssbehera #if defined(__i386) 34145196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34155196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 34165196Ssbehera goto fail; 34175196Ssbehera #else 34185196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34195196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 34205196Ssbehera goto fail; 34215196Ssbehera #endif 34225196Ssbehera 34235196Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 34245196Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 34255196Ssbehera bmcr.bits.loopback = 1; 34265196Ssbehera bmcr.bits.enable_autoneg = 0; 34275196Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 34285196Ssbehera bmcr.bits.speed_1000_sel = 1; 34295196Ssbehera bmcr.bits.duplex_mode = 1; 34305196Ssbehera param_arr[param_autoneg].value = 0; 34315196Ssbehera } else { 34325196Ssbehera bmcr.bits.loopback = 0; 34335196Ssbehera } 34345196Ssbehera 34355196Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 34365196Ssbehera param_arr[param_autoneg].value = 0; 34375196Ssbehera bcm5464r_aux.value = 0; 34385196Ssbehera bcm5464r_aux.bits.ext_lb = 1; 34395196Ssbehera bcm5464r_aux.bits.write_1 = 1; 34405196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34415196Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 34425196Ssbehera goto fail; 34435196Ssbehera } 34445196Ssbehera 34455196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 34465196Ssbehera bmcr.bits.speed_1000_sel = 1; 34475196Ssbehera bmcr.bits.speed_sel = 0; 34485196Ssbehera bmcr.bits.duplex_mode = 1; 34495196Ssbehera statsp->mac_stats.link_speed = 1000; 34505196Ssbehera statsp->mac_stats.link_duplex = 2; 34515196Ssbehera 34525196Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 34535196Ssbehera /* BCM5464R 1000mbps external loopback mode */ 34545196Ssbehera gcr.value = 0; 34555196Ssbehera gcr.bits.ms_mode_en = 1; 34565196Ssbehera gcr.bits.master = 1; 34575196Ssbehera #if defined(__i386) 34585196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34595196Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 34605196Ssbehera gcr.value)) != NXGE_OK) 34615196Ssbehera goto fail; 34625196Ssbehera #else 34635196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34645196Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 34655196Ssbehera gcr.value)) != NXGE_OK) 34665196Ssbehera goto fail; 34675196Ssbehera #endif 34685196Ssbehera bmcr.value = 0; 34695196Ssbehera bmcr.bits.speed_1000_sel = 1; 34705196Ssbehera statsp->mac_stats.link_speed = 1000; 34715196Ssbehera } 34725196Ssbehera 34735196Ssbehera #if defined(__i386) 34745196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34755196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 34765196Ssbehera bmcr.value)) != NXGE_OK) 34775196Ssbehera goto fail; 34785196Ssbehera #else 34795196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 34805196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 34815196Ssbehera bmcr.value)) != NXGE_OK) 34825196Ssbehera goto fail; 34835196Ssbehera #endif 34845196Ssbehera 34855196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 34865196Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 34875196Ssbehera bmcr.value)); 34885196Ssbehera 34895196Ssbehera #if defined(__i386) 34905196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 34915196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 34925196Ssbehera goto fail; 34935196Ssbehera #else 34945196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 34955196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 34965196Ssbehera goto fail; 34975196Ssbehera #endif 34985196Ssbehera 34995196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 35005196Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 35015196Ssbehera 35025196Ssbehera /* 35035196Ssbehera * Initialize the xcvr status kept in the context structure. 35045196Ssbehera */ 35055196Ssbehera nxgep->soft_bmsr.value = 0; 35065196Ssbehera #if defined(__i386) 35075196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 35085196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 35095196Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 35105196Ssbehera goto fail; 35115196Ssbehera #else 35125196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 35135196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 35145196Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 35155196Ssbehera goto fail; 35165196Ssbehera #endif 35175196Ssbehera 35185196Ssbehera statsp->mac_stats.xcvr_inits++; 35195196Ssbehera nxgep->bmsr.value = 0; 35205196Ssbehera 35215196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 35225196Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 35235196Ssbehera return (status); 35245196Ssbehera 35255196Ssbehera fail: 35265196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35275196Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 35285196Ssbehera return (status); 35295196Ssbehera } 35305196Ssbehera 35313859Sml29623 /* Read from a MII compliant register */ 35323859Sml29623 35333859Sml29623 nxge_status_t 35343859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 35353859Sml29623 uint16_t *value) 35363859Sml29623 { 35373859Sml29623 npi_status_t rs = NPI_SUCCESS; 35383859Sml29623 35393859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 35403859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 35413859Sml29623 35425780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock); 35433859Sml29623 35445196Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 35455196Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 35463859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 35473859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 35483859Sml29623 goto fail; 35494977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 35504977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 35513859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 35523859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 35533859Sml29623 goto fail; 35543859Sml29623 } else 35553859Sml29623 goto fail; 35563859Sml29623 35575780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 35583859Sml29623 35593859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 35603859Sml29623 "xcvr_reg<%d> value=0x%x", 35613859Sml29623 xcvr_portn, xcvr_reg, *value)); 35623859Sml29623 return (NXGE_OK); 35633859Sml29623 fail: 35645780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 35653859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 35663859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 35673859Sml29623 xcvr_portn)); 35683859Sml29623 35693859Sml29623 return (NXGE_ERROR | rs); 35703859Sml29623 } 35713859Sml29623 35723859Sml29623 /* Write to a MII compliant Register */ 35733859Sml29623 35743859Sml29623 nxge_status_t 35753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 35763859Sml29623 uint16_t value) 35773859Sml29623 { 35783859Sml29623 npi_status_t rs = NPI_SUCCESS; 35793859Sml29623 35803859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 35813859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 35823859Sml29623 value)); 35833859Sml29623 35845780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock); 35853859Sml29623 35865196Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 35875196Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 35883859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 35893859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 35903859Sml29623 goto fail; 35914977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 35924977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 35933859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 35943859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 35953859Sml29623 goto fail; 35963859Sml29623 } else 35973859Sml29623 goto fail; 35983859Sml29623 35995780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 36003859Sml29623 36013859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 36023859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 36033859Sml29623 return (NXGE_OK); 36043859Sml29623 fail: 36055780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 36063859Sml29623 36073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 36083859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 36093859Sml29623 xcvr_portn)); 36103859Sml29623 36113859Sml29623 return (NXGE_ERROR | rs); 36123859Sml29623 } 36133859Sml29623 36143859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 36153859Sml29623 36163859Sml29623 nxge_status_t 36173859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 36183859Sml29623 uint16_t xcvr_reg, uint16_t *value) 36193859Sml29623 { 36203859Sml29623 npi_status_t rs = NPI_SUCCESS; 36213859Sml29623 36223859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 36233859Sml29623 xcvr_portn)); 36243859Sml29623 36255780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 36263859Sml29623 36273859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 36283859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 36293859Sml29623 goto fail; 36303859Sml29623 36315780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 36323859Sml29623 36333859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 36343859Sml29623 xcvr_portn)); 36353859Sml29623 return (NXGE_OK); 36363859Sml29623 fail: 36375780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 36383859Sml29623 36393859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 36403859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 36413859Sml29623 xcvr_portn)); 36423859Sml29623 36433859Sml29623 return (NXGE_ERROR | rs); 36443859Sml29623 } 36453859Sml29623 36463859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 36473859Sml29623 36483859Sml29623 nxge_status_t 36493859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 36503859Sml29623 uint16_t xcvr_reg, uint16_t value) 36513859Sml29623 { 36523859Sml29623 npi_status_t rs = NPI_SUCCESS; 36533859Sml29623 36543859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 36553859Sml29623 xcvr_portn)); 36563859Sml29623 36575780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 36583859Sml29623 36593859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 36603859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 36613859Sml29623 goto fail; 36623859Sml29623 36635780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 36643859Sml29623 36653859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 36663859Sml29623 xcvr_portn)); 36673859Sml29623 return (NXGE_OK); 36683859Sml29623 fail: 36695780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 36703859Sml29623 36713859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 36723859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 36733859Sml29623 xcvr_portn)); 36743859Sml29623 36753859Sml29623 return (NXGE_ERROR | rs); 36763859Sml29623 } 36773859Sml29623 36783859Sml29623 36793859Sml29623 /* Check MII to see if there is any link status change */ 36803859Sml29623 36813859Sml29623 nxge_status_t 36823859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 36833859Sml29623 nxge_link_state_t *link_up) 36843859Sml29623 { 36853859Sml29623 p_nxge_param_t param_arr; 36863859Sml29623 p_nxge_stats_t statsp; 36873859Sml29623 p_mii_regs_t mii_regs; 36883859Sml29623 p_mii_bmsr_t soft_bmsr; 36893859Sml29623 mii_anar_t anar; 36903859Sml29623 mii_anlpar_t anlpar; 36913859Sml29623 mii_anar_t an_common; 36923859Sml29623 mii_aner_t aner; 36933859Sml29623 mii_gsr_t gsr; 36943859Sml29623 nxge_status_t status = NXGE_OK; 36953859Sml29623 36963859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 36973859Sml29623 36983859Sml29623 mii_regs = NULL; 36993859Sml29623 param_arr = nxgep->param_arr; 37003859Sml29623 statsp = nxgep->statsp; 37013859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 37023859Sml29623 *link_up = LINK_NO_CHANGE; 37033859Sml29623 37045196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37055196Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 37065196Ssbehera bmsr.value, bmsr_ints.value)); 37075196Ssbehera 37083859Sml29623 if (bmsr_ints.bits.link_status) { 37095196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37105196Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 37115196Ssbehera bmsr.value, bmsr_ints.value)); 37123859Sml29623 if (bmsr.bits.link_status) { 37133859Sml29623 soft_bmsr->bits.link_status = 1; 37145196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37155196Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 37165196Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 37173859Sml29623 } else { 37183859Sml29623 statsp->mac_stats.link_up = 0; 37193859Sml29623 soft_bmsr->bits.link_status = 0; 37203859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37213859Sml29623 "Link down cable problem")); 37223859Sml29623 *link_up = LINK_IS_DOWN; 37233859Sml29623 } 37243859Sml29623 } 37253859Sml29623 37265196Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 37275196Ssbehera param_arr[param_autoneg].value) { 37283859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 37293859Sml29623 if (bmsr.bits.auto_neg_complete) 37303859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 37313859Sml29623 else 37323859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 37333859Sml29623 } 37343859Sml29623 if (soft_bmsr->bits.link_status == 0) { 37353859Sml29623 statsp->mac_stats.link_T4 = 0; 37363859Sml29623 statsp->mac_stats.link_speed = 0; 37373859Sml29623 statsp->mac_stats.link_duplex = 0; 37383859Sml29623 statsp->mac_stats.link_asmpause = 0; 37393859Sml29623 statsp->mac_stats.link_pause = 0; 37403859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 37413859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 37423859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 37433859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 37443859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 37453859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 37463859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 37473859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 37483859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 37493859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 37503859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 37513859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 37523859Sml29623 } 37533859Sml29623 } else 37543859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 37553859Sml29623 37563859Sml29623 if ((bmsr_ints.bits.link_status || 37573859Sml29623 bmsr_ints.bits.auto_neg_complete) && 37583859Sml29623 soft_bmsr->bits.link_status && 37593859Sml29623 soft_bmsr->bits.auto_neg_complete) { 37603859Sml29623 statsp->mac_stats.link_up = 1; 37615196Ssbehera 37625196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37635196Ssbehera "==> nxge_mii_check " 37645196Ssbehera "(auto negotiation complete or link up) " 37655196Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 37665196Ssbehera bmsr.value, bmsr_ints.value)); 37675196Ssbehera 37685196Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 37695196Ssbehera param_arr[param_autoneg].value) { 37703859Sml29623 if ((status = nxge_mii_read(nxgep, 37713859Sml29623 statsp->mac_stats.xcvr_portn, 37725125Sjoycey #if defined(__i386) 37735125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 37745125Sjoycey #else 37753859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 37765125Sjoycey #endif 37773859Sml29623 &anar.value)) != NXGE_OK) 37783859Sml29623 goto fail; 37793859Sml29623 if ((status = nxge_mii_read(nxgep, 37803859Sml29623 statsp->mac_stats.xcvr_portn, 37815125Sjoycey #if defined(__i386) 37825125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 37835125Sjoycey #else 37843859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 37855125Sjoycey #endif 37863859Sml29623 &anlpar.value)) != NXGE_OK) 37873859Sml29623 goto fail; 37883859Sml29623 if ((status = nxge_mii_read(nxgep, 37893859Sml29623 statsp->mac_stats.xcvr_portn, 37905125Sjoycey #if defined(__i386) 37915125Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 37925125Sjoycey #else 37933859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 37945125Sjoycey #endif 37953859Sml29623 &aner.value)) != NXGE_OK) 37963859Sml29623 goto fail; 37973859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 37983859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 37993859Sml29623 statsp->mac_stats.lp_cap_100fdx = 38003859Sml29623 anlpar.bits.cap_100fdx; 38013859Sml29623 statsp->mac_stats.lp_cap_100hdx = 38023859Sml29623 anlpar.bits.cap_100hdx; 38033859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 38043859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 38053859Sml29623 statsp->mac_stats.lp_cap_asmpause = 38063859Sml29623 anlpar.bits.cap_asmpause; 38073859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 38083859Sml29623 an_common.value = anar.value & anlpar.value; 38093859Sml29623 if (param_arr[param_anar_1000fdx].value || 38103859Sml29623 param_arr[param_anar_1000hdx].value) { 38113859Sml29623 if ((status = nxge_mii_read(nxgep, 38123859Sml29623 statsp->mac_stats.xcvr_portn, 38135125Sjoycey #if defined(__i386) 38145125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 38155125Sjoycey #else 38163859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 38175125Sjoycey #endif 38183859Sml29623 &gsr.value)) 38193859Sml29623 != NXGE_OK) 38203859Sml29623 goto fail; 38213859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 38223859Sml29623 gsr.bits.link_1000fdx; 38233859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 38243859Sml29623 gsr.bits.link_1000hdx; 38253859Sml29623 if (param_arr[param_anar_1000fdx].value && 38263859Sml29623 gsr.bits.link_1000fdx) { 38273859Sml29623 statsp->mac_stats.link_speed = 1000; 38283859Sml29623 statsp->mac_stats.link_duplex = 2; 38293859Sml29623 } else if ( 38303859Sml29623 param_arr[param_anar_1000hdx].value && 38313859Sml29623 gsr.bits.link_1000hdx) { 38323859Sml29623 statsp->mac_stats.link_speed = 1000; 38333859Sml29623 statsp->mac_stats.link_duplex = 1; 38343859Sml29623 } 38353859Sml29623 } 38363859Sml29623 if ((an_common.value != 0) && 38373859Sml29623 !(statsp->mac_stats.link_speed)) { 38383859Sml29623 if (an_common.bits.cap_100T4) { 38393859Sml29623 statsp->mac_stats.link_T4 = 1; 38403859Sml29623 statsp->mac_stats.link_speed = 100; 38413859Sml29623 statsp->mac_stats.link_duplex = 1; 38423859Sml29623 } else if (an_common.bits.cap_100fdx) { 38433859Sml29623 statsp->mac_stats.link_speed = 100; 38443859Sml29623 statsp->mac_stats.link_duplex = 2; 38453859Sml29623 } else if (an_common.bits.cap_100hdx) { 38463859Sml29623 statsp->mac_stats.link_speed = 100; 38473859Sml29623 statsp->mac_stats.link_duplex = 1; 38483859Sml29623 } else if (an_common.bits.cap_10fdx) { 38493859Sml29623 statsp->mac_stats.link_speed = 10; 38503859Sml29623 statsp->mac_stats.link_duplex = 2; 38513859Sml29623 } else if (an_common.bits.cap_10hdx) { 38523859Sml29623 statsp->mac_stats.link_speed = 10; 38533859Sml29623 statsp->mac_stats.link_duplex = 1; 38543859Sml29623 } else { 38553859Sml29623 goto fail; 38563859Sml29623 } 38573859Sml29623 } 38583859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 38593859Sml29623 statsp->mac_stats.link_asmpause = 38603859Sml29623 an_common.bits.cap_asmpause; 38613859Sml29623 if (statsp->mac_stats.link_asmpause) 38623859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 38633859Sml29623 (statsp->mac_stats.lp_cap_pause 38643859Sml29623 == 1)) 38653859Sml29623 statsp->mac_stats.link_pause 38663859Sml29623 = 0; 38673859Sml29623 else 38683859Sml29623 statsp->mac_stats.link_pause 38693859Sml29623 = 1; 38703859Sml29623 else 38713859Sml29623 statsp->mac_stats.link_pause = 38723859Sml29623 an_common.bits.cap_pause; 38733859Sml29623 } 38745196Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 38755196Ssbehera statsp->mac_stats.link_speed = 1000; 38765196Ssbehera statsp->mac_stats.link_duplex = 2; 38773859Sml29623 } 38783859Sml29623 *link_up = LINK_IS_UP; 38793859Sml29623 } 38803859Sml29623 38813859Sml29623 if (nxgep->link_notify) { 38823859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 38833859Sml29623 LINK_IS_DOWN); 38843859Sml29623 nxgep->link_notify = B_FALSE; 38853859Sml29623 } 38863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 38873859Sml29623 return (NXGE_OK); 38883859Sml29623 fail: 38893859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38903859Sml29623 "nxge_mii_check: Unable to check MII")); 38913859Sml29623 return (status); 38923859Sml29623 } 38933859Sml29623 38944977Sraghus /* Check PCS to see if there is any link status change */ 38954977Sraghus nxge_status_t 38964977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 38974977Sraghus { 38984977Sraghus p_nxge_stats_t statsp; 38994977Sraghus nxge_status_t status = NXGE_OK; 39004977Sraghus boolean_t linkup; 39014977Sraghus 39024977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 39034977Sraghus 39044977Sraghus statsp = nxgep->statsp; 39054977Sraghus *link_up = LINK_NO_CHANGE; 39064977Sraghus 39074977Sraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 39084977Sraghus if (linkup) { 39094977Sraghus if (nxgep->link_notify || 39104977Sraghus nxgep->statsp->mac_stats.link_up == 0) { 39114977Sraghus statsp->mac_stats.link_up = 1; 39124977Sraghus statsp->mac_stats.link_speed = 1000; 39134977Sraghus statsp->mac_stats.link_duplex = 2; 39144977Sraghus *link_up = LINK_IS_UP; 39154977Sraghus nxgep->link_notify = B_FALSE; 39164977Sraghus } 39174977Sraghus } else { 39184977Sraghus if (nxgep->link_notify || 39194977Sraghus nxgep->statsp->mac_stats.link_up == 1) { 39204977Sraghus statsp->mac_stats.link_up = 0; 39214977Sraghus statsp->mac_stats.link_speed = 0; 39224977Sraghus statsp->mac_stats.link_duplex = 0; 39234977Sraghus *link_up = LINK_IS_DOWN; 39244977Sraghus nxgep->link_notify = B_FALSE; 39254977Sraghus } 39264977Sraghus } 39274977Sraghus 39284977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 39294977Sraghus return (NXGE_OK); 39304977Sraghus fail: 39314977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39324977Sraghus "nxge_pcs_check: Unable to check PCS")); 39334977Sraghus return (status); 39344977Sraghus } 39354977Sraghus 39363859Sml29623 /* Add a multicast address entry into the HW hash table */ 39373859Sml29623 39383859Sml29623 nxge_status_t 39393859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 39403859Sml29623 { 39413859Sml29623 uint32_t mchash; 39423859Sml29623 p_hash_filter_t hash_filter; 39433859Sml29623 uint16_t hash_bit; 39443859Sml29623 boolean_t rx_init = B_FALSE; 39453859Sml29623 uint_t j; 39463859Sml29623 nxge_status_t status = NXGE_OK; 39473859Sml29623 39483859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 39493859Sml29623 39503859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 39513859Sml29623 mchash = crc32_mchash(addrp); 39523859Sml29623 if (nxgep->hash_filter == NULL) { 39533859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 39543859Sml29623 "Allocating hash filter storage.")); 39553859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 39563859Sml29623 KM_SLEEP); 39573859Sml29623 } 39583859Sml29623 hash_filter = nxgep->hash_filter; 39593859Sml29623 j = mchash / HASH_REG_WIDTH; 39603859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 39613859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 39623859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 39633859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 39643859Sml29623 hash_filter->hash_ref_cnt++; 39653859Sml29623 rx_init = B_TRUE; 39663859Sml29623 } 39673859Sml29623 if (rx_init) { 39683859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 39693859Sml29623 goto fail; 39703859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 39713859Sml29623 goto fail; 39723859Sml29623 } 39733859Sml29623 39743859Sml29623 RW_EXIT(&nxgep->filter_lock); 39753859Sml29623 39763859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 39773859Sml29623 39783859Sml29623 return (NXGE_OK); 39793859Sml29623 fail: 39803859Sml29623 RW_EXIT(&nxgep->filter_lock); 39813859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 39823859Sml29623 "Unable to add multicast address")); 39833859Sml29623 return (status); 39843859Sml29623 } 39853859Sml29623 39863859Sml29623 /* Remove a multicast address entry from the HW hash table */ 39873859Sml29623 39883859Sml29623 nxge_status_t 39893859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 39903859Sml29623 { 39913859Sml29623 uint32_t mchash; 39923859Sml29623 p_hash_filter_t hash_filter; 39933859Sml29623 uint16_t hash_bit; 39943859Sml29623 boolean_t rx_init = B_FALSE; 39953859Sml29623 uint_t j; 39963859Sml29623 nxge_status_t status = NXGE_OK; 39973859Sml29623 39983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 39993859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 40003859Sml29623 mchash = crc32_mchash(addrp); 40013859Sml29623 if (nxgep->hash_filter == NULL) { 40023859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 40033859Sml29623 "Hash filter already de_allocated.")); 40043859Sml29623 RW_EXIT(&nxgep->filter_lock); 40053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 40063859Sml29623 return (NXGE_OK); 40073859Sml29623 } 40083859Sml29623 hash_filter = nxgep->hash_filter; 40093859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 40103859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 40113859Sml29623 j = mchash / HASH_REG_WIDTH; 40123859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 40133859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 40143859Sml29623 hash_filter->hash_ref_cnt--; 40153859Sml29623 rx_init = B_TRUE; 40163859Sml29623 } 40173859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 40183859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 40193859Sml29623 "De-allocating hash filter storage.")); 40203859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 40213859Sml29623 nxgep->hash_filter = NULL; 40223859Sml29623 } 40233859Sml29623 40243859Sml29623 if (rx_init) { 40253859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 40263859Sml29623 goto fail; 40273859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 40283859Sml29623 goto fail; 40293859Sml29623 } 40303859Sml29623 RW_EXIT(&nxgep->filter_lock); 40313859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 40323859Sml29623 40333859Sml29623 return (NXGE_OK); 40343859Sml29623 fail: 40353859Sml29623 RW_EXIT(&nxgep->filter_lock); 40363859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 40373859Sml29623 "Unable to remove multicast address")); 40383859Sml29623 40393859Sml29623 return (status); 40403859Sml29623 } 40413859Sml29623 40423859Sml29623 /* Set MAC address into MAC address HW registers */ 40433859Sml29623 40443859Sml29623 nxge_status_t 40453859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 40463859Sml29623 { 40473859Sml29623 nxge_status_t status = NXGE_OK; 40483859Sml29623 40493859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 40503859Sml29623 40513859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 40523859Sml29623 /* 40533859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 40543859Sml29623 */ 40553859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 40563859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 40573859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 40583859Sml29623 goto nxge_set_mac_addr_exit; 40593859Sml29623 } 40603859Sml29623 nxgep->ouraddr = *addrp; 40613859Sml29623 /* 40623859Sml29623 * Set new interface local address and re-init device. 40633859Sml29623 * This is destructive to any other streams attached 40643859Sml29623 * to this device. 40653859Sml29623 */ 40663859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 40673859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 40683859Sml29623 goto fail; 40693859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 40703859Sml29623 goto fail; 40713859Sml29623 40723859Sml29623 RW_EXIT(&nxgep->filter_lock); 40733859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 40743859Sml29623 goto nxge_set_mac_addr_end; 40753859Sml29623 nxge_set_mac_addr_exit: 40763859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 40773859Sml29623 nxge_set_mac_addr_end: 40783859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 40793859Sml29623 40803859Sml29623 return (NXGE_OK); 40813859Sml29623 fail: 40823859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 40833859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 40843859Sml29623 "Unable to set mac address")); 40853859Sml29623 return (status); 40863859Sml29623 } 40873859Sml29623 40884693Stm144005 static 40894693Stm144005 check_link_state_t 40904693Stm144005 nxge_check_link_stop( 40914693Stm144005 nxge_t *nxge) 40924693Stm144005 { 40934693Stm144005 /* If the poll has been cancelled, return STOP. */ 40944693Stm144005 MUTEX_ENTER(&nxge->poll_lock); 40954693Stm144005 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 40964693Stm144005 nxge->poll_state = LINK_MONITOR_STOP; 40974693Stm144005 nxge->nxge_link_poll_timerid = 0; 40984693Stm144005 cv_broadcast(&nxge->poll_cv); 40994693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 41004693Stm144005 41014693Stm144005 NXGE_DEBUG_MSG((nxge, MAC_CTL, 41024693Stm144005 "nxge_check_%s_link(port<%d>) stopped.", 41034693Stm144005 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 41044693Stm144005 nxge->mac.portnum)); 41054693Stm144005 return (CHECK_LINK_STOP); 41064693Stm144005 } 41074693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 41084693Stm144005 41094693Stm144005 return (CHECK_LINK_RESCHEDULE); 41104693Stm144005 } 41114693Stm144005 41123859Sml29623 /* Check status of MII (MIF or PCS) link */ 41133859Sml29623 41144732Sdavemq static nxge_status_t 41153859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 41163859Sml29623 { 41173859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 41183859Sml29623 mii_anlpar_t anlpar; 41193859Sml29623 mii_gsr_t gsr; 41203859Sml29623 p_mii_regs_t mii_regs; 41213859Sml29623 nxge_status_t status = NXGE_OK; 41223859Sml29623 uint8_t portn; 41233859Sml29623 nxge_link_state_t link_up; 41243859Sml29623 41254693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 41264693Stm144005 return (NXGE_ERROR); 41274693Stm144005 41284693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 41294693Stm144005 return (NXGE_OK); 41304693Stm144005 41313859Sml29623 portn = nxgep->mac.portnum; 41323859Sml29623 41333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 41344693Stm144005 portn)); 41353859Sml29623 41363859Sml29623 mii_regs = NULL; 41373859Sml29623 41383859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 41393859Sml29623 41403859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 41413859Sml29623 goto nxge_check_mii_link_exit; 41423859Sml29623 41434977Sraghus switch (nxgep->mac.portmode) { 41444977Sraghus default: 41455196Ssbehera bmsr_data.value = 0; 41463859Sml29623 if ((status = nxge_mii_read(nxgep, 41474977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 41485125Sjoycey #if defined(__i386) 41495125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 41505125Sjoycey #else 41514977Sraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 41525125Sjoycey #endif 41534977Sraghus &bmsr_data.value)) != NXGE_OK) { 41543859Sml29623 goto fail; 41553859Sml29623 } 41564977Sraghus 41575196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41585196Ssbehera "==> nxge_check_mii_link port<0x%x> " 41595196Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 41605572Ssbehera portn, bmsr_data.value, nxgep->bmsr.value)); 41615196Ssbehera 41624977Sraghus if (nxgep->param_arr[param_autoneg].value) { 41634977Sraghus if ((status = nxge_mii_read(nxgep, 41644977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 41655125Sjoycey #if defined(__i386) 41665125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 41675125Sjoycey #else 41684977Sraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 41695125Sjoycey #endif 41704977Sraghus &gsr.value)) != NXGE_OK) 41714977Sraghus goto fail; 41724977Sraghus if ((status = nxge_mii_read(nxgep, 41734977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 41745125Sjoycey #if defined(__i386) 41755125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 41765125Sjoycey #else 41774977Sraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 41785125Sjoycey #endif 41794977Sraghus &anlpar.value)) != NXGE_OK) 41804977Sraghus goto fail; 41815196Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 41825196Ssbehera 41835196Ssbehera if (nxgep->statsp->mac_stats.link_up && 41845196Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 41855196Ssbehera gsr.bits.link_1000fdx) || 41865196Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 41875196Ssbehera gsr.bits.link_1000hdx) || 41885196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 41895196Ssbehera anlpar.bits.cap_100T4) || 41905196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 41915196Ssbehera anlpar.bits.cap_100fdx) || 41925196Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 41935196Ssbehera anlpar.bits.cap_100hdx) || 41945196Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 41955196Ssbehera anlpar.bits.cap_10fdx) || 41965196Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 41975196Ssbehera anlpar.bits.cap_10hdx))) { 41985196Ssbehera bmsr_data.bits.link_status = 0; 41995196Ssbehera } 42004977Sraghus } 42014977Sraghus } 42024977Sraghus 42034977Sraghus /* Workaround for link down issue */ 42044977Sraghus if (bmsr_data.value == 0) { 42054977Sraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 42064977Sraghus goto nxge_check_mii_link_exit; 42074977Sraghus } 42084977Sraghus 42095196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 42105196Ssbehera "==> nxge_check_mii_link port<0x%x> :" 42115196Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 42125572Ssbehera portn, nxgep->bmsr.value, bmsr_data.value)); 42135196Ssbehera 42144977Sraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 42154977Sraghus nxgep->bmsr.value = bmsr_data.value; 42165196Ssbehera 42175196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 42185196Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 42195196Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 42205572Ssbehera portn, bmsr_data.value, bmsr_ints.value)); 42215196Ssbehera 42224977Sraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 42234977Sraghus &link_up)) != NXGE_OK) { 42244977Sraghus goto fail; 42254977Sraghus } 42264977Sraghus break; 42274977Sraghus 42284977Sraghus case PORT_1G_SERDES: 42294977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 42304977Sraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 42314977Sraghus if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 42324977Sraghus != NXGE_OK) { 42334977Sraghus goto fail; 42344977Sraghus } 42354977Sraghus break; 42363859Sml29623 } 42373859Sml29623 42383859Sml29623 nxge_check_mii_link_exit: 42393859Sml29623 RW_EXIT(&nxgep->filter_lock); 42403859Sml29623 if (link_up == LINK_IS_UP) { 42413859Sml29623 nxge_link_is_up(nxgep); 42423859Sml29623 } else if (link_up == LINK_IS_DOWN) { 42433859Sml29623 nxge_link_is_down(nxgep); 42443859Sml29623 } 42453859Sml29623 42463859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 42473859Sml29623 42483859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 42494977Sraghus portn)); 42503859Sml29623 return (NXGE_OK); 42513859Sml29623 42523859Sml29623 fail: 42533859Sml29623 RW_EXIT(&nxgep->filter_lock); 42543859Sml29623 42553859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 42563859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 42574977Sraghus "nxge_check_mii_link: Failed to check link port<%d>", 42584977Sraghus portn)); 42593859Sml29623 return (status); 42603859Sml29623 } 42613859Sml29623 42623859Sml29623 42633859Sml29623 /*ARGSUSED*/ 42644732Sdavemq static nxge_status_t 42653859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 42663859Sml29623 { 42673859Sml29623 uint8_t portn; 42683859Sml29623 nxge_status_t status = NXGE_OK; 42695422Ssbehera boolean_t link_up; 42704977Sraghus uint32_t val; 42714977Sraghus npi_status_t rs; 42723859Sml29623 42734693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 42744693Stm144005 return (NXGE_ERROR); 42754693Stm144005 42764693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 42774693Stm144005 return (NXGE_OK); 42784693Stm144005 42793859Sml29623 portn = nxgep->mac.portnum; 42805196Ssbehera val = 0; 42815196Ssbehera rs = NPI_SUCCESS; 42823859Sml29623 42833859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 42844693Stm144005 portn)); 42853859Sml29623 42864977Sraghus switch (nxgep->mac.portmode) { 42874977Sraghus default: 42885572Ssbehera /* 42895572Ssbehera * Check if the phy is present in case of hot swappable phy 42905572Ssbehera */ 42915572Ssbehera if (nxgep->hot_swappable_phy) { 42925572Ssbehera boolean_t phy_present_now = B_FALSE; 42935572Ssbehera 42945572Ssbehera /* 42955572Ssbehera * If this is the 2nd Goa port, then check 2 addresses 42965572Ssbehera * to take care of the Goa NEM card requirements. 42975572Ssbehera */ 42985572Ssbehera if (portn == 1) { 42995572Ssbehera if (nxge_is_phy_present(nxgep, 43005572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR, 43015572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 43025572Ssbehera phy_present_now = B_TRUE; 43035572Ssbehera nxgep->xcvr_addr = 43045572Ssbehera BCM8706_ALT_GOA_PORT1_ADDR; 43055572Ssbehera goto phy_check_done; 43065572Ssbehera } 43075572Ssbehera } 43085572Ssbehera if (nxge_is_phy_present(nxgep, 43095572Ssbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 43105572Ssbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 43115572Ssbehera nxgep->xcvr_addr = 43125572Ssbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn; 43135572Ssbehera phy_present_now = B_TRUE; 43145572Ssbehera } 43155572Ssbehera 43165572Ssbehera phy_check_done: 43175572Ssbehera if (nxgep->phy_absent) { 43185572Ssbehera if (phy_present_now) { 43195572Ssbehera /* 43205572Ssbehera * Detect, Initialize phy and do link up 43215572Ssbehera * set xcvr vals, link_init, nxge_init 43225572Ssbehera */ 43235572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43245572Ssbehera "Hot swappable phy DETECTED!!")); 43255572Ssbehera nxgep->phy_absent = B_FALSE; 43265572Ssbehera (void) nxge_xcvr_find(nxgep); 43275572Ssbehera (void) nxge_link_init(nxgep); 43285572Ssbehera if (!(nxgep->drv_state & 43295572Ssbehera STATE_HW_INITIALIZED)) { 43305572Ssbehera status = nxge_init(nxgep); 43315572Ssbehera if (status != NXGE_OK) { 43325572Ssbehera NXGE_ERROR_MSG((nxgep, 43335572Ssbehera NXGE_ERR_CTL, 43345572Ssbehera "Hot swappable " 43355572Ssbehera "phy present, but" 43365572Ssbehera " driver init" 43375572Ssbehera " failed...")); 43385572Ssbehera goto fail; 43395572Ssbehera } 43405572Ssbehera } 43415572Ssbehera } 43425572Ssbehera 43435572Ssbehera goto start_link_check; 43445572Ssbehera 43455572Ssbehera } else if (!phy_present_now) { 43465572Ssbehera /* 43475572Ssbehera * Phy gone, bring link down reset xcvr vals 43485572Ssbehera */ 43495572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43505572Ssbehera "Hot swappable phy REMOVED!!")); 43515572Ssbehera nxgep->phy_absent = B_TRUE; 43525572Ssbehera nxgep->statsp->mac_stats.link_up = 0; 43535572Ssbehera nxgep->statsp->mac_stats.link_speed = 0; 43545572Ssbehera nxgep->statsp->mac_stats.link_duplex = 0; 43555572Ssbehera nxge_link_is_down(nxgep); 43565572Ssbehera nxgep->link_notify = B_FALSE; 43575572Ssbehera 43585572Ssbehera (void) nxge_xcvr_find(nxgep); 43595572Ssbehera 43605572Ssbehera goto start_link_check; 43615572Ssbehera 43625572Ssbehera } 43635572Ssbehera } 43645572Ssbehera 43654977Sraghus status = nxge_check_bcm8704_link(nxgep, &link_up); 43664977Sraghus if (status != NXGE_OK) 43674977Sraghus goto fail; 43684977Sraghus break; 43694977Sraghus case PORT_10G_SERDES: 43704977Sraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 43715422Ssbehera XPCS_REG_STATUS, &val); 43724977Sraghus if (rs != 0) 43734977Sraghus goto fail; 43744977Sraghus 43754977Sraghus link_up = B_FALSE; 43765422Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 43775422Ssbehera link_up = B_TRUE; 43784977Sraghus } 43794977Sraghus 43804977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43814977Sraghus "==> nxge_check_10g_link port<%d> " 43825422Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 43835422Ssbehera portn, val, link_up)); 43845422Ssbehera 43854977Sraghus break; 43864977Sraghus } 43873859Sml29623 43883859Sml29623 if (link_up) { 43893859Sml29623 if (nxgep->link_notify || 43903859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 43913859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 43923859Sml29623 goto fail; 43933859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 43943859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 43953859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 43963859Sml29623 43973859Sml29623 nxge_link_is_up(nxgep); 43983859Sml29623 nxgep->link_notify = B_FALSE; 43993859Sml29623 } 44003859Sml29623 } else { 44013859Sml29623 if (nxgep->link_notify || 44023859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 44033859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 44043859Sml29623 goto fail; 44053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44064977Sraghus "Link down cable problem")); 44073859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 44083859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 44093859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 44103859Sml29623 44113859Sml29623 nxge_link_is_down(nxgep); 44123859Sml29623 nxgep->link_notify = B_FALSE; 44133859Sml29623 } 44143859Sml29623 } 44153859Sml29623 44165572Ssbehera start_link_check: 44173859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 44183859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 44194693Stm144005 portn)); 44203859Sml29623 return (NXGE_OK); 44213859Sml29623 44223859Sml29623 fail: 44234693Stm144005 (void) nxge_check_link_stop(nxgep); 44244693Stm144005 44253859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 44264693Stm144005 "nxge_check_10g_link: Failed to check link port<%d>", 44274693Stm144005 portn)); 44283859Sml29623 return (status); 44293859Sml29623 } 44303859Sml29623 44313859Sml29623 44323859Sml29623 /* Declare link down */ 44333859Sml29623 44343859Sml29623 void 44353859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 44363859Sml29623 { 44374732Sdavemq p_nxge_stats_t statsp; 44384732Sdavemq char link_stat_msg[64]; 44394732Sdavemq 44403859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 44413859Sml29623 44424732Sdavemq statsp = nxgep->statsp; 44434732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 44444732Sdavemq statsp->mac_stats.xcvr_portn); 44454732Sdavemq 44464732Sdavemq if (nxge_no_msg == B_FALSE) { 44474732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 44484732Sdavemq } 44494732Sdavemq 44503859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 44513859Sml29623 44523859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 44533859Sml29623 } 44543859Sml29623 44553859Sml29623 /* Declare link up */ 44563859Sml29623 44573859Sml29623 void 44583859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 44593859Sml29623 { 44604732Sdavemq p_nxge_stats_t statsp; 44614732Sdavemq char link_stat_msg[64]; 44623859Sml29623 uint32_t val; 44633859Sml29623 44643859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 44653859Sml29623 44664732Sdavemq statsp = nxgep->statsp; 44674732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 44684732Sdavemq statsp->mac_stats.xcvr_portn, 44694732Sdavemq statsp->mac_stats.link_speed); 44704732Sdavemq 44714732Sdavemq if (statsp->mac_stats.link_T4) 44724732Sdavemq (void) strcat(link_stat_msg, "T4"); 44734732Sdavemq else if (statsp->mac_stats.link_duplex == 2) 44744732Sdavemq (void) strcat(link_stat_msg, "full duplex"); 44754732Sdavemq else 44764732Sdavemq (void) strcat(link_stat_msg, "half duplex"); 44774732Sdavemq 44783859Sml29623 (void) nxge_xif_init(nxgep); 44793859Sml29623 44803859Sml29623 /* Clean up symbol errors incurred during link transition */ 44814977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 44824977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 44833859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 44843859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 44853859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 44863859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 44873859Sml29623 } 44883859Sml29623 44894732Sdavemq if (nxge_no_msg == B_FALSE) { 44904732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 44914732Sdavemq } 44924732Sdavemq 44933859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 44943859Sml29623 44953859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 44963859Sml29623 } 44973859Sml29623 44983859Sml29623 /* 44993859Sml29623 * Calculate the bit in the multicast address filter 45003859Sml29623 * that selects the given * address. 45013859Sml29623 * Note: For GEM, the last 8-bits are used. 45023859Sml29623 */ 45033859Sml29623 uint32_t 45043859Sml29623 crc32_mchash(p_ether_addr_t addr) 45053859Sml29623 { 45063859Sml29623 uint8_t *cp; 45073859Sml29623 uint32_t crc; 45083859Sml29623 uint32_t c; 45093859Sml29623 int byte; 45103859Sml29623 int bit; 45113859Sml29623 45123859Sml29623 cp = (uint8_t *)addr; 45133859Sml29623 crc = (uint32_t)0xffffffff; 45143859Sml29623 for (byte = 0; byte < 6; byte++) { 45153859Sml29623 c = (uint32_t)cp[byte]; 45163859Sml29623 for (bit = 0; bit < 8; bit++) { 45173859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 45183859Sml29623 crc = (crc >> 1)^0xedb88320; 45193859Sml29623 else 45203859Sml29623 crc = (crc >> 1); 45213859Sml29623 c >>= 1; 45223859Sml29623 } 45233859Sml29623 } 45243859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 45253859Sml29623 } 45263859Sml29623 45273859Sml29623 /* Reset serdes */ 45283859Sml29623 45293859Sml29623 nxge_status_t 45303859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 45313859Sml29623 { 45323859Sml29623 npi_handle_t handle; 45333859Sml29623 45343859Sml29623 handle = nxgep->npi_handle; 45353859Sml29623 45363859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 45373859Sml29623 drv_usecwait(500); 45383859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 45393859Sml29623 45403859Sml29623 return (NXGE_OK); 45413859Sml29623 } 45423859Sml29623 45433859Sml29623 /* Monitor link status using interrupt or polling */ 45443859Sml29623 45453859Sml29623 nxge_status_t 45463859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 45473859Sml29623 { 45483859Sml29623 nxge_status_t status = NXGE_OK; 45493859Sml29623 45503859Sml29623 /* 45514693Stm144005 * Return immediately if this is an imaginary XMAC port. 45524693Stm144005 * (At least, we don't have 4-port XMAC cards yet.) 45533859Sml29623 */ 45544977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 45554977Sraghus nxgep->mac.portmode == PORT_10G_SERDES) && 45564977Sraghus (nxgep->mac.portnum > 1)) 45573859Sml29623 return (NXGE_OK); 45583859Sml29623 45593859Sml29623 if (nxgep->statsp == NULL) { 45603859Sml29623 /* stats has not been allocated. */ 45613859Sml29623 return (NXGE_OK); 45623859Sml29623 } 45633859Sml29623 /* Don't check link if we're not in internal loopback mode */ 45643859Sml29623 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 45653859Sml29623 return (NXGE_OK); 45663859Sml29623 45673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45684693Stm144005 "==> nxge_link_monitor port<%d> enable=%d", 45694693Stm144005 nxgep->mac.portnum, enable)); 45703859Sml29623 if (enable == LINK_MONITOR_START) { 45713859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 45723859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 45734693Stm144005 != NXGE_OK) 45743859Sml29623 goto fail; 45753859Sml29623 } else { 45764693Stm144005 timeout_id_t timerid; 45774693Stm144005 45784693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 45794693Stm144005 return (NXGE_OK); 45804693Stm144005 45814732Sdavemq if (nxgep->xcvr.check_link) { 45824732Sdavemq timerid = timeout( 45834732Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 45844693Stm144005 nxgep, 45854693Stm144005 drv_usectohz(LINK_MONITOR_PERIOD)); 45864732Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 45874732Sdavemq nxgep->nxge_link_poll_timerid = timerid; 45884732Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 45894732Sdavemq } else { 45904693Stm144005 return (NXGE_ERROR); 45913859Sml29623 } 45923859Sml29623 } 45933859Sml29623 } else { 45943859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 45953859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 45964693Stm144005 != NXGE_OK) 45973859Sml29623 goto fail; 45983859Sml29623 } else { 45994693Stm144005 clock_t rv; 46004693Stm144005 46014693Stm144005 MUTEX_ENTER(&nxgep->poll_lock); 46024693Stm144005 46034693Stm144005 /* If <timerid> == 0, the link monitor has */ 46044693Stm144005 /* never been started, or just now stopped. */ 46054693Stm144005 if (nxgep->nxge_link_poll_timerid == 0) { 46064693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 46074693Stm144005 return (NXGE_OK); 46084693Stm144005 } 46094693Stm144005 46104693Stm144005 nxgep->poll_state = LINK_MONITOR_STOPPING; 46114693Stm144005 rv = cv_timedwait(&nxgep->poll_cv, 46124693Stm144005 &nxgep->poll_lock, 46134693Stm144005 ddi_get_lbolt() + 46144693Stm144005 drv_usectohz(LM_WAIT_MULTIPLIER * 46154693Stm144005 LINK_MONITOR_PERIOD)); 46164693Stm144005 if (rv == -1) { 46174693Stm144005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46184693Stm144005 "==> stopping port %d: " 46194693Stm144005 "cv_timedwait(%d) timed out", 46204693Stm144005 nxgep->mac.portnum, nxgep->poll_state)); 46214693Stm144005 nxgep->poll_state = LINK_MONITOR_STOP; 46223859Sml29623 nxgep->nxge_link_poll_timerid = 0; 46233859Sml29623 } 46244693Stm144005 46254693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 46263859Sml29623 } 46273859Sml29623 } 46283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 46294693Stm144005 "<== nxge_link_monitor port<%d> enable=%d", 46304693Stm144005 nxgep->mac.portnum, enable)); 46313859Sml29623 return (NXGE_OK); 46323859Sml29623 fail: 46333859Sml29623 return (status); 46343859Sml29623 } 46353859Sml29623 46363859Sml29623 /* Set promiscous mode */ 46373859Sml29623 46383859Sml29623 nxge_status_t 46393859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 46403859Sml29623 { 46413859Sml29623 nxge_status_t status = NXGE_OK; 46423859Sml29623 46434732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 46443859Sml29623 46453859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 46463859Sml29623 46473859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 46483859Sml29623 46493859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 46503859Sml29623 goto fail; 46513859Sml29623 } 46523859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 46533859Sml29623 goto fail; 46543859Sml29623 } 46553859Sml29623 46563859Sml29623 RW_EXIT(&nxgep->filter_lock); 46573859Sml29623 46583859Sml29623 if (on) 46593859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 46603859Sml29623 else 46613859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 46623859Sml29623 46633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 46643859Sml29623 46653859Sml29623 return (NXGE_OK); 46663859Sml29623 fail: 46673859Sml29623 RW_EXIT(&nxgep->filter_lock); 46683859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 46694732Sdavemq "Unable to set promisc (%d)", on)); 46703859Sml29623 46713859Sml29623 return (status); 46723859Sml29623 } 46733859Sml29623 46743859Sml29623 /*ARGSUSED*/ 46753859Sml29623 uint_t 46763859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 46773859Sml29623 { 46783859Sml29623 #ifdef NXGE_DEBUG 46793859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 46803859Sml29623 #endif 46813859Sml29623 #if NXGE_MIF 46823859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 46833859Sml29623 uint32_t status; 46843859Sml29623 npi_handle_t handle; 46853859Sml29623 uint8_t portn; 46863859Sml29623 p_nxge_stats_t statsp; 46873859Sml29623 #endif 46883859Sml29623 46893859Sml29623 #ifdef NXGE_MIF 46903859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 46913859Sml29623 nxgep = ldvp->nxgep; 46923859Sml29623 } 46933859Sml29623 nxgep = ldvp->nxgep; 46943859Sml29623 #endif 46953859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 46963859Sml29623 46973859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 46983859Sml29623 return (DDI_INTR_CLAIMED); 46993859Sml29623 47003859Sml29623 mif_intr_fail: 47013859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 47023859Sml29623 return (DDI_INTR_UNCLAIMED); 47033859Sml29623 } 47043859Sml29623 47053859Sml29623 /*ARGSUSED*/ 47063859Sml29623 uint_t 47073859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 47083859Sml29623 { 47093859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 47103859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 47113859Sml29623 p_nxge_ldg_t ldgp; 47123859Sml29623 uint32_t status; 47133859Sml29623 npi_handle_t handle; 47143859Sml29623 uint8_t portn; 47153859Sml29623 p_nxge_stats_t statsp; 47163859Sml29623 npi_status_t rs = NPI_SUCCESS; 47173859Sml29623 47183859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 47193859Sml29623 nxgep = ldvp->nxgep; 47203859Sml29623 } 47213859Sml29623 47223859Sml29623 ldgp = ldvp->ldgp; 47233859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 47244732Sdavemq "group %d", ldgp->ldg)); 47253859Sml29623 47263859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 47273859Sml29623 /* 47283859Sml29623 * This interrupt handler is for a specific 47293859Sml29623 * mac port. 47303859Sml29623 */ 47313859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 47323859Sml29623 portn = nxgep->mac.portnum; 47333859Sml29623 47343859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 47354732Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 47363859Sml29623 47373859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 47383859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 47393859Sml29623 (xmac_tx_iconfig_t *)&status); 47403859Sml29623 if (rs != NPI_SUCCESS) 47413859Sml29623 goto npi_fail; 47423859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 47433859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 47443859Sml29623 statsp->xmac_stats.tx_underflow_err++; 47453859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 47463859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 47473859Sml29623 } 47483859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 47493859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 47505523Syc148097 /* 47515523Syc148097 * Do not send FMA ereport because this 47525523Syc148097 * error does not indicate HW failure. 47535523Syc148097 */ 47543859Sml29623 } 47553859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 47563859Sml29623 statsp->xmac_stats.tx_overflow_err++; 47573859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 47583859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 47593859Sml29623 } 47603859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 47613859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 47623859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 47633859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 47643859Sml29623 } 47653859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 47663859Sml29623 statsp->xmac_stats.tx_byte_cnt += 47673859Sml29623 XTXMAC_BYTE_CNT_MASK; 47683859Sml29623 } 47693859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 47703859Sml29623 statsp->xmac_stats.tx_frame_cnt += 47713859Sml29623 XTXMAC_FRM_CNT_MASK; 47723859Sml29623 } 47733859Sml29623 } 47743859Sml29623 47753859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 47763859Sml29623 (xmac_rx_iconfig_t *)&status); 47773859Sml29623 if (rs != NPI_SUCCESS) 47783859Sml29623 goto npi_fail; 47793859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 47803859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 47813859Sml29623 statsp->xmac_stats.rx_overflow_err++; 47823859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 47833859Sml29623 statsp->xmac_stats.rx_underflow_err++; 47843859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 47853859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 47863859Sml29623 } 47875523Syc148097 /* 47885523Syc148097 * Do not send FMA ereport for the following 3 errors 47895523Syc148097 * because they do not indicate HW failures. 47905523Syc148097 */ 47913859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 47923859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 47933859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 47943859Sml29623 } 47953859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 47963859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 47973859Sml29623 MAC_LEN_ER_CNT_MASK; 47983859Sml29623 } 47993859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 48003859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 48013859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 48023859Sml29623 } 48033859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 48043859Sml29623 statsp->xmac_stats.rx_byte_cnt += 48053859Sml29623 XRXMAC_BT_CNT_MASK; 48063859Sml29623 } 48073859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 48083859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 48093859Sml29623 XRXMAC_HIST_CNT1_MASK; 48103859Sml29623 } 48113859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 48123859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 48133859Sml29623 XRXMAC_HIST_CNT2_MASK; 48143859Sml29623 } 48153859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 48163859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 48173859Sml29623 XRXMAC_HIST_CNT3_MASK; 48183859Sml29623 } 48193859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 48203859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 48213859Sml29623 XRXMAC_HIST_CNT4_MASK; 48223859Sml29623 } 48233859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 48243859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 48253859Sml29623 XRXMAC_HIST_CNT5_MASK; 48263859Sml29623 } 48273859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 48283859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 48293859Sml29623 XRXMAC_HIST_CNT6_MASK; 48303859Sml29623 } 48313859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 48323859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 48333859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 48343859Sml29623 } 48353859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 48363859Sml29623 statsp->xmac_stats.rx_mult_cnt += 48373859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 48383859Sml29623 } 48395523Syc148097 /* 48405523Syc148097 * Do not send FMA ereport for the following 3 errors 48415523Syc148097 * because they do not indicate HW failures. 48425523Syc148097 */ 48433859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 48443859Sml29623 statsp->xmac_stats.rx_frag_cnt += 48453859Sml29623 XRXMAC_FRAG_CNT_MASK; 48463859Sml29623 } 48473859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 48483859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 48493859Sml29623 XRXMAC_AL_ER_CNT_MASK; 48503859Sml29623 } 48513859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 48523859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 48533859Sml29623 XMAC_LINK_FLT_CNT_MASK; 48543859Sml29623 } 48553859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 48563859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 48573859Sml29623 } 48583859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 48593859Sml29623 statsp->xmac_stats.rx_localfault_err++; 48603859Sml29623 } 48613859Sml29623 } 48623859Sml29623 48633859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 48643859Sml29623 (xmac_ctl_iconfig_t *)&status); 48653859Sml29623 if (rs != NPI_SUCCESS) 48663859Sml29623 goto npi_fail; 48673859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 48683859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 48693859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 48703859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 48713859Sml29623 statsp->xmac_stats.tx_pause_state++; 48723859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 48733859Sml29623 statsp->xmac_stats.tx_nopause_state++; 48743859Sml29623 } 48753859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 48763859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 48773859Sml29623 (bmac_tx_iconfig_t *)&status); 48783859Sml29623 if (rs != NPI_SUCCESS) 48793859Sml29623 goto npi_fail; 48803859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 48813859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 48823859Sml29623 statsp->bmac_stats.tx_underrun_err++; 48833859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 48843859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 48853859Sml29623 } 48863859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 48873859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 48883859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 48893859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 48903859Sml29623 } 48913859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 48923859Sml29623 statsp->bmac_stats.tx_byte_cnt += 48933859Sml29623 BTXMAC_BYTE_CNT_MASK; 48943859Sml29623 } 48953859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 48963859Sml29623 statsp->bmac_stats.tx_frame_cnt += 48973859Sml29623 BTXMAC_FRM_CNT_MASK; 48983859Sml29623 } 48993859Sml29623 } 49003859Sml29623 49013859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 49023859Sml29623 (bmac_rx_iconfig_t *)&status); 49033859Sml29623 if (rs != NPI_SUCCESS) 49043859Sml29623 goto npi_fail; 49053859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 49063859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 49073859Sml29623 statsp->bmac_stats.rx_overflow_err++; 49083859Sml29623 } 49093859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 49103859Sml29623 statsp->bmac_stats.rx_frame_cnt += 49113859Sml29623 RXMAC_FRM_CNT_MASK; 49123859Sml29623 } 49133859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 49143859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 49153859Sml29623 BMAC_CRC_ER_CNT_MASK; 49163859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 49173859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 49183859Sml29623 } 49193859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 49203859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 49213859Sml29623 MAC_LEN_ER_CNT_MASK; 49223859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 49233859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 49243859Sml29623 } 49253859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 49263859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 49273859Sml29623 BMAC_CD_VIO_CNT_MASK; 49283859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 49293859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 49303859Sml29623 } 49313859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 49323859Sml29623 statsp->bmac_stats.rx_byte_cnt += 49333859Sml29623 BRXMAC_BYTE_CNT_MASK; 49343859Sml29623 } 49353859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 49363859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 49373859Sml29623 BMAC_AL_ER_CNT_MASK; 49383859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 49393859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 49403859Sml29623 } 49413859Sml29623 49423859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 49433859Sml29623 (bmac_ctl_iconfig_t *)&status); 49443859Sml29623 if (rs != NPI_SUCCESS) 49453859Sml29623 goto npi_fail; 49463859Sml29623 49473859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 49483859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 49493859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 49503859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 49513859Sml29623 statsp->bmac_stats.tx_pause_state++; 49523859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 49533859Sml29623 statsp->bmac_stats.tx_nopause_state++; 49543859Sml29623 } 49553859Sml29623 } 49563859Sml29623 49573859Sml29623 if (ldgp->nldvs == 1) { 49583859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 49593859Sml29623 B_TRUE, ldgp->ldg_timer); 49603859Sml29623 } 49613859Sml29623 49623859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 49633859Sml29623 return (DDI_INTR_CLAIMED); 49643859Sml29623 49653859Sml29623 npi_fail: 49663859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 49673859Sml29623 return (DDI_INTR_UNCLAIMED); 49683859Sml29623 } 49693859Sml29623 49703859Sml29623 nxge_status_t 49713859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 49723859Sml29623 { 49733859Sml29623 uint8_t phy_port_addr; 49743859Sml29623 nxge_status_t status = NXGE_OK; 49753859Sml29623 boolean_t rx_sig_ok; 49763859Sml29623 boolean_t pcs_blk_lock; 49773859Sml29623 boolean_t link_align; 49783859Sml29623 uint16_t val1, val2, val3; 49793859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 49803859Sml29623 uint16_t val_debug; 49813859Sml29623 uint16_t val; 49823859Sml29623 #endif 49833859Sml29623 49843859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 49853859Sml29623 49863859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 49873859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 49883859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 49893859Sml29623 if ((val_debug & ~0x200) != 0) { 49903859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 49913859Sml29623 nxgep->mac.portnum, val_debug); 49923859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 49933859Sml29623 &val_debug); 49943859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 49953859Sml29623 nxgep->mac.portnum, val_debug); 49963859Sml29623 } 49973859Sml29623 49983859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 49993859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 50003859Sml29623 if (val != 0) 50013859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 50023859Sml29623 50033859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 50043859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 50053859Sml29623 if (val != 0) 50063859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 50073859Sml29623 50083859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 50093859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 50103859Sml29623 if (val != 0) 50113859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 50123859Sml29623 #endif 50133859Sml29623 50143859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 50153859Sml29623 50163859Sml29623 /* Check Device 1 Register 0xA bit0 */ 50173859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 50183859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 50193859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 50203859Sml29623 &val1); 50213859Sml29623 if (status != NXGE_OK) 50223859Sml29623 goto fail; 50233859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 50243859Sml29623 50253859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 50263859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 50273859Sml29623 BCM8704_PCS_DEV_ADDR, 50283859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 50293859Sml29623 &val2)) != NPI_SUCCESS) 50303859Sml29623 goto fail; 50313859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 50323859Sml29623 50333859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 50343859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 50353859Sml29623 BCM8704_PHYXS_ADDR, 50363859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 50373859Sml29623 &val3); 50383859Sml29623 if (status != NXGE_OK) 50393859Sml29623 goto fail; 50405572Ssbehera 50415572Ssbehera switch (nxgep->chip_id) { 50425572Ssbehera case BCM8704_CHIP_ID: 50435572Ssbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 50445572Ssbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 50455572Ssbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 50465572Ssbehera break; 50475572Ssbehera case BCM8706_CHIP_ID: 50485572Ssbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 50495572Ssbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 50505572Ssbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 50515572Ssbehera B_TRUE : B_FALSE; 50525572Ssbehera break; 50535572Ssbehera default: 50545572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 50555572Ssbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 50565572Ssbehera goto fail; 50575572Ssbehera } 50585572Ssbehera 50593859Sml29623 50603859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 50613859Sml29623 /* Temp workaround for link down issue */ 50623859Sml29623 if (pcs_blk_lock == B_FALSE) { 50633859Sml29623 if (val2 != 0x4) { 50643859Sml29623 pcs_blk_lock = B_TRUE; 50653859Sml29623 cmn_err(CE_NOTE, 50663859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 50673859Sml29623 "Reg 0x20 = 0x%x\n", 50683859Sml29623 nxgep->mac.portnum, val2); 50693859Sml29623 } 50703859Sml29623 } 50713859Sml29623 50723859Sml29623 if (link_align == B_FALSE) { 50733859Sml29623 if (val3 != 0x140f) { 50743859Sml29623 link_align = B_TRUE; 50753859Sml29623 cmn_err(CE_NOTE, 50763859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 50773859Sml29623 "Reg 0x18 = 0x%x\n", 50783859Sml29623 nxgep->mac.portnum, val3); 50793859Sml29623 } 50803859Sml29623 } 50813859Sml29623 50823859Sml29623 if (rx_sig_ok == B_FALSE) { 50833859Sml29623 if ((val2 == 0) || (val3 == 0)) { 50843859Sml29623 rx_sig_ok = B_TRUE; 50853859Sml29623 cmn_err(CE_NOTE, 50863859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 50873859Sml29623 nxgep->mac.portnum); 50883859Sml29623 } 50893859Sml29623 } 50903859Sml29623 #endif 50913859Sml29623 50923859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 50933859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 50943859Sml29623 50953859Sml29623 return (NXGE_OK); 50963859Sml29623 fail: 50973859Sml29623 return (status); 50983859Sml29623 } 50993859Sml29623 51003859Sml29623 nxge_status_t 51013859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 51023859Sml29623 { 51033859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 51044732Sdavemq != NPI_SUCCESS) 51053859Sml29623 return (NXGE_ERROR); 51063859Sml29623 else 51073859Sml29623 return (NXGE_OK); 51083859Sml29623 } 51093859Sml29623 51103859Sml29623 nxge_status_t 51113859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 51123859Sml29623 { 51133859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 51144732Sdavemq != NPI_SUCCESS) 51153859Sml29623 return (NXGE_ERROR); 51163859Sml29623 else 51173859Sml29623 return (NXGE_OK); 51183859Sml29623 } 51194185Sspeer 51205572Ssbehera static boolean_t 51215572Ssbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 51225572Ssbehera { 51235572Ssbehera uint32_t pma_pmd_id = 0; 51245572Ssbehera uint32_t pcs_id = 0; 51255572Ssbehera uint32_t phy_id = 0; 51265572Ssbehera 51275572Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 51285572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51295572Ssbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 51305572Ssbehera if ((pma_pmd_id & mask) == (id & mask)) 51315572Ssbehera goto found_phy; 51325572Ssbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 51335572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51345572Ssbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 51355572Ssbehera if ((pcs_id & mask) == (id & mask)) 51365572Ssbehera goto found_phy; 51375572Ssbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 51385572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51395572Ssbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 51405572Ssbehera if ((phy_id & mask) == (id & mask)) 51415572Ssbehera goto found_phy; 51425572Ssbehera 51435572Ssbehera return (B_FALSE); 51445572Ssbehera 51455572Ssbehera found_phy: 51465572Ssbehera return (B_TRUE); 51475572Ssbehera } 51485572Ssbehera 51494732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 51504732Sdavemq 51514732Sdavemq static boolean_t 51524732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 51534732Sdavemq { 51544732Sdavemq int i; 51554732Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 51564732Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 51574732Sdavemq boolean_t found = B_FALSE; 51584732Sdavemq 51594732Sdavemq switch (type) { 51604732Sdavemq case CLAUSE_45_TYPE: 51614732Sdavemq for (i = 0; i < cl45_arr_len; i++) { 51624782Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 51634782Ssbehera (id & BCM_PHY_ID_MASK)) { 51644732Sdavemq found = B_TRUE; 51654732Sdavemq break; 51664732Sdavemq } 51674732Sdavemq } 51684732Sdavemq break; 51694732Sdavemq case CLAUSE_22_TYPE: 51704732Sdavemq for (i = 0; i < cl22_arr_len; i++) { 51714782Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 51724782Ssbehera (id & BCM_PHY_ID_MASK)) { 51734732Sdavemq found = B_TRUE; 51744732Sdavemq break; 51754732Sdavemq } 51764732Sdavemq } 51774732Sdavemq break; 51784732Sdavemq default: 51794732Sdavemq break; 51804732Sdavemq } 51814732Sdavemq 51824732Sdavemq return (found); 51834732Sdavemq } 51844732Sdavemq 51854977Sraghus static uint32_t 51864977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 51874977Sraghus { 51884977Sraghus uint16_t val1 = 0; 51894977Sraghus uint16_t val2 = 0; 51904977Sraghus uint32_t pma_pmd_dev_id = 0; 51914977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 51924977Sraghus 51935780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 51944977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 51954977Sraghus NXGE_DEV_ID_REG_1, &val1); 51964977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 51974977Sraghus NXGE_DEV_ID_REG_2, &val2); 51985780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 51994977Sraghus 52004977Sraghus pma_pmd_dev_id = val1; 52014977Sraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 52024977Sraghus pma_pmd_dev_id |= val2; 52034977Sraghus 52044977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 52054977Sraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 52064977Sraghus 52074977Sraghus return (pma_pmd_dev_id); 52084977Sraghus } 52094977Sraghus 52104977Sraghus static uint32_t 52114977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 52124977Sraghus { 52134977Sraghus uint16_t val1 = 0; 52144977Sraghus uint16_t val2 = 0; 52154977Sraghus uint32_t pcs_dev_id = 0; 52164977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 52174977Sraghus 52185780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 52194977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 52204977Sraghus NXGE_DEV_ID_REG_1, &val1); 52214977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 52224977Sraghus NXGE_DEV_ID_REG_2, &val2); 52235780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 52244977Sraghus 52254977Sraghus pcs_dev_id = val1; 52264977Sraghus pcs_dev_id = (pcs_dev_id << 16); 52274977Sraghus pcs_dev_id |= val2; 52284977Sraghus 52294977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 52304977Sraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 52314977Sraghus 52324977Sraghus return (pcs_dev_id); 52334977Sraghus } 52344977Sraghus 52354977Sraghus static uint32_t 52364977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 52374977Sraghus { 52384977Sraghus uint16_t val1 = 0; 52394977Sraghus uint16_t val2 = 0; 52404977Sraghus uint32_t phy_id = 0; 52414977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 52424977Sraghus npi_status_t npi_status = NPI_SUCCESS; 52434977Sraghus 52445780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock); 52454977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 52464977Sraghus &val1); 52474977Sraghus if (npi_status != NPI_SUCCESS) { 52484977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 52494977Sraghus "clause 22 read to reg 2 failed!!!")); 52504977Sraghus goto exit; 52514977Sraghus } 52524977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 52534977Sraghus &val2); 52544977Sraghus if (npi_status != 0) { 52554977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 52564977Sraghus "clause 22 read to reg 3 failed!!!")); 52574977Sraghus goto exit; 52584977Sraghus } 52594977Sraghus phy_id = val1; 52604977Sraghus phy_id = (phy_id << 16); 52614977Sraghus phy_id |= val2; 52624977Sraghus 52634977Sraghus exit: 52645780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 52654977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 52664977Sraghus phy_port, phy_id)); 52674977Sraghus 52684977Sraghus return (phy_id); 52694977Sraghus } 52704977Sraghus 52714732Sdavemq /* 52724732Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 52734732Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 52744732Sdavemq * read. Then use the values obtained to determine the phy type of each port 52754732Sdavemq * and the Neptune type. 52764732Sdavemq */ 52774732Sdavemq 52784732Sdavemq nxge_status_t 52794732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 52804732Sdavemq { 52814732Sdavemq int i, j, k, l; 52824732Sdavemq uint32_t pma_pmd_dev_id = 0; 52834732Sdavemq uint32_t pcs_dev_id = 0; 52844732Sdavemq uint32_t phy_id = 0; 52854782Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 52864782Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 52874782Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 52884732Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 52894732Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 52905572Ssbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 52915572Ssbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 52924732Sdavemq uint8_t total_port_fd, total_phy_fd; 52934732Sdavemq nxge_status_t status = NXGE_OK; 52944732Sdavemq 52954732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 52964732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 52974732Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 52984732Sdavemq nxgep->niu_type)); 52994732Sdavemq 53004732Sdavemq j = k = l = 0; 53014732Sdavemq total_port_fd = total_phy_fd = 0; 53024732Sdavemq /* 53034732Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 53044732Sdavemq * for on chip serdes usages. 53054732Sdavemq */ 53064732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 53074977Sraghus 53084977Sraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 53094732Sdavemq 53104732Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 53114732Sdavemq pma_pmd_dev_fd[i] = 1; 53124732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 53134732Sdavemq "PMA/PMD dev found", i)); 53144782Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 53154782Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 53164782Ssbehera BCM_PHY_ID_MASK; 53175572Ssbehera port_fd_arr[j] = (uint8_t)i; 53184732Sdavemq j++; 53194732Sdavemq } 53204732Sdavemq } else { 53214732Sdavemq pma_pmd_dev_fd[i] = 0; 53224732Sdavemq } 53234732Sdavemq 53244977Sraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 53254732Sdavemq 53264732Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 53274732Sdavemq pcs_dev_fd[i] = 1; 53284732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 53294732Sdavemq "dev found", i)); 53304782Ssbehera if (k < NXGE_PORTS_NEPTUNE) { 53314782Ssbehera port_pcs_dev_id[k] = pcs_dev_id & 53324782Ssbehera BCM_PHY_ID_MASK; 53335572Ssbehera port_fd_arr[k] = (uint8_t)i; 53344732Sdavemq k++; 53354732Sdavemq } 53364732Sdavemq } else { 53374732Sdavemq pcs_dev_fd[i] = 0; 53384732Sdavemq } 53394732Sdavemq 53405572Ssbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 53415572Ssbehera total_port_fd ++; 53425572Ssbehera } 53434732Sdavemq 53444977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 53454732Sdavemq 53464732Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 53475572Ssbehera total_phy_fd ++; 53484732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 53494732Sdavemq "found", i)); 53504782Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 53514782Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 53525572Ssbehera phy_fd_arr[l] = (uint8_t)i; 53534732Sdavemq l++; 53544732Sdavemq } 53554732Sdavemq } 53564732Sdavemq } 53574732Sdavemq 53584732Sdavemq switch (total_port_fd) { 53594732Sdavemq case 2: 53604732Sdavemq switch (total_phy_fd) { 53614732Sdavemq case 2: 53624977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53634977Sraghus "Unsupported neptune type 1")); 53644977Sraghus goto error_exit; 53654732Sdavemq case 1: 53664732Sdavemq /* TODO - 2 10G, 1 1G */ 53674732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53684732Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 53694732Sdavemq goto error_exit; 53704732Sdavemq case 0: 53714732Sdavemq /* 2 10G */ 53724782Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 53734782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 53744782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 53754782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 53764977Sraghus 53774977Sraghus /* 53784977Sraghus * Check the first phy port address against 53794977Sraghus * the known phy start addresses to determine 53804977Sraghus * the platform type. 53814977Sraghus */ 53825572Ssbehera 53835572Ssbehera switch (port_fd_arr[0]) { 53845572Ssbehera case BCM8704_NEPTUNE_PORT_ADDR_BASE: 53854977Sraghus hw_p->niu_type = NEPTUNE_2_10GF; 53864977Sraghus hw_p->platform_type = 53874977Sraghus P_NEPTUNE_ATLAS_2PORT; 53885572Ssbehera break; 53895572Ssbehera case BCM8706_GOA_PORT_ADDR_BASE: 53905572Ssbehera if (hw_p->platform_type != 53915572Ssbehera P_NEPTUNE_NIU) { 53925572Ssbehera hw_p->platform_type = 53935572Ssbehera P_NEPTUNE_GENERIC; 53945572Ssbehera hw_p->niu_type = 53955572Ssbehera NEPTUNE_2_10GF; 53965572Ssbehera } 53975572Ssbehera break; 53985572Ssbehera default: 53995572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 54004977Sraghus "Unsupported neptune type 2 - 1")); 54014977Sraghus goto error_exit; 54024977Sraghus } 54035572Ssbehera 54045572Ssbehera for (i = 0; i < 2; i++) { 54055572Ssbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 54065572Ssbehera } 54074732Sdavemq } else { 54084732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54094732Sdavemq "Unsupported neptune type 2")); 54104732Sdavemq goto error_exit; 54114732Sdavemq } 54124732Sdavemq break; 54134732Sdavemq case 4: 54144732Sdavemq /* Maramba with 2 XAUI */ 54154782Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 54164782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 54174782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 54184782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 54194782Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 54204782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 54214782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 54224782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 54234732Sdavemq 54244732Sdavemq /* 54254732Sdavemq * Check the first phy port address against 54264732Sdavemq * the known phy start addresses to determine 54274732Sdavemq * the platform type. 54284732Sdavemq */ 54295572Ssbehera switch (phy_fd_arr[0]) { 54305572Ssbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 54314732Sdavemq hw_p->platform_type = 54324732Sdavemq P_NEPTUNE_MARAMBA_P0; 54335572Ssbehera break; 54345572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 54354732Sdavemq hw_p->platform_type = 54364732Sdavemq P_NEPTUNE_MARAMBA_P1; 54375572Ssbehera break; 54385572Ssbehera default: 54394732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 54404732Sdavemq "Unknown port %d...Cannot " 54414732Sdavemq "determine platform type", i)); 54424977Sraghus goto error_exit; 54434732Sdavemq } 54445572Ssbehera 54454977Sraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 54464977Sraghus 54475572Ssbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 54485572Ssbehera hw_p->xcvr_addr[1] = port_fd_arr[1]; 54495572Ssbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 54505572Ssbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 54515572Ssbehera 54524732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54534732Sdavemq "Maramba with 2 XAUI")); 54544732Sdavemq } else { 54554732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54564732Sdavemq "Unsupported neptune type 3")); 54574732Sdavemq goto error_exit; 54584732Sdavemq } 54594732Sdavemq break; 54604732Sdavemq default: 54614732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54624732Sdavemq "Unsupported neptune type 5")); 54634732Sdavemq goto error_exit; 54644732Sdavemq } 54654782Ssbehera break; 54664732Sdavemq case 1: 54674732Sdavemq switch (total_phy_fd) { 54684732Sdavemq case 3: 54694977Sraghus /* 54704977Sraghus * TODO 3 1G, 1 10G mode. 54714977Sraghus * Differentiate between 1_1G_1_10G_2_1G and 54724977Sraghus * 1_10G_3_1G 54734977Sraghus */ 54744977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54754977Sraghus "Unsupported neptune type 7")); 54764977Sraghus goto error_exit; 54774732Sdavemq case 2: 54784732Sdavemq /* 54794732Sdavemq * TODO 2 1G, 1 10G mode. 54804732Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 54814732Sdavemq * 1_10G_2_1G 54824732Sdavemq */ 54834732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54844732Sdavemq "Unsupported neptune type 8")); 54854732Sdavemq goto error_exit; 54864732Sdavemq case 1: 54874732Sdavemq /* 54884732Sdavemq * TODO 1 1G, 1 10G mode. 54894732Sdavemq * Differentiate between 1_1G_1_10G and 54904732Sdavemq * 1_10G_1_1G 54914732Sdavemq */ 54924732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 54934732Sdavemq "Unsupported neptune type 9")); 54944732Sdavemq goto error_exit; 54954732Sdavemq case 0: 54965572Ssbehera /* 1 10G mode, N2 with 1 XAUI */ 54975572Ssbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 54985572Ssbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 54995572Ssbehera 55005572Ssbehera /* 55015572Ssbehera * Check the first phy port address against 55025572Ssbehera * the known phy start addresses to determine 55035572Ssbehera * the platform type. 55045572Ssbehera */ 55055572Ssbehera 55065572Ssbehera switch (port_fd_arr[0]) { 55075572Ssbehera case BCM8704_N2_PORT_ADDR_BASE: 55085572Ssbehera case (BCM8704_N2_PORT_ADDR_BASE + 1): 55095572Ssbehera case BCM8706_ALT_GOA_PORT1_ADDR: 55105572Ssbehera if (hw_p->platform_type != 55115572Ssbehera P_NEPTUNE_NIU) { 55125572Ssbehera hw_p->platform_type = 55135572Ssbehera P_NEPTUNE_GENERIC; 55145572Ssbehera hw_p->niu_type = 55155572Ssbehera NEPTUNE_2_10GF; 55165572Ssbehera } 55175572Ssbehera break; 55185572Ssbehera default: 55195572Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 55205572Ssbehera "Unsupported neptune type 10")); 55215572Ssbehera goto error_exit; 55225572Ssbehera } 55235572Ssbehera 5524*6028Ssbehera hw_p->xcvr_addr[nxgep->function_num] = 5525*6028Ssbehera port_fd_arr[0]; 55265572Ssbehera } else { 55275572Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55285572Ssbehera "Unsupported neptune type 10 - 1")); 55295572Ssbehera goto error_exit; 55305572Ssbehera } 55315572Ssbehera break; 55324732Sdavemq case 4: 55334732Sdavemq /* Maramba with 1 XAUI */ 55344782Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 55354782Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 55364732Sdavemq 55374732Sdavemq /* 55384732Sdavemq * Check the first phy port address against 55394732Sdavemq * the known phy start addresses to determine 55404732Sdavemq * the platform type. 55414732Sdavemq */ 55425572Ssbehera switch (phy_fd_arr[0]) { 55435572Ssbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 55444732Sdavemq hw_p->platform_type = 55454732Sdavemq P_NEPTUNE_MARAMBA_P0; 55465572Ssbehera break; 55475572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 55484732Sdavemq hw_p->platform_type = 55494732Sdavemq P_NEPTUNE_MARAMBA_P1; 55505572Ssbehera break; 55515572Ssbehera default: 55524732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 55534732Sdavemq "Unknown port %d...Cannot " 55545572Ssbehera "determine platform type 10 - 2", 55555572Ssbehera i)); 55564977Sraghus goto error_exit; 55574977Sraghus } 55584977Sraghus 55595572Ssbehera /* 55605572Ssbehera * Check the BCM8704 address to determine 55615572Ssbehera * if XAUI is in port 0 or port 1. 55625572Ssbehera */ 55635572Ssbehera switch (port_fd_arr[0]) { 55645572Ssbehera case BCM8704_MARAMBA_PORT_ADDR_BASE: 55655572Ssbehera hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 55665572Ssbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 55675572Ssbehera for (i = 1; i < NXGE_MAX_PORTS; i++) { 55685572Ssbehera hw_p->xcvr_addr[i] = 55695572Ssbehera phy_fd_arr[i]; 55704977Sraghus } 55715572Ssbehera break; 55725572Ssbehera case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1): 55734977Sraghus hw_p->niu_type = 55744977Sraghus NEPTUNE_1_1GC_1_10GF_2_1GC; 55755572Ssbehera hw_p->xcvr_addr[0] = phy_fd_arr[0]; 55765572Ssbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 55775572Ssbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 55785572Ssbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 55795572Ssbehera break; 55805572Ssbehera default: 55814977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55824977Sraghus "Unsupported neptune type 11")); 55834977Sraghus goto error_exit; 55844732Sdavemq } 55854732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55864732Sdavemq "Maramba with 1 XAUI")); 55874732Sdavemq } else { 55884732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55894732Sdavemq "Unsupported neptune type 12")); 55904732Sdavemq goto error_exit; 55914732Sdavemq } 55924732Sdavemq break; 55934732Sdavemq default: 55944732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55954732Sdavemq "Unsupported neptune type 13")); 55964732Sdavemq goto error_exit; 55974732Sdavemq } 55984732Sdavemq break; 55994732Sdavemq case 0: 56004732Sdavemq switch (total_phy_fd) { 56014732Sdavemq case 4: 56024782Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 56034782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 56044782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 56054782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 56064732Sdavemq 56074732Sdavemq /* 56084732Sdavemq * Check the first phy port address against 56094732Sdavemq * the known phy start addresses to determine 56104732Sdavemq * the platform type. 56114732Sdavemq */ 56125572Ssbehera switch (phy_fd_arr[0]) { 56135572Ssbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 56144732Sdavemq hw_p->platform_type = 56154732Sdavemq P_NEPTUNE_MARAMBA_P1; 56165572Ssbehera break; 56175572Ssbehera case BCM5464_NEPTUNE_PORT_ADDR_BASE: 56184977Sraghus hw_p->platform_type = 56194977Sraghus P_NEPTUNE_ATLAS_4PORT; 56205572Ssbehera break; 56215572Ssbehera default: 56224977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 56234977Sraghus "Unknown port %d...Cannot " 56244977Sraghus "determine platform type", i)); 56254977Sraghus goto error_exit; 56264732Sdavemq } 56274977Sraghus hw_p->niu_type = NEPTUNE_4_1GC; 56285572Ssbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 56295572Ssbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 56305572Ssbehera } 56314732Sdavemq } else { 56324732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56334732Sdavemq "Unsupported neptune type 14")); 56344732Sdavemq goto error_exit; 56354732Sdavemq } 56364732Sdavemq break; 56374732Sdavemq case 3: 56384732Sdavemq /* TODO 3 1G mode */ 56394732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56404732Sdavemq "Unsupported neptune type 15")); 56414732Sdavemq goto error_exit; 56424732Sdavemq case 2: 56434732Sdavemq /* TODO 2 1G mode */ 56444732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56454732Sdavemq "Unsupported neptune type 16")); 56464732Sdavemq goto error_exit; 56474732Sdavemq case 1: 56484732Sdavemq /* TODO 1 1G mode */ 56494732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56504732Sdavemq "Unsupported neptune type 17")); 56514732Sdavemq goto error_exit; 56524732Sdavemq default: 56534732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56544732Sdavemq "Unsupported neptune type 18, total phy fd %d", 56554732Sdavemq total_phy_fd)); 56564732Sdavemq goto error_exit; 56574732Sdavemq } 56584732Sdavemq break; 56594732Sdavemq default: 56604732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56614732Sdavemq "Unsupported neptune type 19")); 56624732Sdavemq goto error_exit; 56634732Sdavemq } 56644732Sdavemq 56654732Sdavemq scan_exit: 56664732Sdavemq 56674732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 56684732Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 56694732Sdavemq return (status); 56704732Sdavemq 56714732Sdavemq error_exit: 56724732Sdavemq return (NXGE_ERROR); 56734732Sdavemq } 56744732Sdavemq 56754185Sspeer boolean_t 56764185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 56774185Sspeer { 56784185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 56794185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 56804185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 56814185Sspeer return (B_FALSE); 56824185Sspeer else 56834185Sspeer return (B_TRUE); 56844185Sspeer } 56854732Sdavemq 56864732Sdavemq static void 56874732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 56884732Sdavemq 56894732Sdavemq npi_status_t rs = NPI_SUCCESS; 56904732Sdavemq uint8_t xcvr_portn; 56914732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 56924732Sdavemq 56934732Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 56944732Sdavemq 56954732Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 56964732Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 56974732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 56984732Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 56994732Sdavemq } 57004732Sdavemq /* 57014732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 57024732Sdavemq * swapped with ethernet port number. This is 57034732Sdavemq * designed for better signal integrity in routing. 57044732Sdavemq */ 57054732Sdavemq switch (portn) { 57064732Sdavemq case 0: 57074732Sdavemq xcvr_portn += 3; 57084732Sdavemq break; 57094732Sdavemq case 1: 57104732Sdavemq xcvr_portn += 2; 57114732Sdavemq break; 57124732Sdavemq case 2: 57134732Sdavemq xcvr_portn += 1; 57144732Sdavemq break; 57154732Sdavemq case 3: 57164732Sdavemq default: 57174732Sdavemq break; 57184732Sdavemq } 57194732Sdavemq 57205780Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mii_lock); 57214732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 57224732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 57234732Sdavemq if (rs != NPI_SUCCESS) { 57244732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57254732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 57264732Sdavemq "returned error 0x[%x]", rs)); 57275780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 57284732Sdavemq return; 57294732Sdavemq } 57304732Sdavemq 57314732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 57324732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 57334732Sdavemq if (rs != NPI_SUCCESS) { 57344732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 57354732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 57364732Sdavemq "returned error 0x[%x]", rs)); 57374732Sdavemq } 57384732Sdavemq 57395780Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mii_lock); 57404732Sdavemq } 57415196Ssbehera 57425196Ssbehera static nxge_status_t 57435196Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 57445196Ssbehera { 57455196Ssbehera p_nxge_stats_t statsp; 57465196Ssbehera uint8_t xcvr_portn; 57475196Ssbehera p_mii_regs_t mii_regs; 57485196Ssbehera mii_mode_control_stat_t mode; 57495196Ssbehera int status = NXGE_OK; 57505196Ssbehera 57515196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 57525196Ssbehera 57535196Ssbehera statsp = nxgep->statsp; 57545196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 57555196Ssbehera mii_regs = NULL; 57565196Ssbehera mode.value = 0; 57575203Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 57585196Ssbehera #if defined(__i386) 57595196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 57605196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 57615196Ssbehera mode.value)) != NXGE_OK) { 57625196Ssbehera goto fail; 57635196Ssbehera #else 57645196Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 57655196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 57665196Ssbehera mode.value)) != NXGE_OK) { 57675196Ssbehera goto fail; 57685196Ssbehera #endif 57695196Ssbehera } 57705196Ssbehera #if defined(__i386) 57715196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 57725196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 57735196Ssbehera &mode.value)) != NXGE_OK) { 57745196Ssbehera goto fail; 57755196Ssbehera } 57765196Ssbehera #else 57775196Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 57785196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 57795196Ssbehera &mode.value)) != NXGE_OK) { 57805196Ssbehera goto fail; 57815196Ssbehera } 57825196Ssbehera #endif 57835196Ssbehera 57845196Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 57855196Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 57865196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 57875196Ssbehera "nxge_mii_get_link_mode: fiber mode")); 57885196Ssbehera } 57895196Ssbehera 57905196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 57915196Ssbehera "nxge_mii_get_link_mode: " 57925196Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 57935203Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 57945196Ssbehera mode.value, nxgep->mac.portmode)); 57955196Ssbehera 57965196Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 57975196Ssbehera "<== nxge_mii_get_link_mode")); 57985196Ssbehera return (status); 57995196Ssbehera fail: 58005196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58015196Ssbehera "<== nxge_mii_get_link_mode (failed)")); 58025196Ssbehera return (NXGE_ERROR); 58035196Ssbehera } 58045196Ssbehera 58055196Ssbehera #ifdef NXGE_DEBUG 58065196Ssbehera static void 58075196Ssbehera nxge_mii_dump(p_nxge_t nxgep) 58085196Ssbehera { 58095196Ssbehera p_nxge_stats_t statsp; 58105196Ssbehera uint8_t xcvr_portn; 58115196Ssbehera p_mii_regs_t mii_regs; 58125196Ssbehera mii_bmcr_t bmcr; 58135196Ssbehera mii_bmsr_t bmsr; 58145196Ssbehera mii_idr1_t idr1; 58155196Ssbehera mii_idr2_t idr2; 58165196Ssbehera mii_mode_control_stat_t mode; 58175196Ssbehera 58185196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 58195196Ssbehera 58205196Ssbehera statsp = nxgep->statsp; 58215196Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 58225196Ssbehera 58235196Ssbehera mii_regs = NULL; 58245196Ssbehera 58255196Ssbehera #if defined(__i386) 58265196Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 58275196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 58285196Ssbehera #else 58295196Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 58305196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 58315196Ssbehera #endif 58325196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58335196Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 58345196Ssbehera xcvr_portn, bmcr.value)); 58355196Ssbehera 58365196Ssbehera #if defined(__i386) 58375196Ssbehera (void) nxge_mii_read(nxgep, 58385196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58395196Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 58405196Ssbehera #else 58415196Ssbehera (void) nxge_mii_read(nxgep, 58425196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58435196Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 58445196Ssbehera #endif 58455196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58465196Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 58475196Ssbehera xcvr_portn, bmsr.value)); 58485196Ssbehera 58495196Ssbehera #if defined(__i386) 58505196Ssbehera (void) nxge_mii_read(nxgep, 58515196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58525196Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 58535196Ssbehera #else 58545196Ssbehera (void) nxge_mii_read(nxgep, 58555196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58565196Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 58575196Ssbehera #endif 58585196Ssbehera 58595196Ssbehera 58605196Ssbehera #if defined(__i386) 58615196Ssbehera (void) nxge_mii_read(nxgep, 58625196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58635196Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 58645196Ssbehera #else 58655196Ssbehera (void) nxge_mii_read(nxgep, 58665196Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 58675196Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 58685196Ssbehera #endif 58695196Ssbehera 58705196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58715196Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 58725196Ssbehera xcvr_portn, idr1.value)); 58735196Ssbehera 58745196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58755196Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 58765196Ssbehera xcvr_portn, idr2.value)); 58775196Ssbehera 58785196Ssbehera mode.value = 0; 58795203Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 58805196Ssbehera 58815196Ssbehera #if defined(__i386) 58825196Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 58835196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 58845196Ssbehera 58855196Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 58865196Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 58875196Ssbehera #else 58885196Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 58895196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 58905196Ssbehera 58915196Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 58925196Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 58935196Ssbehera #endif 58945196Ssbehera 58955196Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 58965196Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 58975196Ssbehera xcvr_portn, mode.value)); 58985196Ssbehera } 58995196Ssbehera #endif 5900