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 /* 223859Sml29623 * Copyright 2007 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 nxge_os_mutex_t nxge_mdio_lock; 383859Sml29623 extern nxge_os_mutex_t nxge_mii_lock; 393859Sml29623 extern boolean_t nxge_jumbo_enable; 403859Sml29623 414693Stm144005 typedef enum { 424693Stm144005 CHECK_LINK_RESCHEDULE, 434693Stm144005 CHECK_LINK_STOP 444693Stm144005 } check_link_state_t; 454693Stm144005 464693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *); 474693Stm144005 483859Sml29623 /* 493859Sml29623 * Ethernet broadcast address definition. 503859Sml29623 */ 513859Sml29623 static ether_addr_st etherbroadcastaddr = 523859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 534732Sdavemq /* 544732Sdavemq * Ethernet zero address definition. 554732Sdavemq */ 564185Sspeer static ether_addr_st etherzeroaddr = 574185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 584732Sdavemq /* 594732Sdavemq * Supported chip types 604732Sdavemq */ 614732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID}; 624732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 634732Sdavemq 644732Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 654732Sdavemq sizeof (uint32_t)) 664732Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 674732Sdavemq sizeof (uint32_t)) 684732Sdavemq /* 694732Sdavemq * static functions 704732Sdavemq */ 714977Sraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 724977Sraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 734977Sraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 744732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_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); 874732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 884732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 894732Sdavemq 904732Sdavemq /* 914732Sdavemq * xcvr tables for supported transceivers 924732Sdavemq */ 934732Sdavemq 944977Sraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 954732Sdavemq nxge_n2_serdes_init, 964732Sdavemq nxge_10G_xcvr_init, 974732Sdavemq nxge_10G_link_intr_stop, 984732Sdavemq nxge_10G_link_intr_start, 994732Sdavemq nxge_check_10g_link, 1004732Sdavemq PCS_XCVR, 1014732Sdavemq BCM8704_N2_PORT_ADDR_BASE 1024732Sdavemq }; 1034732Sdavemq 1044977Sraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1054977Sraghus nxge_n2_serdes_init, 1064977Sraghus nxge_1G_xcvr_init, 1074977Sraghus nxge_1G_fiber_link_intr_stop, 1084977Sraghus nxge_1G_fiber_link_intr_start, 1094977Sraghus nxge_check_mii_link, 1104977Sraghus PCS_XCVR, 1114977Sraghus 0 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, 1204732Sdavemq PCS_XCVR, 1214732Sdavemq BCM8704_NEPTUNE_PORT_ADDR_BASE 1224732Sdavemq }; 1234732Sdavemq 1244732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 1254732Sdavemq NULL, 1264732Sdavemq nxge_1G_xcvr_init, 1274732Sdavemq nxge_1G_copper_link_intr_stop, 1284732Sdavemq nxge_1G_copper_link_intr_start, 1294732Sdavemq nxge_check_mii_link, 1304732Sdavemq INT_MII_XCVR, 1314732Sdavemq BCM5464_NEPTUNE_PORT_ADDR_BASE 1324732Sdavemq }; 1334732Sdavemq 1344732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 1354732Sdavemq nxge_1G_serdes_init, 1364732Sdavemq nxge_1G_xcvr_init, 1374732Sdavemq nxge_1G_fiber_link_intr_stop, 1384732Sdavemq nxge_1G_fiber_link_intr_start, 1394732Sdavemq nxge_check_mii_link, 1404732Sdavemq PCS_XCVR, 1414732Sdavemq 0 1424732Sdavemq }; 1434732Sdavemq 1444732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 1454732Sdavemq nxge_neptune_10G_serdes_init, 1464732Sdavemq NULL, 1474732Sdavemq NULL, 1484732Sdavemq NULL, 1494977Sraghus NULL, 1504732Sdavemq PCS_XCVR, 1514732Sdavemq 0 1524732Sdavemq }; 1533859Sml29623 1543859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 1553859Sml29623 1564977Sraghus nxge_status_t 1574977Sraghus nxge_get_xcvr_type(p_nxge_t nxgep) 1584977Sraghus { 1594977Sraghus nxge_status_t status = NXGE_OK; 1604977Sraghus char *phy_type; 1614977Sraghus char *prop_val; 1624977Sraghus 1634977Sraghus nxgep->mac.portmode = 0; 1644977Sraghus 1654977Sraghus /* Get property from the driver conf. file */ 1664977Sraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 1674977Sraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1684977Sraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 1694977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1704977Sraghus "found conf file: phy-type %s", prop_val)); 1714977Sraghus if (strcmp("xgsd", prop_val) == 0) { 1724977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 1734977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 1744977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1754977Sraghus "found: 10G Serdes")); 1764977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 1774977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 1784977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 1794977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 1804977Sraghus } else if (strcmp("mif", prop_val) == 0) { 1814977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 1824977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 1834977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 1844977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 1854977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 1864977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 1874977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 1884977Sraghus } 1894977Sraghus 1904977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 1914977Sraghus "phy-type", prop_val); 1924977Sraghus ddi_prop_free(prop_val); 1934977Sraghus 1944977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 1954977Sraghus "Got phy type [0x%x] from conf file", 1964977Sraghus nxgep->mac.portmode)); 1974977Sraghus 1984977Sraghus return (NXGE_OK); 1994977Sraghus } 2004977Sraghus /* 2014977Sraghus * TODO add MDIO support for Monza RTM card, Glendale (also Goa) - 2024977Sraghus * only N2-NIU 2034977Sraghus */ 2044977Sraghus if (nxgep->niu_type == N2_NIU) { 2054977Sraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 2064977Sraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 2074977Sraghus if (strcmp("xgf", prop_val) == 0) { 2084977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2094977Sraghus XPCS_XCVR; 2104977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 2114977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2124977Sraghus "10G Fiber Xcvr")); 2134977Sraghus } else if (strcmp("mif", prop_val) == 0) { 2144977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2154977Sraghus INT_MII_XCVR; 2164977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 2174977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2184977Sraghus "1G Copper Xcvr")); 2194977Sraghus } else if (strcmp("pcs", prop_val) == 0) { 2204977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2214977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 2224977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2234977Sraghus "1G Fiber Xcvr")); 2244977Sraghus } else if (strcmp("xgc", prop_val) == 0) { 2254977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = 2264977Sraghus XPCS_XCVR; 2274977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 2284977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2294977Sraghus "10G Copper Xcvr")); 2304977Sraghus } else if (strcmp("xgsd", prop_val) == 0) { 2314977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2324977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 2334977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2344977Sraghus "OBP: 10G Serdes")); 2354977Sraghus } else if (strcmp("gsd", prop_val) == 0) { 2364977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2374977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 2384977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2394977Sraghus "OBP: 1G Serdes")); 2404977Sraghus } else { 2414977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2424977Sraghus "Unknown phy-type: %s", prop_val)); 2434977Sraghus ddi_prop_free(prop_val); 2444977Sraghus return (NXGE_ERROR); 2454977Sraghus } 2464977Sraghus status = NXGE_OK; 2474977Sraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 2484977Sraghus nxgep->dip, "phy-type", prop_val); 2494977Sraghus ddi_prop_free(prop_val); 2504977Sraghus 2514977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 2524977Sraghus "Got phy type [0x%x] from OBP", 2534977Sraghus nxgep->mac.portmode)); 2544977Sraghus 2554977Sraghus return (status); 2564977Sraghus } else { 2574977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2584977Sraghus "Exiting...phy-type property not found")); 2594977Sraghus return (NXGE_ERROR); 2604977Sraghus } 2614977Sraghus } 2624977Sraghus 2634977Sraghus 2644977Sraghus if (!nxgep->vpd_info.present) { 2654977Sraghus return (NXGE_OK); 2664977Sraghus } 2674977Sraghus 2684977Sraghus if (!nxgep->vpd_info.ver_valid) { 2694977Sraghus goto read_seeprom; 2704977Sraghus } 2714977Sraghus 2724977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2734977Sraghus "Reading phy type from expansion ROM")); 2744977Sraghus /* 2754977Sraghus * Try to read the phy type from the vpd data read off the 2764977Sraghus * expansion ROM. 2774977Sraghus */ 2784977Sraghus phy_type = nxgep->vpd_info.phy_type; 2794977Sraghus 2804977Sraghus if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') { 2814977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 2824977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 2834977Sraghus } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 2844977Sraghus phy_type[2] == 'f') { 2854977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 2864977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2874977Sraghus } else if (phy_type[0] == 'p' && phy_type[1] == 'c' && 2884977Sraghus phy_type[2] == 's') { 2894977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 2904977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2914977Sraghus } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 2924977Sraghus phy_type[2] == 'c') { 2934977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 2944977Sraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2954977Sraghus } else { 2964977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2974977Sraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 2984977Sraghus phy_type[0], phy_type[1], phy_type[2])); 2994977Sraghus goto read_seeprom; 3004977Sraghus } 3014977Sraghus 3024977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3034977Sraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 3044977Sraghus 3054977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3064977Sraghus return (status); 3074977Sraghus 3084977Sraghus read_seeprom: 3094977Sraghus /* 3104977Sraghus * read the phy type from the SEEPROM - NCR registers 3114977Sraghus */ 3124977Sraghus status = nxge_espc_phy_type_get(nxgep); 3134977Sraghus if (status != NXGE_OK) { 3144977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3154977Sraghus "Failed to get phy type")); 3164977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3174977Sraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 3184977Sraghus } 3194977Sraghus 3204977Sraghus return (status); 3214977Sraghus 3224977Sraghus } 3234977Sraghus 3244732Sdavemq /* Set up the PHY specific values. */ 3254732Sdavemq 3264732Sdavemq nxge_status_t 3274732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 3284732Sdavemq { 3294732Sdavemq nxge_status_t status = NXGE_OK; 3304732Sdavemq uint32_t port_type; 3314732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3324977Sraghus uint32_t pcs_id = 0; 3334977Sraghus uint32_t pma_pmd_id = 0; 3344977Sraghus uint32_t phy_id = 0; 3354732Sdavemq 3364732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 3374732Sdavemq portn)); 3384732Sdavemq 3394977Sraghus switch (nxgep->niu_type) { 3404977Sraghus case N2_NIU: 3414977Sraghus switch (nxgep->mac.portmode) { 3424977Sraghus case PORT_1G_FIBER: 3434977Sraghus case PORT_1G_SERDES: 3444977Sraghus nxgep->xcvr = nxge_n2_1G_table; 3454977Sraghus nxgep->xcvr.xcvr_addr = portn; 3464977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 3474977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 3484977Sraghus "Serdes")); 3494977Sraghus break; 3504977Sraghus case PORT_10G_FIBER: 3514977Sraghus case PORT_10G_SERDES: 3524977Sraghus nxgep->xcvr = nxge_n2_10G_table; 3534977Sraghus nxgep->xcvr.xcvr_addr += portn; 3544977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 3554977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 3564977Sraghus "Serdes")); 3574977Sraghus break; 3584977Sraghus default: 3594977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3604977Sraghus "<== nxge_setup_xcvr_table: " 3614977Sraghus "Unable to determine NIU portmode")); 3624977Sraghus return (NXGE_ERROR); 3634977Sraghus } 3644977Sraghus break; 3654977Sraghus default: 3664977Sraghus if (nxgep->mac.portmode == 0) { 3674977Sraghus /* 3684977Sraghus * Would be the case for platforms like Maramba 3694977Sraghus * in which the phy type could not be got from conf 3704977Sraghus * file, OBP, VPD or Serial PROM. 3714977Sraghus */ 3724977Sraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 3734977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3744977Sraghus "<== nxge_setup_xcvr_table:" 3754977Sraghus " Invalid Neptune type [0x%x]", 3764977Sraghus nxgep->niu_type)); 3774977Sraghus return (NXGE_ERROR); 3784977Sraghus } 3794977Sraghus 3804977Sraghus port_type = nxgep->niu_type >> 3814977Sraghus (NXGE_PORT_TYPE_SHIFT * portn); 3824977Sraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 3834977Sraghus 3844977Sraghus switch (port_type) { 3854977Sraghus 3864977Sraghus case NXGE_PORT_1G_COPPER: 3874977Sraghus nxgep->mac.portmode = PORT_1G_COPPER; 3884977Sraghus break; 3894977Sraghus case NXGE_PORT_10G_COPPER: 3904977Sraghus nxgep->mac.portmode = PORT_10G_COPPER; 3914977Sraghus break; 3924977Sraghus case NXGE_PORT_1G_FIBRE: 3934977Sraghus nxgep->mac.portmode = PORT_1G_FIBER; 3944977Sraghus break; 3954977Sraghus case NXGE_PORT_10G_FIBRE: 3964977Sraghus nxgep->mac.portmode = PORT_10G_FIBER; 3974977Sraghus break; 3984977Sraghus case NXGE_PORT_1G_SERDES: 3994977Sraghus nxgep->mac.portmode = PORT_1G_SERDES; 4004977Sraghus break; 4014977Sraghus case NXGE_PORT_10G_SERDES: 4024977Sraghus nxgep->mac.portmode = PORT_10G_SERDES; 4034977Sraghus break; 4044977Sraghus case NXGE_PORT_1G_RGMII_FIBER: 4054977Sraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 4064977Sraghus break; 4074977Sraghus default: 4084977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4094977Sraghus "<== nxge_setup_xcvr_table: " 4104977Sraghus "Unknown port-type: 0x%x", port_type)); 4114977Sraghus return (NXGE_ERROR); 4124977Sraghus } 4134977Sraghus } 4144977Sraghus 4154977Sraghus switch (nxgep->mac.portmode) { 4164977Sraghus case PORT_1G_COPPER: 4174977Sraghus case PORT_1G_RGMII_FIBER: 4184732Sdavemq nxgep->xcvr = nxge_1G_copper_table; 4194977Sraghus 4204977Sraghus /* 4214977Sraghus * For Altas 4-1G copper, Xcvr port numbers are 4224977Sraghus * swapped with ethernet port number. This is 4234977Sraghus * designed for better signal integrity in 4244977Sraghus * routing. This is also the case for the 4254977Sraghus * on-board Neptune copper ports on the Maramba 4264977Sraghus * platform. 4274977Sraghus */ 4284977Sraghus switch (nxgep->platform_type) { 4294977Sraghus case P_NEPTUNE_MARAMBA_P1: 4304732Sdavemq nxgep->xcvr.xcvr_addr = 4314732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 4324977Sraghus break; 4334977Sraghus case P_NEPTUNE_MARAMBA_P0: 4344732Sdavemq nxgep->xcvr.xcvr_addr = 4354732Sdavemq BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 4364977Sraghus break; 4374977Sraghus default: 4384977Sraghus break; 4394732Sdavemq } 4404732Sdavemq /* 4414732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 4424732Sdavemq * swapped with ethernet port number. This is 4434977Sraghus * designed for better signal integrity in 4444977Sraghus * routing. This is also the case for the 4454977Sraghus * on-board Neptune copper ports on the Maramba 4464977Sraghus * platform. 4474732Sdavemq */ 4484977Sraghus switch (nxgep->platform_type) { 4494977Sraghus case P_NEPTUNE_ATLAS_4PORT: 4504977Sraghus case P_NEPTUNE_MARAMBA_P0: 4514977Sraghus case P_NEPTUNE_MARAMBA_P1: 4524977Sraghus switch (portn) { 4534977Sraghus case 0: 4544977Sraghus nxgep->xcvr.xcvr_addr += 3; 4554977Sraghus break; 4564977Sraghus case 1: 4574977Sraghus nxgep->xcvr.xcvr_addr += 2; 4584977Sraghus break; 4594977Sraghus case 2: 4604977Sraghus nxgep->xcvr.xcvr_addr += 1; 4614977Sraghus break; 4624977Sraghus case 3: 4634977Sraghus break; 4644977Sraghus default: 4654977Sraghus return (NXGE_ERROR); 4664977Sraghus } 4674732Sdavemq break; 4684732Sdavemq default: 4694977Sraghus break; 4704732Sdavemq } 4714977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 4724977Sraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 4734977Sraghus "Copper" : "RGMII Fiber")); 4744732Sdavemq break; 4754977Sraghus case PORT_10G_COPPER: 4764732Sdavemq nxgep->xcvr = nxge_10G_copper_table; 4774732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 4784732Sdavemq break; 4794977Sraghus case PORT_1G_FIBER: 4804977Sraghus case PORT_1G_SERDES: 4814732Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 4824977Sraghus nxgep->xcvr.xcvr_addr = portn; 4834977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 4844977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 4854977Sraghus "Fiber" : "Serdes")); 4864732Sdavemq break; 4874977Sraghus case PORT_10G_FIBER: 4884977Sraghus case PORT_10G_SERDES: 4894732Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 4904977Sraghus switch (nxgep->platform_type) { 4914977Sraghus case P_NEPTUNE_MARAMBA_P0: 4924977Sraghus case P_NEPTUNE_MARAMBA_P1: 4934732Sdavemq nxgep->xcvr.xcvr_addr = 4944732Sdavemq BCM8704_MARAMBA_PORT_ADDR_BASE; 4954732Sdavemq /* 4964732Sdavemq * Switch off LED for corresponding copper 4974732Sdavemq * port 4984732Sdavemq */ 4994732Sdavemq nxge_bcm5464_link_led_off(nxgep); 5004977Sraghus break; 5014977Sraghus default: 5024977Sraghus break; 5034732Sdavemq } 5044732Sdavemq nxgep->xcvr.xcvr_addr += portn; 5054977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 5064977Sraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 5074977Sraghus "Fiber" : "Serdes")); 5084732Sdavemq break; 5094732Sdavemq default: 5104732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5114732Sdavemq "Unknown port-type: 0x%x", port_type)); 5124732Sdavemq return (NXGE_ERROR); 5134732Sdavemq } 5144732Sdavemq } 5154732Sdavemq 5164732Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 5174732Sdavemq nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr; 5184977Sraghus 5194977Sraghus /* 5204977Sraghus * Get the actual device ID value returned by MDIO read. 5214977Sraghus */ 5224977Sraghus nxgep->statsp->mac_stats.xcvr_id = 0; 5234977Sraghus 5244977Sraghus pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr.xcvr_addr); 5254977Sraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 5264977Sraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 5274977Sraghus } else { 5284977Sraghus pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr.xcvr_addr); 5294977Sraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 5304977Sraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 5314977Sraghus } else { 5324977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, 5334977Sraghus nxgep->xcvr.xcvr_addr); 5344977Sraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 5354977Sraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 5364977Sraghus } 5374977Sraghus } 5384977Sraghus } 5394977Sraghus 5404732Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 5414732Sdavemq 5424977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 5434977Sraghus "[0x%x] platform type[0x%x]", nxgep->niu_type, 5444977Sraghus nxgep->platform_type)); 5454977Sraghus 5464732Sdavemq return (status); 5474732Sdavemq } 5484732Sdavemq 5493859Sml29623 /* Initialize the entire MAC and physical layer */ 5503859Sml29623 5513859Sml29623 nxge_status_t 5523859Sml29623 nxge_mac_init(p_nxge_t nxgep) 5533859Sml29623 { 5543859Sml29623 uint8_t portn; 5553859Sml29623 nxge_status_t status = NXGE_OK; 5563859Sml29623 5573859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5583859Sml29623 5593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 5603859Sml29623 5613859Sml29623 nxgep->mac.portnum = portn; 5623859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 5633859Sml29623 5643859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 5653859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 5663859Sml29623 5673859Sml29623 /* Initialize XIF to configure a network mode */ 5683859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 5693859Sml29623 goto fail; 5703859Sml29623 } 5713859Sml29623 5723859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 5733859Sml29623 goto fail; 5743859Sml29623 } 5753859Sml29623 5763859Sml29623 /* Initialize TX and RX MACs */ 5773859Sml29623 /* 5783859Sml29623 * Always perform XIF init first, before TX and RX MAC init 5793859Sml29623 */ 5803859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 5813859Sml29623 goto fail; 5823859Sml29623 5833859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 5843859Sml29623 goto fail; 5853859Sml29623 5863859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 5873859Sml29623 goto fail; 5883859Sml29623 5893859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 5903859Sml29623 goto fail; 5913859Sml29623 5923859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 5933859Sml29623 goto fail; 5943859Sml29623 5953859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5963859Sml29623 goto fail; 5973859Sml29623 5983859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 5993859Sml29623 6004977Sraghus 6013859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 6023859Sml29623 6033859Sml29623 return (NXGE_OK); 6043859Sml29623 fail: 6053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6063859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 6073859Sml29623 portn)); 6083859Sml29623 return (status); 6093859Sml29623 } 6103859Sml29623 6113859Sml29623 /* Initialize the Ethernet Link */ 6123859Sml29623 6133859Sml29623 nxge_status_t 6143859Sml29623 nxge_link_init(p_nxge_t nxgep) 6153859Sml29623 { 6163859Sml29623 nxge_status_t status = NXGE_OK; 6174977Sraghus nxge_port_mode_t portmode; 6183859Sml29623 #ifdef NXGE_DEBUG 6193859Sml29623 uint8_t portn; 6203859Sml29623 6213859Sml29623 portn = nxgep->mac.portnum; 6223859Sml29623 6233859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 6243859Sml29623 #endif 6253859Sml29623 6264977Sraghus portmode = nxgep->mac.portmode; 6274977Sraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 6284977Sraghus (portmode != PORT_1G_SERDES)) { 6293859Sml29623 /* Workaround to get link up in both NIU ports */ 6304977Sraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 6313859Sml29623 goto fail; 6324977Sraghus } 6333859Sml29623 } 6343859Sml29623 NXGE_DELAY(200000); 6353859Sml29623 /* Initialize internal serdes */ 6363859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 6373859Sml29623 goto fail; 6383859Sml29623 NXGE_DELAY(200000); 6393859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 6403859Sml29623 goto fail; 6413859Sml29623 6423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 6433859Sml29623 6443859Sml29623 return (NXGE_OK); 6453859Sml29623 6463859Sml29623 fail: 6473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6483859Sml29623 "nxge_link_init: ", 6493859Sml29623 "failed to initialize Ethernet link on port<%d>", 6503859Sml29623 portn)); 6513859Sml29623 6523859Sml29623 return (status); 6533859Sml29623 } 6543859Sml29623 6553859Sml29623 6563859Sml29623 /* Initialize the XIF sub-block within the MAC */ 6573859Sml29623 6583859Sml29623 nxge_status_t 6593859Sml29623 nxge_xif_init(p_nxge_t nxgep) 6603859Sml29623 { 6613859Sml29623 uint32_t xif_cfg = 0; 6623859Sml29623 npi_attr_t ap; 6633859Sml29623 uint8_t portn; 6643859Sml29623 nxge_port_t portt; 6653859Sml29623 nxge_port_mode_t portmode; 6663859Sml29623 p_nxge_stats_t statsp; 6673859Sml29623 npi_status_t rs = NPI_SUCCESS; 6683859Sml29623 npi_handle_t handle; 6693859Sml29623 6703859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6713859Sml29623 6723859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 6733859Sml29623 6743859Sml29623 handle = nxgep->npi_handle; 6753859Sml29623 portmode = nxgep->mac.portmode; 6763859Sml29623 portt = nxgep->mac.porttype; 6773859Sml29623 statsp = nxgep->statsp; 6783859Sml29623 6793859Sml29623 if (portt == PORT_TYPE_XMAC) { 6803859Sml29623 6813859Sml29623 /* Setup XIF Configuration for XMAC */ 6823859Sml29623 6833859Sml29623 if ((portmode == PORT_10G_FIBER) || 6844977Sraghus (portmode == PORT_10G_COPPER) || 6854977Sraghus (portmode == PORT_10G_SERDES)) 6863859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 6873859Sml29623 6883859Sml29623 if (portmode == PORT_1G_COPPER) { 6893859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 6903859Sml29623 } 6913859Sml29623 6923859Sml29623 /* Set MAC Internal Loopback if necessary */ 6933859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 6943859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 6953859Sml29623 6963859Sml29623 if (statsp->mac_stats.link_speed == 100) 6973859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 6983859Sml29623 6993859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 7003859Sml29623 7014977Sraghus if ((portmode == PORT_10G_FIBER) || 7024977Sraghus (portmode == PORT_10G_SERDES)) { 7033859Sml29623 if (statsp->mac_stats.link_up) { 7043859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 7053859Sml29623 } else { 7063859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 7073859Sml29623 } 7083859Sml29623 } 7093859Sml29623 7103859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 7113859Sml29623 if (rs != NPI_SUCCESS) 7123859Sml29623 goto fail; 7133859Sml29623 7143859Sml29623 nxgep->mac.xif_config = xif_cfg; 7153859Sml29623 7163859Sml29623 /* Set Port Mode */ 7173859Sml29623 if ((portmode == PORT_10G_FIBER) || 7184977Sraghus (portmode == PORT_10G_COPPER) || 7194977Sraghus (portmode == PORT_10G_SERDES)) { 7203859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 7213859Sml29623 MAC_XGMII_MODE, rs); 7223859Sml29623 if (rs != NPI_SUCCESS) 7233859Sml29623 goto fail; 7243859Sml29623 if (statsp->mac_stats.link_up) { 7253859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 7263859Sml29623 goto fail; 7273859Sml29623 } else { 7283859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 7293859Sml29623 goto fail; 7303859Sml29623 } 7313859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 7324977Sraghus (portmode == PORT_1G_COPPER) || 7334977Sraghus (portmode == PORT_1G_SERDES)) { 7343859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 7353859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 7363859Sml29623 MAC_GMII_MODE, rs); 7373859Sml29623 } else { 7383859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 7393859Sml29623 MAC_MII_MODE, rs); 7403859Sml29623 } 7413859Sml29623 if (rs != NPI_SUCCESS) 7423859Sml29623 goto fail; 7433859Sml29623 } else { 7443859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7453859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 7463859Sml29623 " for port<%d>", portmode, portn)); 7473859Sml29623 goto fail; 7483859Sml29623 } 7493859Sml29623 7503859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 7513859Sml29623 7523859Sml29623 /* Setup XIF Configuration for BMAC */ 7533859Sml29623 7543859Sml29623 if (portmode == PORT_1G_COPPER) { 7553859Sml29623 if (statsp->mac_stats.link_speed == 100) 7563859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 7573859Sml29623 } 7583859Sml29623 7593859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 7603859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 7613859Sml29623 7623859Sml29623 if (statsp->mac_stats.link_speed == 1000) 7633859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 7643859Sml29623 7653859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 7663859Sml29623 7673859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 7683859Sml29623 if (rs != NPI_SUCCESS) 7693859Sml29623 goto fail; 7703859Sml29623 nxgep->mac.xif_config = xif_cfg; 7713859Sml29623 } 7723859Sml29623 7733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 7743859Sml29623 return (NXGE_OK); 7753859Sml29623 fail: 7763859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7773859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 7783859Sml29623 portn)); 7793859Sml29623 return (NXGE_ERROR | rs); 7803859Sml29623 } 7813859Sml29623 7823859Sml29623 /* Initialize the PCS sub-block in the MAC */ 7833859Sml29623 7843859Sml29623 nxge_status_t 7853859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 7863859Sml29623 { 7873859Sml29623 pcs_cfg_t pcs_cfg; 7883859Sml29623 uint32_t val; 7893859Sml29623 uint8_t portn; 7903859Sml29623 nxge_port_mode_t portmode; 7913859Sml29623 npi_handle_t handle; 7923859Sml29623 p_nxge_stats_t statsp; 7933859Sml29623 npi_status_t rs = NPI_SUCCESS; 7943859Sml29623 7953859Sml29623 handle = nxgep->npi_handle; 7963859Sml29623 portmode = nxgep->mac.portmode; 7973859Sml29623 portn = nxgep->mac.portnum; 7983859Sml29623 statsp = nxgep->statsp; 7993859Sml29623 8003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 8013859Sml29623 8024977Sraghus if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 8034977Sraghus if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 8044977Sraghus goto fail; 8054977Sraghus } 8064977Sraghus 8073859Sml29623 /* Initialize port's PCS */ 8083859Sml29623 pcs_cfg.value = 0; 8093859Sml29623 pcs_cfg.bits.w0.enable = 1; 8103859Sml29623 pcs_cfg.bits.w0.mask = 1; 8113859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 8123859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 8134977Sraghus 8144977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8154977Sraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 8164977Sraghus portn, pcs_cfg.value)); 8173859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 8184977Sraghus (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 8193859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 8203859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 8213859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 8223859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 8233859Sml29623 8243859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 8253859Sml29623 goto fail; 8263859Sml29623 8273859Sml29623 /* Set XPCS Internal Loopback if necessary */ 8283859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 8293859Sml29623 XPCS_REG_CONTROL1, &val)) 8303859Sml29623 != NPI_SUCCESS) 8313859Sml29623 goto fail; 8323859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 8333859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 8343859Sml29623 val |= XPCS_CTRL1_LOOPBK; 8353859Sml29623 else 8363859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 8373859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 8383859Sml29623 XPCS_REG_CONTROL1, val)) 8393859Sml29623 != NPI_SUCCESS) 8403859Sml29623 goto fail; 8413859Sml29623 8423859Sml29623 /* Clear descw errors */ 8433859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 8443859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 8453859Sml29623 != NPI_SUCCESS) 8463859Sml29623 goto fail; 8473859Sml29623 /* Clear symbol errors */ 8483859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 8493859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 8503859Sml29623 != NPI_SUCCESS) 8513859Sml29623 goto fail; 8523859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 8533859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 8543859Sml29623 != NPI_SUCCESS) 8553859Sml29623 goto fail; 8563859Sml29623 8573859Sml29623 } else if (portmode == PORT_1G_COPPER) { 8583859Sml29623 if (portn < 4) { 8593859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 8603859Sml29623 PCS_DATAPATH_MODE_MII); 8613859Sml29623 } 8623859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 8633859Sml29623 goto fail; 8643859Sml29623 8653859Sml29623 } else { 8663859Sml29623 goto fail; 8673859Sml29623 } 8683859Sml29623 pass: 8693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 8703859Sml29623 return (NXGE_OK); 8713859Sml29623 fail: 8723859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8733859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 8743859Sml29623 portn)); 8753859Sml29623 return (NXGE_ERROR | rs); 8763859Sml29623 } 8773859Sml29623 8783859Sml29623 /* Initialize the Internal Serdes */ 8793859Sml29623 8803859Sml29623 nxge_status_t 8813859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 8823859Sml29623 { 8833859Sml29623 p_nxge_stats_t statsp; 8843859Sml29623 #ifdef NXGE_DEBUG 8853859Sml29623 uint8_t portn; 8863859Sml29623 #endif 8873859Sml29623 nxge_status_t status = NXGE_OK; 8883859Sml29623 8893859Sml29623 #ifdef NXGE_DEBUG 8903859Sml29623 portn = nxgep->mac.portnum; 8913859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8924732Sdavemq "==> nxge_serdes_init port<%d>", portn)); 8933859Sml29623 #endif 8943859Sml29623 8954732Sdavemq if (nxgep->xcvr.serdes_init) { 8964732Sdavemq statsp = nxgep->statsp; 8974732Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 8984732Sdavemq if (status != NXGE_OK) 8993859Sml29623 goto fail; 9004732Sdavemq statsp->mac_stats.serdes_inits++; 9013859Sml29623 } 9023859Sml29623 9033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 9044732Sdavemq portn)); 9053859Sml29623 9063859Sml29623 return (NXGE_OK); 9073859Sml29623 9083859Sml29623 fail: 9093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9104732Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 9114732Sdavemq portn)); 9123859Sml29623 9133859Sml29623 return (status); 9143859Sml29623 } 9153859Sml29623 9163859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 9173859Sml29623 9184732Sdavemq static nxge_status_t 9193859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 9203859Sml29623 { 9213859Sml29623 uint8_t portn; 9223859Sml29623 int chan; 9233859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 9244977Sraghus esr_ti_cfgpll_l_t pll_sts_l; 9253859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 9263859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 9273859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 9283859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 9294977Sraghus #ifdef NXGE_DEBUG 9304977Sraghus esr_ti_testcfg_t cfg; 9314977Sraghus #endif 9323859Sml29623 esr_ti_testcfg_t test_cfg; 9333859Sml29623 nxge_status_t status = NXGE_OK; 9343859Sml29623 9353859Sml29623 portn = nxgep->mac.portnum; 9363859Sml29623 9373859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 9383859Sml29623 portn)); 9393859Sml29623 9403859Sml29623 tx_cfg_l.value = 0; 9413859Sml29623 tx_cfg_h.value = 0; 9423859Sml29623 rx_cfg_l.value = 0; 9433859Sml29623 rx_cfg_h.value = 0; 9443859Sml29623 pll_cfg_l.value = 0; 9454977Sraghus pll_sts_l.value = 0; 9463859Sml29623 test_cfg.value = 0; 9473859Sml29623 9484977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 9494977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 9503859Sml29623 /* 0x0E01 */ 9513859Sml29623 tx_cfg_l.bits.entx = 1; 9523859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 9533859Sml29623 9543859Sml29623 /* 0x9101 */ 9553859Sml29623 rx_cfg_l.bits.enrx = 1; 9563859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 9573859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 9583859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 9593859Sml29623 9603859Sml29623 /* 0x0008 */ 9613859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 9623859Sml29623 9633859Sml29623 /* Set loopback mode if necessary */ 9643859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 9653859Sml29623 tx_cfg_l.bits.entest = 1; 9663859Sml29623 rx_cfg_l.bits.entest = 1; 9673859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 9683859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 9693859Sml29623 ESR_N2_DEV_ADDR, 9703859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 9713859Sml29623 != NXGE_OK) 9723859Sml29623 goto fail; 9733859Sml29623 } 9743859Sml29623 9753859Sml29623 /* Use default PLL value */ 9763859Sml29623 9774977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 9784977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 9793859Sml29623 9803859Sml29623 /* 0x0E21 */ 9813859Sml29623 tx_cfg_l.bits.entx = 1; 9823859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 9833859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 9843859Sml29623 9853859Sml29623 /* 0x9121 */ 9863859Sml29623 rx_cfg_l.bits.enrx = 1; 9873859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 9883859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 9893859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 9903859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 9913859Sml29623 9924977Sraghus if (portn == 0) { 9934977Sraghus /* 0x8 */ 9944977Sraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 9954977Sraghus } 9963859Sml29623 9973859Sml29623 /* MPY = 0x100 */ 9983859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 9993859Sml29623 10003859Sml29623 /* Set PLL */ 10013859Sml29623 pll_cfg_l.bits.enpll = 1; 10024977Sraghus pll_sts_l.bits.enpll = 1; 10033859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10043859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 10053859Sml29623 != NXGE_OK) 10063859Sml29623 goto fail; 10074977Sraghus 10084977Sraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10094977Sraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 10104977Sraghus goto fail; 10114977Sraghus 10124977Sraghus #ifdef NXGE_DEBUG 10134977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 10144977Sraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 10154977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10164977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 10174977Sraghus portn, pll_cfg_l.value, cfg.value)); 10184977Sraghus 10194977Sraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 10204977Sraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 10214977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10224977Sraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 10234977Sraghus portn, pll_sts_l.value, cfg.value)); 10244977Sraghus #endif 10254977Sraghus 10264977Sraghus /* Set loopback mode if necessary */ 10274977Sraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 10284977Sraghus tx_cfg_l.bits.entest = 1; 10294977Sraghus rx_cfg_l.bits.entest = 1; 10304977Sraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 10314977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10324977Sraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 10334977Sraghus portn, test_cfg.value)); 10344977Sraghus if ((status = nxge_mdio_write(nxgep, portn, 10354977Sraghus ESR_N2_DEV_ADDR, 10364977Sraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 10374977Sraghus goto fail; 10384977Sraghus } 10394977Sraghus } 10403859Sml29623 } else { 10413859Sml29623 goto fail; 10423859Sml29623 } 10433859Sml29623 10443859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 10453859Sml29623 10463859Sml29623 NXGE_DELAY(20); 10473859Sml29623 10483859Sml29623 /* init TX channels */ 10493859Sml29623 for (chan = 0; chan < 4; chan++) { 10503859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10513859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 10523859Sml29623 != NXGE_OK) 10533859Sml29623 goto fail; 10543859Sml29623 10553859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10563859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 10573859Sml29623 != NXGE_OK) 10583859Sml29623 goto fail; 10594977Sraghus 10604977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10614977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 10624977Sraghus portn, chan, tx_cfg_l.value)); 10634977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10644977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 10654977Sraghus portn, chan, tx_cfg_h.value)); 10663859Sml29623 } 10673859Sml29623 10683859Sml29623 /* init RX channels */ 10693859Sml29623 for (chan = 0; chan < 4; chan++) { 10703859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10713859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 10723859Sml29623 != NXGE_OK) 10733859Sml29623 goto fail; 10743859Sml29623 10753859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 10763859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 10773859Sml29623 != NXGE_OK) 10783859Sml29623 goto fail; 10794977Sraghus 10804977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10814977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 10824977Sraghus portn, chan, rx_cfg_l.value)); 10834977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10844977Sraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 10854977Sraghus portn, chan, rx_cfg_h.value)); 10863859Sml29623 } 10873859Sml29623 10883859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 10893859Sml29623 portn)); 10903859Sml29623 10913859Sml29623 return (NXGE_OK); 10923859Sml29623 fail: 10933859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10943859Sml29623 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 10953859Sml29623 portn)); 10963859Sml29623 10973859Sml29623 return (status); 10983859Sml29623 } 10993859Sml29623 11004732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 11014732Sdavemq 11024732Sdavemq static nxge_status_t 11034732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 11043859Sml29623 { 11053859Sml29623 npi_handle_t handle; 11063859Sml29623 uint8_t portn; 11073859Sml29623 int chan; 11083859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 11093859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 11103859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 11113859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 11123859Sml29623 uint64_t val; 11133859Sml29623 uint16_t val16l; 11143859Sml29623 uint16_t val16h; 11153859Sml29623 nxge_status_t status = NXGE_OK; 11163859Sml29623 11173859Sml29623 portn = nxgep->mac.portnum; 11183859Sml29623 11193859Sml29623 if ((portn != 0) && (portn != 1)) 11203859Sml29623 return (NXGE_OK); 11213859Sml29623 11224732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11234732Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 11243859Sml29623 11253859Sml29623 handle = nxgep->npi_handle; 11264732Sdavemq switch (portn) { 11274732Sdavemq case 0: 11284732Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 11294732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 11304732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 11314732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 11324732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 11334732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 11344732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 11354732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 11364732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 11374732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 11384732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 11394732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 11404732Sdavemq 11414732Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 11424732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 11434732Sdavemq ESR_REG_WR(handle, 11444732Sdavemq ESR_0_TEST_CONFIG_REG, 11454732Sdavemq ESR_PAD_LOOPBACK_CH3 | 11464732Sdavemq ESR_PAD_LOOPBACK_CH2 | 11474732Sdavemq ESR_PAD_LOOPBACK_CH1 | 11484732Sdavemq ESR_PAD_LOOPBACK_CH0); 11494732Sdavemq } else { 11504732Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 11513859Sml29623 } 11524732Sdavemq break; 11534732Sdavemq case 1: 11544732Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 11554732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 11564732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 11574732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 11584732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 11594732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 11604732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 11614732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 11624732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 11634732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 11644732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 11654732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 11664732Sdavemq 11674732Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 11684732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 11694732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 11704732Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 11714732Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 11724732Sdavemq } else { 11734732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 11743859Sml29623 } 11754732Sdavemq break; 11764732Sdavemq default: 11774732Sdavemq /* Nothing to do here */ 11784732Sdavemq goto done; 11794732Sdavemq } 11804732Sdavemq 11814732Sdavemq /* init TX RX channels */ 11824732Sdavemq for (chan = 0; chan < 4; chan++) { 11834732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 11844732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 11854732Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 11863859Sml29623 goto fail; 11874732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 11884732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 11894732Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 11903859Sml29623 goto fail; 11913859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 11924732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 11934732Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 11943859Sml29623 goto fail; 11953859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 11964732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 11974732Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 11984732Sdavemq goto fail; 11994732Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 12004732Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 12014732Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 12024732Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 12034732Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 12044732Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 12054732Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 12064732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 12074732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 12084732Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 12094732Sdavemq goto fail; 12104732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 12114732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 12124732Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 12134732Sdavemq goto fail; 12144732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 12154732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 12164732Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 12174732Sdavemq goto fail; 12184732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 12194732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 12204732Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 12213859Sml29623 goto fail; 12223859Sml29623 } 12233859Sml29623 12244732Sdavemq /* Apply Tx core reset */ 12254732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 12264732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 12274732Sdavemq (uint16_t)0)) != NXGE_OK) 12284732Sdavemq goto fail; 12294732Sdavemq 12304732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 12314732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 12324732Sdavemq NXGE_OK) 12334732Sdavemq goto fail; 12344732Sdavemq 12354732Sdavemq NXGE_DELAY(200); 12364732Sdavemq 12374732Sdavemq /* Apply Rx core reset */ 12384732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 12394732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 12404732Sdavemq NXGE_OK) 12414732Sdavemq goto fail; 12424732Sdavemq 12434732Sdavemq NXGE_DELAY(200); 12444732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 12454732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 12464732Sdavemq goto fail; 12474732Sdavemq 12484732Sdavemq NXGE_DELAY(200); 12494732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 12504732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 12514732Sdavemq &val16l)) != NXGE_OK) 12524732Sdavemq goto fail; 12534732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 12544732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 12554732Sdavemq goto fail; 12564732Sdavemq if ((val16l != 0) || (val16h != 0)) { 12574732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12584732Sdavemq "Failed to reset port<%d> XAUI Serdes", portn)); 12594732Sdavemq } 12604732Sdavemq 12614732Sdavemq ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 12624732Sdavemq 12634732Sdavemq if (portn == 0) { 12644732Sdavemq if ((val & ESR_SIG_P0_BITS_MASK) != 12653859Sml29623 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 12663859Sml29623 ESR_SIG_XSERDES_RDY_P0 | 12673859Sml29623 ESR_SIG_XDETECT_P0_CH3 | 12683859Sml29623 ESR_SIG_XDETECT_P0_CH2 | 12693859Sml29623 ESR_SIG_XDETECT_P0_CH1 | 12703859Sml29623 ESR_SIG_XDETECT_P0_CH0)) { 12714732Sdavemq goto fail; 12724732Sdavemq } 12734732Sdavemq } else if (portn == 1) { 12744732Sdavemq if ((val & ESR_SIG_P1_BITS_MASK) != 12753859Sml29623 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 12763859Sml29623 ESR_SIG_XSERDES_RDY_P1 | 12773859Sml29623 ESR_SIG_XDETECT_P1_CH3 | 12783859Sml29623 ESR_SIG_XDETECT_P1_CH2 | 12793859Sml29623 ESR_SIG_XDETECT_P1_CH1 | 12803859Sml29623 ESR_SIG_XDETECT_P1_CH0)) { 12813859Sml29623 goto fail; 12823859Sml29623 } 12833859Sml29623 } 12843859Sml29623 12853859Sml29623 done: 12864732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12874732Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 12884732Sdavemq 12893859Sml29623 return (NXGE_OK); 12903859Sml29623 fail: 12914732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12924732Sdavemq "nxge_neptune_10G_serdes_init: " 12934732Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 12943859Sml29623 12953859Sml29623 return (status); 12963859Sml29623 } 12973859Sml29623 12984732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 12994732Sdavemq 13004732Sdavemq static nxge_status_t 13014732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 13023859Sml29623 { 13034732Sdavemq npi_handle_t handle; 13044732Sdavemq uint8_t portn; 13054732Sdavemq uint64_t val; 13063859Sml29623 13073859Sml29623 portn = nxgep->mac.portnum; 13084732Sdavemq 13094732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13104732Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 13114732Sdavemq 13124732Sdavemq handle = nxgep->npi_handle; 13134732Sdavemq 13144732Sdavemq ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val); 13154732Sdavemq val &= ~ESR_PLL_CFG_FBDIV_2; 13164732Sdavemq switch (portn) { 13174732Sdavemq case 0: 13184732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_0; 13194732Sdavemq break; 13204732Sdavemq case 1: 13214732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_1; 13224732Sdavemq break; 13234732Sdavemq case 2: 13244732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_2; 13254732Sdavemq break; 13264732Sdavemq case 3: 13274732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_3; 13284732Sdavemq break; 13294732Sdavemq default: 13304732Sdavemq goto fail; 13313859Sml29623 } 13323859Sml29623 13334732Sdavemq ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 13344732Sdavemq 13354732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13364732Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 13373859Sml29623 return (NXGE_OK); 13384732Sdavemq fail: 13394732Sdavemq NXGE_DEBUG_MSG((nxgep, TX_CTL, 13404732Sdavemq "nxge_1G_serdes_init: " 13414732Sdavemq "Failed to initialize Neptune serdes for port<%d>", 13424732Sdavemq portn)); 13434732Sdavemq 13444732Sdavemq return (NXGE_ERROR); 13453859Sml29623 } 13463859Sml29623 13474732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */ 13484732Sdavemq 13494732Sdavemq static nxge_status_t 13504732Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep) 13513859Sml29623 { 13523859Sml29623 p_nxge_stats_t statsp; 13533859Sml29623 uint16_t val; 13543859Sml29623 #ifdef NXGE_DEBUG 13553859Sml29623 uint8_t portn; 13563859Sml29623 uint16_t val1; 13573859Sml29623 #endif 13583859Sml29623 uint8_t phy_port_addr; 13593859Sml29623 pmd_tx_control_t tx_ctl; 13603859Sml29623 control_t ctl; 13613859Sml29623 phyxs_control_t phyxs_ctl; 13623859Sml29623 pcs_control_t pcs_ctl; 13633859Sml29623 uint32_t delay = 0; 13643859Sml29623 optics_dcntr_t op_ctr; 13653859Sml29623 nxge_status_t status = NXGE_OK; 13663859Sml29623 #ifdef NXGE_DEBUG 13673859Sml29623 portn = nxgep->mac.portnum; 13683859Sml29623 #endif 13694732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 13704732Sdavemq portn)); 13714732Sdavemq 13724732Sdavemq statsp = nxgep->statsp; 13734732Sdavemq 13744977Sraghus if (nxgep->mac.portmode == PORT_10G_SERDES) { 13754977Sraghus goto done; 13764977Sraghus } 13774977Sraghus 13784732Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 13794732Sdavemq 13804732Sdavemq /* Disable Link LEDs */ 13814732Sdavemq if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 13824732Sdavemq goto fail; 13834732Sdavemq 13844732Sdavemq /* Set Clause 45 */ 13854732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 13864732Sdavemq 13874732Sdavemq /* Reset the transceiver */ 13884732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 13894732Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 13904732Sdavemq goto fail; 13914732Sdavemq 13924732Sdavemq phyxs_ctl.bits.reset = 1; 13934732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 13944732Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 13954732Sdavemq goto fail; 13964732Sdavemq 13974732Sdavemq do { 13984732Sdavemq drv_usecwait(500); 13994732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14004732Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 14014732Sdavemq &phyxs_ctl.value)) != NXGE_OK) 14024732Sdavemq goto fail; 14034732Sdavemq delay++; 14044732Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 14054732Sdavemq if (delay == 100) { 14064732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 14074732Sdavemq "failed to reset Transceiver on port<%d>", portn)); 14084732Sdavemq status = NXGE_ERROR; 14094732Sdavemq goto fail; 14104732Sdavemq } 14114732Sdavemq 14124732Sdavemq /* Set to 0x7FBF */ 14134732Sdavemq ctl.value = 0; 14144732Sdavemq ctl.bits.res1 = 0x3F; 14154732Sdavemq ctl.bits.optxon_lvl = 1; 14164732Sdavemq ctl.bits.oprxflt_lvl = 1; 14174732Sdavemq ctl.bits.optrxlos_lvl = 1; 14184732Sdavemq ctl.bits.optxflt_lvl = 1; 14194732Sdavemq ctl.bits.opprflt_lvl = 1; 14204732Sdavemq ctl.bits.obtmpflt_lvl = 1; 14214732Sdavemq ctl.bits.opbiasflt_lvl = 1; 14224732Sdavemq ctl.bits.optxrst_lvl = 1; 14234732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 14244732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 14254732Sdavemq != NXGE_OK) 14264732Sdavemq goto fail; 14274732Sdavemq 14284732Sdavemq /* Set to 0x164 */ 14294732Sdavemq tx_ctl.value = 0; 14304732Sdavemq tx_ctl.bits.tsck_lpwren = 1; 14314732Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 14324732Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 14334732Sdavemq tx_ctl.bits.xfp_clken = 1; 14344732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 14354732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 14364732Sdavemq tx_ctl.value)) != NXGE_OK) 14374732Sdavemq goto fail; 14384732Sdavemq /* 14394732Sdavemq * According to Broadcom's instruction, SW needs to read 14404732Sdavemq * back these registers twice after written. 14414732Sdavemq */ 14424732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14434732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 14444732Sdavemq != NXGE_OK) 14454732Sdavemq goto fail; 14464732Sdavemq 14474732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14484732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 14494732Sdavemq != NXGE_OK) 14504732Sdavemq goto fail; 14514732Sdavemq 14524732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14534732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 14544732Sdavemq != NXGE_OK) 14554732Sdavemq goto fail; 14564732Sdavemq 14574732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14584732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 14594732Sdavemq != NXGE_OK) 14604732Sdavemq goto fail; 14614732Sdavemq 14624732Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 14634732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14644732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 14654732Sdavemq &op_ctr.value)) != NXGE_OK) 14664732Sdavemq goto fail; 14674732Sdavemq op_ctr.bits.gpio_sel = 0x3; 14684732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 14694732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 14704732Sdavemq op_ctr.value)) != NXGE_OK) 14714732Sdavemq goto fail; 14724732Sdavemq 14734732Sdavemq NXGE_DELAY(1000000); 14744732Sdavemq 14754732Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 14764732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 14774732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 14784732Sdavemq != NXGE_OK) 14794732Sdavemq goto fail; 14804732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 14814732Sdavemq pcs_ctl.bits.loopback = 1; 14824732Sdavemq else 14834732Sdavemq pcs_ctl.bits.loopback = 0; 14844732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 14854732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 14864732Sdavemq != NXGE_OK) 14874732Sdavemq goto fail; 14884732Sdavemq 14894732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 14904732Sdavemq if (status != NXGE_OK) 14914732Sdavemq goto fail; 14924732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 14934732Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 14944732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 14954732Sdavemq if (status != NXGE_OK) 14964732Sdavemq goto fail; 14974732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 14984732Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 14994732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 15004732Sdavemq if (status != NXGE_OK) 15014732Sdavemq goto fail; 15024732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15034732Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 15044732Sdavemq 15054732Sdavemq #ifdef NXGE_DEBUG 15064732Sdavemq /* Diagnose link issue if link is not up */ 15074732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 15084732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 15094732Sdavemq &val); 15104732Sdavemq if (status != NXGE_OK) 15114732Sdavemq goto fail; 15124732Sdavemq 15134732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 15144732Sdavemq BCM8704_USER_DEV3_ADDR, 15154732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 15164732Sdavemq &val); 15174732Sdavemq if (status != NXGE_OK) 15184732Sdavemq goto fail; 15194732Sdavemq 15204732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 15214732Sdavemq BCM8704_USER_DEV3_ADDR, 15224732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 15234732Sdavemq &val1); 15244732Sdavemq if (status != NXGE_OK) 15254732Sdavemq goto fail; 15264732Sdavemq 15274732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 15284732Sdavemq BCM8704_USER_DEV3_ADDR, 15294732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 15304732Sdavemq &val1); 15314732Sdavemq if (status != NXGE_OK) 15324732Sdavemq goto fail; 15334732Sdavemq 15344732Sdavemq if (val != 0x3FC) { 15354732Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 15364732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15374732Sdavemq "Cable not connected to peer or bad" 15384732Sdavemq " cable on port<%d>\n", portn)); 15394732Sdavemq } else if (val == 0x639C) { 15404732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15414732Sdavemq "Optical module (XFP) is bad or absent" 15424732Sdavemq " on port<%d>\n", portn)); 15434732Sdavemq } 15444732Sdavemq } 15454732Sdavemq #endif 15464732Sdavemq 15474977Sraghus done: 15484732Sdavemq statsp->mac_stats.cap_10gfdx = 1; 15494732Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 15504732Sdavemq 15514732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 15524732Sdavemq portn)); 15534732Sdavemq return (NXGE_OK); 15544732Sdavemq 15554732Sdavemq fail: 15564732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15574732Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 15584732Sdavemq "port<%d>", portn)); 15594732Sdavemq return (status); 15604732Sdavemq } 15614732Sdavemq 15624732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 15634732Sdavemq 15644732Sdavemq static nxge_status_t 15654732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 15664732Sdavemq { 15674732Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 15684732Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 15694732Sdavemq nxge_status_t status = NXGE_OK; 15704732Sdavemq 15714977Sraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 15724977Sraghus statsp->mac_stats.cap_1000fdx = 15734977Sraghus param_arr[param_anar_1000fdx].value; 15744977Sraghus goto done; 15754977Sraghus } 15764977Sraghus 15774732Sdavemq /* Set Clause 22 */ 15784732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 15794732Sdavemq 15804732Sdavemq /* Set capability flags */ 15814732Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 15824977Sraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 15834977Sraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 15844977Sraghus statsp->mac_stats.cap_100fdx = 15854977Sraghus param_arr[param_anar_100fdx].value; 15864977Sraghus statsp->mac_stats.cap_10fdx = 15874977Sraghus param_arr[param_anar_10fdx].value; 15884977Sraghus } 15894732Sdavemq 15904732Sdavemq status = nxge_mii_xcvr_init(nxgep); 15914977Sraghus done: 15924732Sdavemq return (status); 15934732Sdavemq } 15944732Sdavemq 15954732Sdavemq /* Initialize transceiver */ 15964732Sdavemq 15974732Sdavemq nxge_status_t 15984732Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 15994732Sdavemq { 16004732Sdavemq p_nxge_stats_t statsp; 16014732Sdavemq #ifdef NXGE_DEBUG 16024732Sdavemq uint8_t portn; 16034732Sdavemq #endif 16044732Sdavemq 16054732Sdavemq nxge_status_t status = NXGE_OK; 16064732Sdavemq #ifdef NXGE_DEBUG 16074732Sdavemq portn = nxgep->mac.portnum; 16084732Sdavemq #endif 16093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 16103859Sml29623 statsp = nxgep->statsp; 16113859Sml29623 16123859Sml29623 /* 16133859Sml29623 * Initialize the xcvr statistics. 16143859Sml29623 */ 16153859Sml29623 statsp->mac_stats.cap_autoneg = 0; 16163859Sml29623 statsp->mac_stats.cap_100T4 = 0; 16173859Sml29623 statsp->mac_stats.cap_100fdx = 0; 16183859Sml29623 statsp->mac_stats.cap_100hdx = 0; 16193859Sml29623 statsp->mac_stats.cap_10fdx = 0; 16203859Sml29623 statsp->mac_stats.cap_10hdx = 0; 16213859Sml29623 statsp->mac_stats.cap_asmpause = 0; 16223859Sml29623 statsp->mac_stats.cap_pause = 0; 16233859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 16243859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 16253859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 16263859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 16273859Sml29623 16283859Sml29623 /* 16293859Sml29623 * Initialize the link statistics. 16303859Sml29623 */ 16313859Sml29623 statsp->mac_stats.link_T4 = 0; 16323859Sml29623 statsp->mac_stats.link_asmpause = 0; 16333859Sml29623 statsp->mac_stats.link_pause = 0; 16343859Sml29623 16354732Sdavemq if (nxgep->xcvr.xcvr_init) { 16364732Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 16373859Sml29623 if (status != NXGE_OK) 16383859Sml29623 goto fail; 16394732Sdavemq statsp->mac_stats.xcvr_inits++; 16403859Sml29623 } 16413859Sml29623 16424732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 16434732Sdavemq portn)); 16443859Sml29623 return (NXGE_OK); 16453859Sml29623 16463859Sml29623 fail: 16473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16484732Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 16494732Sdavemq portn)); 16503859Sml29623 return (status); 16513859Sml29623 } 16523859Sml29623 16534977Sraghus /* Look for transceiver type */ 16544977Sraghus 16554977Sraghus nxge_status_t 16564977Sraghus nxge_xcvr_find(p_nxge_t nxgep) 16574977Sraghus { 16584977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16594977Sraghus "==> nxge_xcvr_find: port<%d>", nxgep->mac.portnum)); 16604977Sraghus 16614977Sraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 16624977Sraghus return (NXGE_ERROR); 16634977Sraghus 16644977Sraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 16654977Sraghus return (NXGE_ERROR); 16664977Sraghus 16674977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 16684977Sraghus nxgep->statsp->mac_stats.xcvr_inuse)); 16694977Sraghus 16704977Sraghus return (NXGE_OK); 16714977Sraghus } 16723859Sml29623 16733859Sml29623 /* Initialize the TxMAC sub-block */ 16743859Sml29623 16753859Sml29623 nxge_status_t 16763859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 16773859Sml29623 { 16783859Sml29623 npi_attr_t ap; 16793859Sml29623 uint8_t portn; 16803859Sml29623 nxge_port_mode_t portmode; 16813859Sml29623 nxge_port_t portt; 16823859Sml29623 npi_handle_t handle; 16833859Sml29623 npi_status_t rs = NPI_SUCCESS; 16843859Sml29623 16853859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 16863859Sml29623 portt = nxgep->mac.porttype; 16873859Sml29623 handle = nxgep->npi_handle; 16883859Sml29623 portmode = nxgep->mac.portmode; 16893859Sml29623 16903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 16913859Sml29623 portn)); 16923859Sml29623 16933859Sml29623 /* Set Max and Min Frame Size */ 16943859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 16953859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 16963859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 16973859Sml29623 } else { 16983859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 16993859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 17003859Sml29623 } 17013859Sml29623 17023859Sml29623 if (rs != NPI_SUCCESS) 17033859Sml29623 goto fail; 17043859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || 17053859Sml29623 nxgep->mac.is_jumbo == B_TRUE) 17063859Sml29623 nxgep->mac.maxframesize = 0x2400; 17073859Sml29623 else 17083859Sml29623 nxgep->mac.maxframesize = 0x5EE + 4; 17093859Sml29623 nxgep->mac.minframesize = 64; 17103859Sml29623 17113859Sml29623 if (portt == PORT_TYPE_XMAC) { 17123859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 17133859Sml29623 0)) != NPI_SUCCESS) 17143859Sml29623 goto fail; 17153859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 17163859Sml29623 if ((portmode == PORT_10G_FIBER) || 17174977Sraghus (portmode == PORT_10G_COPPER) || 17184977Sraghus (portmode == PORT_10G_SERDES)) { 17193859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 17203859Sml29623 XGMII_IPG_12_15, rs); 17213859Sml29623 if (rs != NPI_SUCCESS) 17223859Sml29623 goto fail; 17233859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 17243859Sml29623 } else { 17253859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 17263859Sml29623 MII_GMII_IPG_12, rs); 17273859Sml29623 if (rs != NPI_SUCCESS) 17283859Sml29623 goto fail; 17293859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 17303859Sml29623 } 17313859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 17323859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 17333859Sml29623 goto fail; 17343859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 17353859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 17363859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 17373859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 17383859Sml29623 17393859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 17403859Sml29623 != NPI_SUCCESS) 17413859Sml29623 goto fail; 17423859Sml29623 17433859Sml29623 } else { 17443859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 17453859Sml29623 0)) != NPI_SUCCESS) 17463859Sml29623 goto fail; 17473859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 17483859Sml29623 17493859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 17503859Sml29623 rs); 17513859Sml29623 if (rs != NPI_SUCCESS) 17523859Sml29623 goto fail; 17533859Sml29623 nxgep->mac.ctrltype = 0x8808; 17543859Sml29623 17553859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 17563859Sml29623 if (rs != NPI_SUCCESS) 17573859Sml29623 goto fail; 17583859Sml29623 nxgep->mac.pa_size = 0x7; 17593859Sml29623 17603859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 17613859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 17623859Sml29623 goto fail; 17633859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 17643859Sml29623 } 17653859Sml29623 17663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 17673859Sml29623 portn)); 17683859Sml29623 17693859Sml29623 return (NXGE_OK); 17703859Sml29623 fail: 17713859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17723859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 17733859Sml29623 portn)); 17743859Sml29623 17753859Sml29623 return (NXGE_ERROR | rs); 17763859Sml29623 } 17773859Sml29623 17783859Sml29623 /* Initialize the RxMAC sub-block */ 17793859Sml29623 17803859Sml29623 nxge_status_t 17813859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 17823859Sml29623 { 17833859Sml29623 npi_attr_t ap; 17843859Sml29623 uint32_t i; 17853859Sml29623 uint16_t hashtab_e; 17863859Sml29623 p_hash_filter_t hash_filter; 17873859Sml29623 nxge_port_t portt; 17883859Sml29623 uint8_t portn; 17893859Sml29623 npi_handle_t handle; 17903859Sml29623 npi_status_t rs = NPI_SUCCESS; 17913859Sml29623 uint16_t *addr16p; 17923859Sml29623 uint16_t addr0, addr1, addr2; 17933859Sml29623 xmac_rx_config_t xconfig; 17943859Sml29623 bmac_rx_config_t bconfig; 17953859Sml29623 17963859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 17973859Sml29623 17983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 17993859Sml29623 portn)); 18003859Sml29623 handle = nxgep->npi_handle; 18013859Sml29623 portt = nxgep->mac.porttype; 18023859Sml29623 18033859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 18043859Sml29623 addr0 = ntohs(addr16p[2]); 18053859Sml29623 addr1 = ntohs(addr16p[1]); 18063859Sml29623 addr2 = ntohs(addr16p[0]); 18073859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 18083859Sml29623 rs); 18093859Sml29623 18103859Sml29623 if (rs != NPI_SUCCESS) 18113859Sml29623 goto fail; 18123859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 18133859Sml29623 if (rs != NPI_SUCCESS) 18143859Sml29623 goto fail; 18153859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 18163859Sml29623 if (rs != NPI_SUCCESS) 18173859Sml29623 goto fail; 18183859Sml29623 18193859Sml29623 /* 18203859Sml29623 * Load the multicast hash filter bits. 18213859Sml29623 */ 18223859Sml29623 hash_filter = nxgep->hash_filter; 18233859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 18243859Sml29623 if (hash_filter != NULL) { 18253859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 18263859Sml29623 (NMCFILTER_REGS - 1) - i]; 18273859Sml29623 } else { 18283859Sml29623 hashtab_e = 0; 18293859Sml29623 } 18303859Sml29623 18313859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 18323859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 18333859Sml29623 goto fail; 18343859Sml29623 } 18353859Sml29623 18363859Sml29623 if (portt == PORT_TYPE_XMAC) { 18373859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 18383859Sml29623 0)) != NPI_SUCCESS) 18393859Sml29623 goto fail; 18403859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 18413859Sml29623 18423859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 18433859Sml29623 18443859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 18453859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 18463859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 18473859Sml29623 18483859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 18493859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 18503859Sml29623 18513859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 18523859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 18533859Sml29623 18543859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 18553859Sml29623 18563859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 18573859Sml29623 xconfig)) != NPI_SUCCESS) 18583859Sml29623 goto fail; 18593859Sml29623 nxgep->mac.rx_config = xconfig; 18603859Sml29623 18613859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 18623859Sml29623 18633859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 18643859Sml29623 != NPI_SUCCESS) 18653859Sml29623 goto fail; 18663859Sml29623 } else { 18673859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 18683859Sml29623 18693859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 18703859Sml29623 0) != NPI_SUCCESS) 18713859Sml29623 goto fail; 18723859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 18733859Sml29623 18743859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 18753859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 18763859Sml29623 18773859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 18783859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 18793859Sml29623 18803859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 18813859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 18823859Sml29623 18833859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 18843859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 18853859Sml29623 bconfig)) != NPI_SUCCESS) 18863859Sml29623 goto fail; 18873859Sml29623 nxgep->mac.rx_config = bconfig; 18883859Sml29623 18893859Sml29623 /* Always enable comparison of mac unique address */ 18903859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 18913859Sml29623 != NPI_SUCCESS) 18923859Sml29623 goto fail; 18933859Sml29623 } 18943859Sml29623 18953859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 18963859Sml29623 portn)); 18973859Sml29623 18983859Sml29623 return (NXGE_OK); 18993859Sml29623 19003859Sml29623 fail: 19013859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19023859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 19033859Sml29623 portn)); 19043859Sml29623 19053859Sml29623 return (NXGE_ERROR | rs); 19063859Sml29623 } 19073859Sml29623 19083859Sml29623 /* Enable TXMAC */ 19093859Sml29623 19103859Sml29623 nxge_status_t 19113859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 19123859Sml29623 { 19133859Sml29623 npi_handle_t handle; 19143859Sml29623 npi_status_t rs = NPI_SUCCESS; 19153859Sml29623 nxge_status_t status = NXGE_OK; 19163859Sml29623 19173859Sml29623 handle = nxgep->npi_handle; 19183859Sml29623 19193859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 19203859Sml29623 nxgep->mac.portnum)); 19213859Sml29623 19223859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 19233859Sml29623 goto fail; 19243859Sml29623 19253859Sml29623 /* based on speed */ 19263859Sml29623 nxgep->msg_min = ETHERMIN; 19273859Sml29623 19283859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 19293859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 19303859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 19313859Sml29623 goto fail; 19323859Sml29623 } else { 19333859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 19343859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 19353859Sml29623 goto fail; 19363859Sml29623 } 19373859Sml29623 19383859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 19393859Sml29623 nxgep->mac.portnum)); 19403859Sml29623 19413859Sml29623 return (NXGE_OK); 19423859Sml29623 fail: 19433859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19443859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 19453859Sml29623 nxgep->mac.portnum)); 19463859Sml29623 if (rs != NPI_SUCCESS) 19473859Sml29623 return (NXGE_ERROR | rs); 19483859Sml29623 else 19493859Sml29623 return (status); 19503859Sml29623 } 19513859Sml29623 19523859Sml29623 /* Disable TXMAC */ 19533859Sml29623 19543859Sml29623 nxge_status_t 19553859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 19563859Sml29623 { 19573859Sml29623 npi_handle_t handle; 19583859Sml29623 npi_status_t rs = NPI_SUCCESS; 19593859Sml29623 19603859Sml29623 handle = nxgep->npi_handle; 19613859Sml29623 19623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 19633859Sml29623 nxgep->mac.portnum)); 19643859Sml29623 19653859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 19663859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 19673859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 19683859Sml29623 goto fail; 19693859Sml29623 } else { 19703859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 19713859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 19723859Sml29623 goto fail; 19733859Sml29623 } 19743859Sml29623 19753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 19763859Sml29623 nxgep->mac.portnum)); 19773859Sml29623 return (NXGE_OK); 19783859Sml29623 fail: 19793859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 19803859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 19813859Sml29623 nxgep->mac.portnum)); 19823859Sml29623 return (NXGE_ERROR | rs); 19833859Sml29623 } 19843859Sml29623 19853859Sml29623 /* Enable RXMAC */ 19863859Sml29623 19873859Sml29623 nxge_status_t 19883859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 19893859Sml29623 { 19903859Sml29623 npi_handle_t handle; 19913859Sml29623 uint8_t portn; 19923859Sml29623 npi_status_t rs = NPI_SUCCESS; 19933859Sml29623 nxge_status_t status = NXGE_OK; 19943859Sml29623 19953859Sml29623 handle = nxgep->npi_handle; 19963859Sml29623 portn = nxgep->mac.portnum; 19973859Sml29623 19983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 19993859Sml29623 portn)); 20003859Sml29623 20013859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 20023859Sml29623 goto fail; 20033859Sml29623 20043859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 20053859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 20063859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 20073859Sml29623 goto fail; 20083859Sml29623 } else { 20093859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 20103859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 20113859Sml29623 goto fail; 20123859Sml29623 } 20133859Sml29623 20143859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 20153859Sml29623 portn)); 20163859Sml29623 20173859Sml29623 return (NXGE_OK); 20183859Sml29623 fail: 20193859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20203859Sml29623 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 20213859Sml29623 portn)); 20223859Sml29623 20233859Sml29623 if (rs != NPI_SUCCESS) 20243859Sml29623 return (NXGE_ERROR | rs); 20253859Sml29623 else 20263859Sml29623 return (status); 20273859Sml29623 } 20283859Sml29623 20293859Sml29623 /* Disable RXMAC */ 20303859Sml29623 20313859Sml29623 nxge_status_t 20323859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 20333859Sml29623 { 20343859Sml29623 npi_handle_t handle; 20353859Sml29623 uint8_t portn; 20363859Sml29623 npi_status_t rs = NPI_SUCCESS; 20373859Sml29623 20383859Sml29623 handle = nxgep->npi_handle; 20393859Sml29623 portn = nxgep->mac.portnum; 20403859Sml29623 20413859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 20423859Sml29623 portn)); 20433859Sml29623 20443859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 20453859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 20463859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 20473859Sml29623 goto fail; 20483859Sml29623 } else { 20493859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 20503859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 20513859Sml29623 goto fail; 20523859Sml29623 } 20533859Sml29623 20543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 20553859Sml29623 portn)); 20563859Sml29623 return (NXGE_OK); 20573859Sml29623 fail: 20583859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20593859Sml29623 "nxgep_rx_mac_disable: ", 20603859Sml29623 "Failed to disable port<%d> RxMAC", 20613859Sml29623 portn)); 20623859Sml29623 20633859Sml29623 return (NXGE_ERROR | rs); 20643859Sml29623 } 20653859Sml29623 20663859Sml29623 /* Reset TXMAC */ 20673859Sml29623 20683859Sml29623 nxge_status_t 20693859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 20703859Sml29623 { 20713859Sml29623 npi_handle_t handle; 20723859Sml29623 uint8_t portn; 20733859Sml29623 npi_status_t rs = NPI_SUCCESS; 20743859Sml29623 20753859Sml29623 handle = nxgep->npi_handle; 20763859Sml29623 portn = nxgep->mac.portnum; 20773859Sml29623 20783859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 20793859Sml29623 portn)); 20803859Sml29623 20813859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 20823859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 20833859Sml29623 != NPI_SUCCESS) 20843859Sml29623 goto fail; 20853859Sml29623 } else { 20863859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 20873859Sml29623 != NPI_SUCCESS) 20883859Sml29623 goto fail; 20893859Sml29623 } 20903859Sml29623 20913859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 20923859Sml29623 portn)); 20933859Sml29623 20943859Sml29623 return (NXGE_OK); 20953859Sml29623 fail: 20963859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20973859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 20983859Sml29623 portn)); 20993859Sml29623 21003859Sml29623 return (NXGE_ERROR | rs); 21013859Sml29623 } 21023859Sml29623 21033859Sml29623 /* Reset RXMAC */ 21043859Sml29623 21053859Sml29623 nxge_status_t 21063859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 21073859Sml29623 { 21083859Sml29623 npi_handle_t handle; 21093859Sml29623 uint8_t portn; 21103859Sml29623 npi_status_t rs = NPI_SUCCESS; 21113859Sml29623 21123859Sml29623 handle = nxgep->npi_handle; 21133859Sml29623 portn = nxgep->mac.portnum; 21143859Sml29623 21153859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 21163859Sml29623 portn)); 21173859Sml29623 21183859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 21193859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 21203859Sml29623 != NPI_SUCCESS) 21213859Sml29623 goto fail; 21223859Sml29623 } else { 21233859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 21243859Sml29623 != NPI_SUCCESS) 21253859Sml29623 goto fail; 21263859Sml29623 } 21273859Sml29623 21283859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 21293859Sml29623 portn)); 21303859Sml29623 21313859Sml29623 return (NXGE_OK); 21323859Sml29623 fail: 21333859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21343859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 21353859Sml29623 portn)); 21363859Sml29623 return (NXGE_ERROR | rs); 21373859Sml29623 } 21383859Sml29623 21394732Sdavemq /* 10G fiber link interrupt start routine */ 21404732Sdavemq 21414732Sdavemq static nxge_status_t 21424732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 21434732Sdavemq { 21444732Sdavemq npi_status_t rs = NPI_SUCCESS; 21454732Sdavemq uint8_t portn = nxgep->mac.portnum; 21464732Sdavemq 21474732Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 21484732Sdavemq 21494732Sdavemq if (rs != NPI_SUCCESS) 21504732Sdavemq return (NXGE_ERROR | rs); 21514732Sdavemq else 21524732Sdavemq return (NXGE_OK); 21534732Sdavemq } 21544732Sdavemq 21554732Sdavemq /* 10G fiber link interrupt stop routine */ 21564732Sdavemq 21574732Sdavemq static nxge_status_t 21584732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 21594732Sdavemq { 21604732Sdavemq npi_status_t rs = NPI_SUCCESS; 21614732Sdavemq uint8_t portn = nxgep->mac.portnum; 21624732Sdavemq 21634732Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 21644732Sdavemq 21654732Sdavemq if (rs != NPI_SUCCESS) 21664732Sdavemq return (NXGE_ERROR | rs); 21674732Sdavemq else 21684732Sdavemq return (NXGE_OK); 21694732Sdavemq } 21704732Sdavemq 21714732Sdavemq /* 1G fiber link interrupt start routine */ 21724732Sdavemq 21734732Sdavemq static nxge_status_t 21744732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 21754732Sdavemq { 21764732Sdavemq npi_status_t rs = NPI_SUCCESS; 21774732Sdavemq uint8_t portn = nxgep->mac.portnum; 21784732Sdavemq 21794732Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 21804732Sdavemq if (rs != NPI_SUCCESS) 21814732Sdavemq return (NXGE_ERROR | rs); 21824732Sdavemq else 21834732Sdavemq return (NXGE_OK); 21844732Sdavemq } 21854732Sdavemq 21864732Sdavemq /* 1G fiber link interrupt stop routine */ 21874732Sdavemq 21884732Sdavemq static nxge_status_t 21894732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 21904732Sdavemq { 21914732Sdavemq npi_status_t rs = NPI_SUCCESS; 21924732Sdavemq uint8_t portn = nxgep->mac.portnum; 21934732Sdavemq 21944732Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 21954732Sdavemq 21964732Sdavemq if (rs != NPI_SUCCESS) 21974732Sdavemq return (NXGE_ERROR | rs); 21984732Sdavemq else 21994732Sdavemq return (NXGE_OK); 22004732Sdavemq } 22014732Sdavemq 22024732Sdavemq /* 1G copper link interrupt start routine */ 22034732Sdavemq 22044732Sdavemq static nxge_status_t 22054732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 22064732Sdavemq { 22074732Sdavemq npi_status_t rs = NPI_SUCCESS; 22084732Sdavemq uint8_t portn = nxgep->mac.portnum; 22094732Sdavemq 22104732Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 22114732Sdavemq MII_BMSR, BMSR_LSTATUS); 22124732Sdavemq 22134732Sdavemq if (rs != NPI_SUCCESS) 22144732Sdavemq return (NXGE_ERROR | rs); 22154732Sdavemq else 22164732Sdavemq return (NXGE_OK); 22174732Sdavemq } 22184732Sdavemq 22194732Sdavemq /* 1G copper link interrupt stop routine */ 22204732Sdavemq 22214732Sdavemq static nxge_status_t 22224732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 22234732Sdavemq { 22244732Sdavemq npi_status_t rs = NPI_SUCCESS; 22254732Sdavemq uint8_t portn = nxgep->mac.portnum; 22264732Sdavemq 22274732Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 22284732Sdavemq 22294732Sdavemq if (rs != NPI_SUCCESS) 22304732Sdavemq return (NXGE_ERROR | rs); 22314732Sdavemq else 22324732Sdavemq return (NXGE_OK); 22334732Sdavemq } 22344732Sdavemq 22354732Sdavemq /* Enable/Disable Link Status change interrupt */ 22363859Sml29623 22373859Sml29623 nxge_status_t 22383859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 22393859Sml29623 { 22404732Sdavemq uint8_t portn; 22414732Sdavemq nxge_status_t status = NXGE_OK; 22423859Sml29623 22433859Sml29623 portn = nxgep->mac.portnum; 22443859Sml29623 22453859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 22464732Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 22474732Sdavemq return (NXGE_OK); 22484732Sdavemq 22494732Sdavemq if (enable == LINK_INTR_START) 22504732Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 22514732Sdavemq else if (enable == LINK_INTR_STOP) 22524732Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 22534732Sdavemq if (status != NXGE_OK) 22544732Sdavemq goto fail; 22553859Sml29623 22563859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 22573859Sml29623 22583859Sml29623 return (NXGE_OK); 22593859Sml29623 fail: 22603859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22613859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 22623859Sml29623 portn)); 22633859Sml29623 22644732Sdavemq return (status); 22653859Sml29623 } 22663859Sml29623 22673859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 22683859Sml29623 22693859Sml29623 nxge_status_t 22703859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 22713859Sml29623 { 22723859Sml29623 p_nxge_param_t param_arr; 22733859Sml29623 p_nxge_stats_t statsp; 22743859Sml29623 uint8_t xcvr_portn; 22753859Sml29623 p_mii_regs_t mii_regs; 22763859Sml29623 mii_bmcr_t bmcr; 22773859Sml29623 mii_bmsr_t bmsr; 22783859Sml29623 mii_anar_t anar; 22793859Sml29623 mii_gcr_t gcr; 22803859Sml29623 mii_esr_t esr; 22813859Sml29623 mii_aux_ctl_t bcm5464r_aux; 22823859Sml29623 int status = NXGE_OK; 22833859Sml29623 22843859Sml29623 uint_t delay; 22853859Sml29623 22863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 22873859Sml29623 22883859Sml29623 param_arr = nxgep->param_arr; 22893859Sml29623 statsp = nxgep->statsp; 22903859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 22913859Sml29623 22923859Sml29623 mii_regs = NULL; 22933859Sml29623 22943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 22953859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 22963859Sml29623 22973859Sml29623 /* 22983859Sml29623 * Reset the transceiver. 22993859Sml29623 */ 23003859Sml29623 delay = 0; 23013859Sml29623 bmcr.value = 0; 23023859Sml29623 bmcr.bits.reset = 1; 23033859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2304*5125Sjoycey #if defined(__i386) 2305*5125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2306*5125Sjoycey #else 23073859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2308*5125Sjoycey #endif 23093859Sml29623 goto fail; 23103859Sml29623 do { 23113859Sml29623 drv_usecwait(500); 23123859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2313*5125Sjoycey #if defined(__i386) 2314*5125Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 2315*5125Sjoycey #else 23163859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 2317*5125Sjoycey #endif 23183859Sml29623 != NXGE_OK) 23193859Sml29623 goto fail; 23203859Sml29623 delay++; 23213859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 23223859Sml29623 if (delay == 1000) { 23233859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 23243859Sml29623 goto fail; 23253859Sml29623 } 23263859Sml29623 23273859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2328*5125Sjoycey #if defined(__i386) 2329*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 2330*5125Sjoycey #else 23313859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 2332*5125Sjoycey #endif 23333859Sml29623 &bmsr.value)) != NXGE_OK) 23343859Sml29623 goto fail; 23353859Sml29623 23363859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 23373859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 23383859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 23393859Sml29623 param_arr[param_anar_100hdx].value = 0; 23403859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 23413859Sml29623 param_arr[param_anar_10hdx].value = 0; 23423859Sml29623 23433859Sml29623 /* 23443859Sml29623 * Initialize the xcvr statistics. 23453859Sml29623 */ 23463859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 23473859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 23483859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 23493859Sml29623 statsp->mac_stats.cap_100hdx = 0; 23503859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 23513859Sml29623 statsp->mac_stats.cap_10hdx = 0; 23523859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 23533859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 23543859Sml29623 23553859Sml29623 /* 23563859Sml29623 * Initialise the xcvr advertised capability statistics. 23573859Sml29623 */ 23583859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 23593859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 23603859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 23613859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 23623859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 23633859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 23643859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 23653859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 23663859Sml29623 statsp->mac_stats.adv_cap_asmpause = 23673859Sml29623 param_arr[param_anar_asmpause].value; 23683859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 23693859Sml29623 23703859Sml29623 23713859Sml29623 /* 23723859Sml29623 * Check for extended status just in case we're 23733859Sml29623 * running a Gigibit phy. 23743859Sml29623 */ 23753859Sml29623 if (bmsr.bits.extend_status) { 23763859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2377*5125Sjoycey #if defined(__i386) 2378*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 2379*5125Sjoycey #else 23803859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 2381*5125Sjoycey #endif 23823859Sml29623 != NXGE_OK) 23833859Sml29623 goto fail; 23843859Sml29623 param_arr[param_anar_1000fdx].value &= 23853859Sml29623 esr.bits.link_1000fdx; 23863859Sml29623 param_arr[param_anar_1000hdx].value = 0; 23873859Sml29623 23883859Sml29623 statsp->mac_stats.cap_1000fdx = 23893859Sml29623 (esr.bits.link_1000Xfdx || 23903859Sml29623 esr.bits.link_1000fdx); 23913859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 23923859Sml29623 } else { 23933859Sml29623 param_arr[param_anar_1000fdx].value = 0; 23943859Sml29623 param_arr[param_anar_1000hdx].value = 0; 23953859Sml29623 } 23963859Sml29623 23973859Sml29623 /* 23983859Sml29623 * Initialize 1G Statistics once the capability is established. 23993859Sml29623 */ 24003859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 24013859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 24023859Sml29623 24033859Sml29623 /* 24043859Sml29623 * Initialise the link statistics. 24053859Sml29623 */ 24063859Sml29623 statsp->mac_stats.link_T4 = 0; 24073859Sml29623 statsp->mac_stats.link_asmpause = 0; 24083859Sml29623 statsp->mac_stats.link_pause = 0; 24093859Sml29623 statsp->mac_stats.link_speed = 0; 24103859Sml29623 statsp->mac_stats.link_duplex = 0; 24113859Sml29623 statsp->mac_stats.link_up = 0; 24123859Sml29623 24133859Sml29623 /* 24143859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 24153859Sml29623 */ 24163859Sml29623 bmcr.value = 0; 24173859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2418*5125Sjoycey #if defined(__i386) 2419*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2420*5125Sjoycey #else 24213859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2422*5125Sjoycey #endif 24233859Sml29623 goto fail; 24243859Sml29623 24253859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 24263859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 24273859Sml29623 bmcr.bits.loopback = 1; 24283859Sml29623 bmcr.bits.enable_autoneg = 0; 24293859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 24303859Sml29623 bmcr.bits.speed_1000_sel = 1; 24313859Sml29623 bmcr.bits.duplex_mode = 1; 24323859Sml29623 param_arr[param_autoneg].value = 0; 24333859Sml29623 } else { 24343859Sml29623 bmcr.bits.loopback = 0; 24353859Sml29623 } 24363859Sml29623 24373859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 24383859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 24393859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 24403859Sml29623 param_arr[param_autoneg].value = 0; 24413859Sml29623 bcm5464r_aux.value = 0; 24423859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 24433859Sml29623 bcm5464r_aux.bits.write_1 = 1; 24443859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 24453859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 24463859Sml29623 != NXGE_OK) 24473859Sml29623 goto fail; 24483859Sml29623 } 24493859Sml29623 24503859Sml29623 if (param_arr[param_autoneg].value) { 24513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 24523859Sml29623 "Restarting Auto-negotiation.")); 24533859Sml29623 /* 24543859Sml29623 * Setup our Auto-negotiation advertisement register. 24553859Sml29623 */ 24563859Sml29623 anar.value = 0; 24573859Sml29623 anar.bits.selector = 1; 24583859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 24593859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 24603859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 24613859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 24623859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 24633859Sml29623 anar.bits.cap_asmpause = 0; 24643859Sml29623 anar.bits.cap_pause = 0; 24653859Sml29623 if (param_arr[param_anar_1000fdx].value || 24663859Sml29623 param_arr[param_anar_100fdx].value || 24673859Sml29623 param_arr[param_anar_10fdx].value) { 24683859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 24693859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 24703859Sml29623 } 24713859Sml29623 24723859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2473*5125Sjoycey #if defined(__i386) 2474*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 2475*5125Sjoycey #else 24763859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 2477*5125Sjoycey #endif 24783859Sml29623 != NXGE_OK) 24793859Sml29623 goto fail; 24803859Sml29623 if (bmsr.bits.extend_status) { 24813859Sml29623 gcr.value = 0; 24823859Sml29623 gcr.bits.ms_mode_en = 24833859Sml29623 param_arr[param_master_cfg_enable].value; 24843859Sml29623 gcr.bits.master = 24853859Sml29623 param_arr[param_master_cfg_value].value; 24863859Sml29623 gcr.bits.link_1000fdx = 24873859Sml29623 param_arr[param_anar_1000fdx].value; 24883859Sml29623 gcr.bits.link_1000hdx = 24893859Sml29623 param_arr[param_anar_1000hdx].value; 24903859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2491*5125Sjoycey #if defined(__i386) 2492*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 2493*5125Sjoycey #else 24943859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 2495*5125Sjoycey #endif 24963859Sml29623 != NXGE_OK) 24973859Sml29623 goto fail; 24983859Sml29623 } 24993859Sml29623 25003859Sml29623 bmcr.bits.enable_autoneg = 1; 25013859Sml29623 bmcr.bits.restart_autoneg = 1; 25023859Sml29623 25033859Sml29623 } else { 25043859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 25053859Sml29623 bmcr.bits.speed_1000_sel = 25063859Sml29623 param_arr[param_anar_1000fdx].value | 25073859Sml29623 param_arr[param_anar_1000hdx].value; 25083859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 25093859Sml29623 (param_arr[param_anar_100fdx].value | 25103859Sml29623 param_arr[param_anar_100hdx].value); 25113859Sml29623 if (bmcr.bits.speed_1000_sel) { 25123859Sml29623 statsp->mac_stats.link_speed = 1000; 25133859Sml29623 gcr.value = 0; 25143859Sml29623 gcr.bits.ms_mode_en = 25153859Sml29623 param_arr[param_master_cfg_enable].value; 25163859Sml29623 gcr.bits.master = 25173859Sml29623 param_arr[param_master_cfg_value].value; 25183859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2519*5125Sjoycey #if defined(__i386) 2520*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 2521*5125Sjoycey #else 25223859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 2523*5125Sjoycey #endif 25243859Sml29623 gcr.value)) 25253859Sml29623 != NXGE_OK) 25263859Sml29623 goto fail; 25273859Sml29623 if (param_arr[param_anar_1000fdx].value) { 25283859Sml29623 bmcr.bits.duplex_mode = 1; 25293859Sml29623 statsp->mac_stats.link_duplex = 2; 25303859Sml29623 } else 25313859Sml29623 statsp->mac_stats.link_duplex = 1; 25323859Sml29623 } else if (bmcr.bits.speed_sel) { 25333859Sml29623 statsp->mac_stats.link_speed = 100; 25343859Sml29623 if (param_arr[param_anar_100fdx].value) { 25353859Sml29623 bmcr.bits.duplex_mode = 1; 25363859Sml29623 statsp->mac_stats.link_duplex = 2; 25373859Sml29623 } else 25383859Sml29623 statsp->mac_stats.link_duplex = 1; 25393859Sml29623 } else { 25403859Sml29623 statsp->mac_stats.link_speed = 10; 25413859Sml29623 if (param_arr[param_anar_10fdx].value) { 25423859Sml29623 bmcr.bits.duplex_mode = 1; 25433859Sml29623 statsp->mac_stats.link_duplex = 2; 25443859Sml29623 } else 25453859Sml29623 statsp->mac_stats.link_duplex = 1; 25463859Sml29623 } 25473859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 25483859Sml29623 statsp->mac_stats.link_asmpause = 25493859Sml29623 statsp->mac_stats.cap_asmpause; 25503859Sml29623 statsp->mac_stats.link_pause = 25513859Sml29623 statsp->mac_stats.cap_pause; 25523859Sml29623 } 25533859Sml29623 25543859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 25553859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 25563859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 25573859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 25583859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 25593859Sml29623 gcr.value = 0; 25603859Sml29623 gcr.bits.ms_mode_en = 1; 25613859Sml29623 gcr.bits.master = 1; 25623859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2563*5125Sjoycey #if defined(__i386) 2564*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 2565*5125Sjoycey #else 25663859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 2567*5125Sjoycey #endif 25683859Sml29623 gcr.value)) 25693859Sml29623 != NXGE_OK) 25703859Sml29623 goto fail; 25713859Sml29623 bmcr.value = 0; 25723859Sml29623 bmcr.bits.speed_1000_sel = 1; 25733859Sml29623 statsp->mac_stats.link_speed = 1000; 25743859Sml29623 } else if (statsp->port_stats.lb_mode 25753859Sml29623 == nxge_lb_ext100) { 25763859Sml29623 /* BCM5464R 100mbps external loopback mode */ 25773859Sml29623 bmcr.value = 0; 25783859Sml29623 bmcr.bits.speed_sel = 1; 25793859Sml29623 bmcr.bits.duplex_mode = 1; 25803859Sml29623 statsp->mac_stats.link_speed = 100; 25813859Sml29623 } else if (statsp->port_stats.lb_mode 25823859Sml29623 == nxge_lb_ext10) { 25833859Sml29623 /* BCM5464R 10mbps external loopback mode */ 25843859Sml29623 bmcr.value = 0; 25853859Sml29623 bmcr.bits.duplex_mode = 1; 25863859Sml29623 statsp->mac_stats.link_speed = 10; 25873859Sml29623 } 25883859Sml29623 } 25893859Sml29623 } 25903859Sml29623 25913859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2592*5125Sjoycey #if defined(__i386) 2593*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 2594*5125Sjoycey #else 25953859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 2596*5125Sjoycey #endif 25973859Sml29623 bmcr.value)) != NXGE_OK) 25983859Sml29623 goto fail; 25993859Sml29623 26003859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2601*5125Sjoycey #if defined(__i386) 2602*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 2603*5125Sjoycey #else 26043859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 2605*5125Sjoycey #endif 26063859Sml29623 goto fail; 26073859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 26083859Sml29623 26093859Sml29623 /* 26103859Sml29623 * Initialize the xcvr status kept in the context structure. 26113859Sml29623 */ 26123859Sml29623 nxgep->soft_bmsr.value = 0; 26133859Sml29623 26143859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2615*5125Sjoycey #if defined(__i386) 2616*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 2617*5125Sjoycey #else 26183859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 2619*5125Sjoycey #endif 26203859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 26213859Sml29623 goto fail; 26223859Sml29623 26233859Sml29623 statsp->mac_stats.xcvr_inits++; 26243859Sml29623 nxgep->bmsr.value = 0; 26253859Sml29623 26263859Sml29623 fail: 26273859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 26283859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 26293859Sml29623 return (status); 26303859Sml29623 } 26313859Sml29623 26323859Sml29623 /* Read from a MII compliant register */ 26333859Sml29623 26343859Sml29623 nxge_status_t 26353859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 26363859Sml29623 uint16_t *value) 26373859Sml29623 { 26383859Sml29623 npi_status_t rs = NPI_SUCCESS; 26393859Sml29623 26403859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 26413859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 26423859Sml29623 26433859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 26443859Sml29623 26453859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 26463859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 26473859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 26483859Sml29623 goto fail; 26494977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 26504977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 26513859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 26523859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 26533859Sml29623 goto fail; 26543859Sml29623 } else 26553859Sml29623 goto fail; 26563859Sml29623 26573859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 26583859Sml29623 26593859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 26603859Sml29623 "xcvr_reg<%d> value=0x%x", 26613859Sml29623 xcvr_portn, xcvr_reg, *value)); 26623859Sml29623 return (NXGE_OK); 26633859Sml29623 fail: 26643859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 26653859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 26663859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 26673859Sml29623 xcvr_portn)); 26683859Sml29623 26693859Sml29623 return (NXGE_ERROR | rs); 26703859Sml29623 } 26713859Sml29623 26723859Sml29623 /* Write to a MII compliant Register */ 26733859Sml29623 26743859Sml29623 nxge_status_t 26753859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 26763859Sml29623 uint16_t value) 26773859Sml29623 { 26783859Sml29623 npi_status_t rs = NPI_SUCCESS; 26793859Sml29623 26803859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 26813859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 26823859Sml29623 value)); 26833859Sml29623 26843859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 26853859Sml29623 26863859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 26873859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 26883859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 26893859Sml29623 goto fail; 26904977Sraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 26914977Sraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 26923859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 26933859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 26943859Sml29623 goto fail; 26953859Sml29623 } else 26963859Sml29623 goto fail; 26973859Sml29623 26983859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 26993859Sml29623 27003859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 27013859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 27023859Sml29623 return (NXGE_OK); 27033859Sml29623 fail: 27043859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 27053859Sml29623 27063859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27073859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 27083859Sml29623 xcvr_portn)); 27093859Sml29623 27103859Sml29623 return (NXGE_ERROR | rs); 27113859Sml29623 } 27123859Sml29623 27133859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 27143859Sml29623 27153859Sml29623 nxge_status_t 27163859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 27173859Sml29623 uint16_t xcvr_reg, uint16_t *value) 27183859Sml29623 { 27193859Sml29623 npi_status_t rs = NPI_SUCCESS; 27203859Sml29623 27213859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 27223859Sml29623 xcvr_portn)); 27233859Sml29623 27243859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 27253859Sml29623 27263859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 27273859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 27283859Sml29623 goto fail; 27293859Sml29623 27303859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 27313859Sml29623 27323859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 27333859Sml29623 xcvr_portn)); 27343859Sml29623 return (NXGE_OK); 27353859Sml29623 fail: 27363859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 27373859Sml29623 27383859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27393859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 27403859Sml29623 xcvr_portn)); 27413859Sml29623 27423859Sml29623 return (NXGE_ERROR | rs); 27433859Sml29623 } 27443859Sml29623 27453859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 27463859Sml29623 27473859Sml29623 nxge_status_t 27483859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 27493859Sml29623 uint16_t xcvr_reg, uint16_t value) 27503859Sml29623 { 27513859Sml29623 npi_status_t rs = NPI_SUCCESS; 27523859Sml29623 27533859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 27543859Sml29623 xcvr_portn)); 27553859Sml29623 27563859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 27573859Sml29623 27583859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 27593859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 27603859Sml29623 goto fail; 27613859Sml29623 27623859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 27633859Sml29623 27643859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 27653859Sml29623 xcvr_portn)); 27663859Sml29623 return (NXGE_OK); 27673859Sml29623 fail: 27683859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 27693859Sml29623 27703859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27713859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 27723859Sml29623 xcvr_portn)); 27733859Sml29623 27743859Sml29623 return (NXGE_ERROR | rs); 27753859Sml29623 } 27763859Sml29623 27773859Sml29623 27783859Sml29623 /* Check MII to see if there is any link status change */ 27793859Sml29623 27803859Sml29623 nxge_status_t 27813859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 27823859Sml29623 nxge_link_state_t *link_up) 27833859Sml29623 { 27843859Sml29623 p_nxge_param_t param_arr; 27853859Sml29623 p_nxge_stats_t statsp; 27863859Sml29623 p_mii_regs_t mii_regs; 27873859Sml29623 p_mii_bmsr_t soft_bmsr; 27883859Sml29623 mii_anar_t anar; 27893859Sml29623 mii_anlpar_t anlpar; 27903859Sml29623 mii_anar_t an_common; 27913859Sml29623 mii_aner_t aner; 27923859Sml29623 mii_gsr_t gsr; 27933859Sml29623 nxge_status_t status = NXGE_OK; 27943859Sml29623 27953859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 27963859Sml29623 27973859Sml29623 mii_regs = NULL; 27983859Sml29623 param_arr = nxgep->param_arr; 27993859Sml29623 statsp = nxgep->statsp; 28003859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 28013859Sml29623 *link_up = LINK_NO_CHANGE; 28023859Sml29623 28033859Sml29623 if (bmsr_ints.bits.link_status) { 28043859Sml29623 if (bmsr.bits.link_status) { 28053859Sml29623 soft_bmsr->bits.link_status = 1; 28063859Sml29623 } else { 28073859Sml29623 statsp->mac_stats.link_up = 0; 28083859Sml29623 soft_bmsr->bits.link_status = 0; 28093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 28103859Sml29623 "Link down cable problem")); 28113859Sml29623 *link_up = LINK_IS_DOWN; 28123859Sml29623 } 28133859Sml29623 } 28143859Sml29623 28153859Sml29623 if (param_arr[param_autoneg].value) { 28163859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 28173859Sml29623 if (bmsr.bits.auto_neg_complete) 28183859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 28193859Sml29623 else 28203859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 28213859Sml29623 } 28223859Sml29623 if (soft_bmsr->bits.link_status == 0) { 28233859Sml29623 statsp->mac_stats.link_T4 = 0; 28243859Sml29623 statsp->mac_stats.link_speed = 0; 28253859Sml29623 statsp->mac_stats.link_duplex = 0; 28263859Sml29623 statsp->mac_stats.link_asmpause = 0; 28273859Sml29623 statsp->mac_stats.link_pause = 0; 28283859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 28293859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 28303859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 28313859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 28323859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 28333859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 28343859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 28353859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 28363859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 28373859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 28383859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 28393859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 28403859Sml29623 } 28413859Sml29623 } else 28423859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 28433859Sml29623 28443859Sml29623 if ((bmsr_ints.bits.link_status || 28453859Sml29623 bmsr_ints.bits.auto_neg_complete) && 28463859Sml29623 soft_bmsr->bits.link_status && 28473859Sml29623 soft_bmsr->bits.auto_neg_complete) { 28483859Sml29623 statsp->mac_stats.link_up = 1; 28493859Sml29623 if (param_arr[param_autoneg].value) { 28503859Sml29623 if ((status = nxge_mii_read(nxgep, 28513859Sml29623 statsp->mac_stats.xcvr_portn, 2852*5125Sjoycey #if defined(__i386) 2853*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 2854*5125Sjoycey #else 28553859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 2856*5125Sjoycey #endif 28573859Sml29623 &anar.value)) != NXGE_OK) 28583859Sml29623 goto fail; 28593859Sml29623 if ((status = nxge_mii_read(nxgep, 28603859Sml29623 statsp->mac_stats.xcvr_portn, 2861*5125Sjoycey #if defined(__i386) 2862*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 2863*5125Sjoycey #else 28643859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 2865*5125Sjoycey #endif 28663859Sml29623 &anlpar.value)) != NXGE_OK) 28673859Sml29623 goto fail; 28683859Sml29623 if ((status = nxge_mii_read(nxgep, 28693859Sml29623 statsp->mac_stats.xcvr_portn, 2870*5125Sjoycey #if defined(__i386) 2871*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 2872*5125Sjoycey #else 28733859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 2874*5125Sjoycey #endif 28753859Sml29623 &aner.value)) != NXGE_OK) 28763859Sml29623 goto fail; 28773859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 28783859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 28793859Sml29623 statsp->mac_stats.lp_cap_100fdx = 28803859Sml29623 anlpar.bits.cap_100fdx; 28813859Sml29623 statsp->mac_stats.lp_cap_100hdx = 28823859Sml29623 anlpar.bits.cap_100hdx; 28833859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 28843859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 28853859Sml29623 statsp->mac_stats.lp_cap_asmpause = 28863859Sml29623 anlpar.bits.cap_asmpause; 28873859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 28883859Sml29623 an_common.value = anar.value & anlpar.value; 28893859Sml29623 if (param_arr[param_anar_1000fdx].value || 28903859Sml29623 param_arr[param_anar_1000hdx].value) { 28913859Sml29623 if ((status = nxge_mii_read(nxgep, 28923859Sml29623 statsp->mac_stats.xcvr_portn, 2893*5125Sjoycey #if defined(__i386) 2894*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 2895*5125Sjoycey #else 28963859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 2897*5125Sjoycey #endif 28983859Sml29623 &gsr.value)) 28993859Sml29623 != NXGE_OK) 29003859Sml29623 goto fail; 29013859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 29023859Sml29623 gsr.bits.link_1000fdx; 29033859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 29043859Sml29623 gsr.bits.link_1000hdx; 29053859Sml29623 if (param_arr[param_anar_1000fdx].value && 29063859Sml29623 gsr.bits.link_1000fdx) { 29073859Sml29623 statsp->mac_stats.link_speed = 1000; 29083859Sml29623 statsp->mac_stats.link_duplex = 2; 29093859Sml29623 } else if ( 29103859Sml29623 param_arr[param_anar_1000hdx].value && 29113859Sml29623 gsr.bits.link_1000hdx) { 29123859Sml29623 statsp->mac_stats.link_speed = 1000; 29133859Sml29623 statsp->mac_stats.link_duplex = 1; 29143859Sml29623 } 29153859Sml29623 } 29163859Sml29623 if ((an_common.value != 0) && 29173859Sml29623 !(statsp->mac_stats.link_speed)) { 29183859Sml29623 if (an_common.bits.cap_100T4) { 29193859Sml29623 statsp->mac_stats.link_T4 = 1; 29203859Sml29623 statsp->mac_stats.link_speed = 100; 29213859Sml29623 statsp->mac_stats.link_duplex = 1; 29223859Sml29623 } else if (an_common.bits.cap_100fdx) { 29233859Sml29623 statsp->mac_stats.link_speed = 100; 29243859Sml29623 statsp->mac_stats.link_duplex = 2; 29253859Sml29623 } else if (an_common.bits.cap_100hdx) { 29263859Sml29623 statsp->mac_stats.link_speed = 100; 29273859Sml29623 statsp->mac_stats.link_duplex = 1; 29283859Sml29623 } else if (an_common.bits.cap_10fdx) { 29293859Sml29623 statsp->mac_stats.link_speed = 10; 29303859Sml29623 statsp->mac_stats.link_duplex = 2; 29313859Sml29623 } else if (an_common.bits.cap_10hdx) { 29323859Sml29623 statsp->mac_stats.link_speed = 10; 29333859Sml29623 statsp->mac_stats.link_duplex = 1; 29343859Sml29623 } else { 29353859Sml29623 goto fail; 29363859Sml29623 } 29373859Sml29623 } 29383859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 29393859Sml29623 statsp->mac_stats.link_asmpause = 29403859Sml29623 an_common.bits.cap_asmpause; 29413859Sml29623 if (statsp->mac_stats.link_asmpause) 29423859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 29433859Sml29623 (statsp->mac_stats.lp_cap_pause 29443859Sml29623 == 1)) 29453859Sml29623 statsp->mac_stats.link_pause 29463859Sml29623 = 0; 29473859Sml29623 else 29483859Sml29623 statsp->mac_stats.link_pause 29493859Sml29623 = 1; 29503859Sml29623 else 29513859Sml29623 statsp->mac_stats.link_pause = 29523859Sml29623 an_common.bits.cap_pause; 29533859Sml29623 } 29543859Sml29623 } 29553859Sml29623 *link_up = LINK_IS_UP; 29563859Sml29623 } 29573859Sml29623 29583859Sml29623 if (nxgep->link_notify) { 29593859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 29603859Sml29623 LINK_IS_DOWN); 29613859Sml29623 nxgep->link_notify = B_FALSE; 29623859Sml29623 } 29633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 29643859Sml29623 return (NXGE_OK); 29653859Sml29623 fail: 29663859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 29673859Sml29623 "nxge_mii_check: Unable to check MII")); 29683859Sml29623 return (status); 29693859Sml29623 } 29703859Sml29623 29714977Sraghus /* Check PCS to see if there is any link status change */ 29724977Sraghus nxge_status_t 29734977Sraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 29744977Sraghus { 29754977Sraghus p_nxge_stats_t statsp; 29764977Sraghus nxge_status_t status = NXGE_OK; 29774977Sraghus boolean_t linkup; 29784977Sraghus 29794977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 29804977Sraghus 29814977Sraghus statsp = nxgep->statsp; 29824977Sraghus *link_up = LINK_NO_CHANGE; 29834977Sraghus 29844977Sraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 29854977Sraghus if (linkup) { 29864977Sraghus if (nxgep->link_notify || 29874977Sraghus nxgep->statsp->mac_stats.link_up == 0) { 29884977Sraghus statsp->mac_stats.link_up = 1; 29894977Sraghus statsp->mac_stats.link_speed = 1000; 29904977Sraghus statsp->mac_stats.link_duplex = 2; 29914977Sraghus *link_up = LINK_IS_UP; 29924977Sraghus nxgep->link_notify = B_FALSE; 29934977Sraghus } 29944977Sraghus } else { 29954977Sraghus if (nxgep->link_notify || 29964977Sraghus nxgep->statsp->mac_stats.link_up == 1) { 29974977Sraghus statsp->mac_stats.link_up = 0; 29984977Sraghus statsp->mac_stats.link_speed = 0; 29994977Sraghus statsp->mac_stats.link_duplex = 0; 30004977Sraghus *link_up = LINK_IS_DOWN; 30014977Sraghus nxgep->link_notify = B_FALSE; 30024977Sraghus } 30034977Sraghus } 30044977Sraghus 30054977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 30064977Sraghus return (NXGE_OK); 30074977Sraghus fail: 30084977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 30094977Sraghus "nxge_pcs_check: Unable to check PCS")); 30104977Sraghus return (status); 30114977Sraghus } 30124977Sraghus 30133859Sml29623 /* Add a multicast address entry into the HW hash table */ 30143859Sml29623 30153859Sml29623 nxge_status_t 30163859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 30173859Sml29623 { 30183859Sml29623 uint32_t mchash; 30193859Sml29623 p_hash_filter_t hash_filter; 30203859Sml29623 uint16_t hash_bit; 30213859Sml29623 boolean_t rx_init = B_FALSE; 30223859Sml29623 uint_t j; 30233859Sml29623 nxge_status_t status = NXGE_OK; 30243859Sml29623 30253859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 30263859Sml29623 30273859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 30283859Sml29623 mchash = crc32_mchash(addrp); 30293859Sml29623 if (nxgep->hash_filter == NULL) { 30303859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 30313859Sml29623 "Allocating hash filter storage.")); 30323859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 30333859Sml29623 KM_SLEEP); 30343859Sml29623 } 30353859Sml29623 hash_filter = nxgep->hash_filter; 30363859Sml29623 j = mchash / HASH_REG_WIDTH; 30373859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 30383859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 30393859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 30403859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 30413859Sml29623 hash_filter->hash_ref_cnt++; 30423859Sml29623 rx_init = B_TRUE; 30433859Sml29623 } 30443859Sml29623 if (rx_init) { 30453859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 30463859Sml29623 goto fail; 30473859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 30483859Sml29623 goto fail; 30493859Sml29623 } 30503859Sml29623 30513859Sml29623 RW_EXIT(&nxgep->filter_lock); 30523859Sml29623 30533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 30543859Sml29623 30553859Sml29623 return (NXGE_OK); 30563859Sml29623 fail: 30573859Sml29623 RW_EXIT(&nxgep->filter_lock); 30583859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 30593859Sml29623 "Unable to add multicast address")); 30603859Sml29623 return (status); 30613859Sml29623 } 30623859Sml29623 30633859Sml29623 /* Remove a multicast address entry from the HW hash table */ 30643859Sml29623 30653859Sml29623 nxge_status_t 30663859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 30673859Sml29623 { 30683859Sml29623 uint32_t mchash; 30693859Sml29623 p_hash_filter_t hash_filter; 30703859Sml29623 uint16_t hash_bit; 30713859Sml29623 boolean_t rx_init = B_FALSE; 30723859Sml29623 uint_t j; 30733859Sml29623 nxge_status_t status = NXGE_OK; 30743859Sml29623 30753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 30763859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 30773859Sml29623 mchash = crc32_mchash(addrp); 30783859Sml29623 if (nxgep->hash_filter == NULL) { 30793859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 30803859Sml29623 "Hash filter already de_allocated.")); 30813859Sml29623 RW_EXIT(&nxgep->filter_lock); 30823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 30833859Sml29623 return (NXGE_OK); 30843859Sml29623 } 30853859Sml29623 hash_filter = nxgep->hash_filter; 30863859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 30873859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 30883859Sml29623 j = mchash / HASH_REG_WIDTH; 30893859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 30903859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 30913859Sml29623 hash_filter->hash_ref_cnt--; 30923859Sml29623 rx_init = B_TRUE; 30933859Sml29623 } 30943859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 30953859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 30963859Sml29623 "De-allocating hash filter storage.")); 30973859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 30983859Sml29623 nxgep->hash_filter = NULL; 30993859Sml29623 } 31003859Sml29623 31013859Sml29623 if (rx_init) { 31023859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 31033859Sml29623 goto fail; 31043859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 31053859Sml29623 goto fail; 31063859Sml29623 } 31073859Sml29623 RW_EXIT(&nxgep->filter_lock); 31083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 31093859Sml29623 31103859Sml29623 return (NXGE_OK); 31113859Sml29623 fail: 31123859Sml29623 RW_EXIT(&nxgep->filter_lock); 31133859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 31143859Sml29623 "Unable to remove multicast address")); 31153859Sml29623 31163859Sml29623 return (status); 31173859Sml29623 } 31183859Sml29623 31193859Sml29623 /* Set MAC address into MAC address HW registers */ 31203859Sml29623 31213859Sml29623 nxge_status_t 31223859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 31233859Sml29623 { 31243859Sml29623 nxge_status_t status = NXGE_OK; 31253859Sml29623 31263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 31273859Sml29623 31283859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 31293859Sml29623 /* 31303859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 31313859Sml29623 */ 31323859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 31333859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 31343859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 31353859Sml29623 goto nxge_set_mac_addr_exit; 31363859Sml29623 } 31373859Sml29623 nxgep->ouraddr = *addrp; 31383859Sml29623 /* 31393859Sml29623 * Set new interface local address and re-init device. 31403859Sml29623 * This is destructive to any other streams attached 31413859Sml29623 * to this device. 31423859Sml29623 */ 31433859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 31443859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 31453859Sml29623 goto fail; 31463859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 31473859Sml29623 goto fail; 31483859Sml29623 31493859Sml29623 RW_EXIT(&nxgep->filter_lock); 31503859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 31513859Sml29623 goto nxge_set_mac_addr_end; 31523859Sml29623 nxge_set_mac_addr_exit: 31533859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 31543859Sml29623 nxge_set_mac_addr_end: 31553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 31563859Sml29623 31573859Sml29623 return (NXGE_OK); 31583859Sml29623 fail: 31593859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 31603859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 31613859Sml29623 "Unable to set mac address")); 31623859Sml29623 return (status); 31633859Sml29623 } 31643859Sml29623 31654693Stm144005 static 31664693Stm144005 check_link_state_t 31674693Stm144005 nxge_check_link_stop( 31684693Stm144005 nxge_t *nxge) 31694693Stm144005 { 31704693Stm144005 /* If the poll has been cancelled, return STOP. */ 31714693Stm144005 MUTEX_ENTER(&nxge->poll_lock); 31724693Stm144005 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 31734693Stm144005 nxge->poll_state = LINK_MONITOR_STOP; 31744693Stm144005 nxge->nxge_link_poll_timerid = 0; 31754693Stm144005 cv_broadcast(&nxge->poll_cv); 31764693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 31774693Stm144005 31784693Stm144005 NXGE_DEBUG_MSG((nxge, MAC_CTL, 31794693Stm144005 "nxge_check_%s_link(port<%d>) stopped.", 31804693Stm144005 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 31814693Stm144005 nxge->mac.portnum)); 31824693Stm144005 return (CHECK_LINK_STOP); 31834693Stm144005 } 31844693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 31854693Stm144005 31864693Stm144005 return (CHECK_LINK_RESCHEDULE); 31874693Stm144005 } 31884693Stm144005 31893859Sml29623 /* Check status of MII (MIF or PCS) link */ 31903859Sml29623 31914732Sdavemq static nxge_status_t 31923859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 31933859Sml29623 { 31943859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 31953859Sml29623 mii_anlpar_t anlpar; 31963859Sml29623 mii_gsr_t gsr; 31973859Sml29623 p_mii_regs_t mii_regs; 31983859Sml29623 nxge_status_t status = NXGE_OK; 31993859Sml29623 uint8_t portn; 32003859Sml29623 nxge_link_state_t link_up; 32013859Sml29623 32024693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 32034693Stm144005 return (NXGE_ERROR); 32044693Stm144005 32054693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 32064693Stm144005 return (NXGE_OK); 32074693Stm144005 32083859Sml29623 portn = nxgep->mac.portnum; 32093859Sml29623 32103859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 32114693Stm144005 portn)); 32123859Sml29623 32133859Sml29623 mii_regs = NULL; 32143859Sml29623 32153859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 32163859Sml29623 32173859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 32183859Sml29623 goto nxge_check_mii_link_exit; 32193859Sml29623 32204977Sraghus switch (nxgep->mac.portmode) { 32214977Sraghus default: 32223859Sml29623 if ((status = nxge_mii_read(nxgep, 32234977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 3224*5125Sjoycey #if defined(__i386) 3225*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 3226*5125Sjoycey #else 32274977Sraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 3228*5125Sjoycey #endif 32294977Sraghus &bmsr_data.value)) != NXGE_OK) { 32303859Sml29623 goto fail; 32313859Sml29623 } 32324977Sraghus 32334977Sraghus if (nxgep->param_arr[param_autoneg].value) { 32344977Sraghus if ((status = nxge_mii_read(nxgep, 32354977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 3236*5125Sjoycey #if defined(__i386) 3237*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 3238*5125Sjoycey #else 32394977Sraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 3240*5125Sjoycey #endif 32414977Sraghus &gsr.value)) != NXGE_OK) 32424977Sraghus goto fail; 32434977Sraghus if ((status = nxge_mii_read(nxgep, 32444977Sraghus nxgep->statsp->mac_stats.xcvr_portn, 3245*5125Sjoycey #if defined(__i386) 3246*5125Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 3247*5125Sjoycey #else 32484977Sraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 3249*5125Sjoycey #endif 32504977Sraghus &anlpar.value)) != NXGE_OK) 32514977Sraghus goto fail; 32524977Sraghus if (nxgep->statsp->mac_stats.link_up && 32534977Sraghus ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 32544977Sraghus gsr.bits.link_1000fdx) || 32554977Sraghus (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 32564977Sraghus gsr.bits.link_1000hdx) || 32574977Sraghus (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 32584977Sraghus anlpar.bits.cap_100T4) || 32594977Sraghus (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 32604977Sraghus anlpar.bits.cap_100fdx) || 32614977Sraghus (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 32624977Sraghus anlpar.bits.cap_100hdx) || 32634977Sraghus (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 32644977Sraghus anlpar.bits.cap_10fdx) || 32654977Sraghus (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 32664977Sraghus anlpar.bits.cap_10hdx))) { 32674977Sraghus bmsr_data.bits.link_status = 0; 32684977Sraghus } 32694977Sraghus } 32704977Sraghus 32714977Sraghus /* Workaround for link down issue */ 32724977Sraghus if (bmsr_data.value == 0) { 32734977Sraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 32744977Sraghus goto nxge_check_mii_link_exit; 32754977Sraghus } 32764977Sraghus 32774977Sraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 32784977Sraghus nxgep->bmsr.value = bmsr_data.value; 32794977Sraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 32804977Sraghus &link_up)) != NXGE_OK) { 32814977Sraghus goto fail; 32824977Sraghus } 32834977Sraghus break; 32844977Sraghus 32854977Sraghus case PORT_1G_SERDES: 32864977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 32874977Sraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 32884977Sraghus if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 32894977Sraghus != NXGE_OK) { 32904977Sraghus goto fail; 32914977Sraghus } 32924977Sraghus break; 32933859Sml29623 } 32943859Sml29623 32953859Sml29623 nxge_check_mii_link_exit: 32963859Sml29623 RW_EXIT(&nxgep->filter_lock); 32973859Sml29623 if (link_up == LINK_IS_UP) { 32983859Sml29623 nxge_link_is_up(nxgep); 32993859Sml29623 } else if (link_up == LINK_IS_DOWN) { 33003859Sml29623 nxge_link_is_down(nxgep); 33013859Sml29623 } 33023859Sml29623 33033859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 33043859Sml29623 33053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 33064977Sraghus portn)); 33073859Sml29623 return (NXGE_OK); 33083859Sml29623 33093859Sml29623 fail: 33103859Sml29623 RW_EXIT(&nxgep->filter_lock); 33113859Sml29623 33123859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 33133859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 33144977Sraghus "nxge_check_mii_link: Failed to check link port<%d>", 33154977Sraghus portn)); 33163859Sml29623 return (status); 33173859Sml29623 } 33183859Sml29623 33193859Sml29623 33203859Sml29623 /*ARGSUSED*/ 33214732Sdavemq static nxge_status_t 33223859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 33233859Sml29623 { 33243859Sml29623 uint8_t portn; 33253859Sml29623 nxge_status_t status = NXGE_OK; 33263859Sml29623 boolean_t link_up; 33274977Sraghus boolean_t xpcs_up, xmac_up; 33284977Sraghus uint32_t val; 33294977Sraghus npi_status_t rs; 33303859Sml29623 33314693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 33324693Stm144005 return (NXGE_ERROR); 33334693Stm144005 33344693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 33354693Stm144005 return (NXGE_OK); 33364693Stm144005 33373859Sml29623 portn = nxgep->mac.portnum; 33383859Sml29623 33393859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 33404693Stm144005 portn)); 33413859Sml29623 33424977Sraghus switch (nxgep->mac.portmode) { 33434977Sraghus default: 33444977Sraghus status = nxge_check_bcm8704_link(nxgep, &link_up); 33454977Sraghus if (status != NXGE_OK) 33464977Sraghus goto fail; 33474977Sraghus break; 33484977Sraghus case PORT_10G_SERDES: 33494977Sraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 33504977Sraghus XPCS_REG_STATUS1, &val); 33514977Sraghus if (rs != 0) 33524977Sraghus goto fail; 33534977Sraghus 33544977Sraghus link_up = B_FALSE; 33554977Sraghus xmac_up = B_FALSE; 33564977Sraghus xpcs_up = B_FALSE; 33574977Sraghus if (val & XPCS_STATUS1_RX_LINK_STATUS_UP) { 33584977Sraghus xpcs_up = B_TRUE; 33594977Sraghus } 33604977Sraghus 33614977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 33624977Sraghus "==> nxge_check_10g_link port<%d> " 33634977Sraghus "XPCS_REG_STATUS1 0x%x xpcs_up %d", 33644977Sraghus portn, val, xpcs_up)); 33654977Sraghus /* 33664977Sraghus * Read the xMAC internal signal 2 register. 33674977Sraghus * This register should be the superset of the XPCS when wanting 33684977Sraghus * to get the link status. If this register read is proved to be 33694977Sraghus * reliable, there is no need to read the XPCS register. 33704977Sraghus */ 33714977Sraghus xmac_up = B_TRUE; 33724977Sraghus XMAC_REG_RD(nxgep->npi_handle, portn, XMAC_INTERN2_REG, &val); 33734977Sraghus if (val & XMAC_IS2_LOCAL_FLT_OC_SYNC) { /* link is down */ 33744977Sraghus xmac_up = B_FALSE; 33754977Sraghus } 33764977Sraghus 33774977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 33784977Sraghus "==> nxge_check_10g_link port<%d> " 33794977Sraghus "XMAC_INTERN2_REG 0x%x xmac_up %d", 33804977Sraghus portn, val, xmac_up)); 33814977Sraghus 33824977Sraghus if (xpcs_up && xmac_up) { 33834977Sraghus link_up = B_TRUE; 33844977Sraghus } 33854977Sraghus break; 33864977Sraghus } 33873859Sml29623 33883859Sml29623 if (link_up) { 33893859Sml29623 if (nxgep->link_notify || 33903859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 33913859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 33923859Sml29623 goto fail; 33933859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 33943859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 33953859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 33963859Sml29623 33973859Sml29623 nxge_link_is_up(nxgep); 33983859Sml29623 nxgep->link_notify = B_FALSE; 33993859Sml29623 } 34003859Sml29623 } else { 34013859Sml29623 if (nxgep->link_notify || 34023859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 34033859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 34043859Sml29623 goto fail; 34053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 34064977Sraghus "Link down cable problem")); 34073859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 34083859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 34093859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 34103859Sml29623 34113859Sml29623 nxge_link_is_down(nxgep); 34123859Sml29623 nxgep->link_notify = B_FALSE; 34133859Sml29623 } 34143859Sml29623 } 34153859Sml29623 34163859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 34173859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 34184693Stm144005 portn)); 34193859Sml29623 return (NXGE_OK); 34203859Sml29623 34213859Sml29623 fail: 34224693Stm144005 (void) nxge_check_link_stop(nxgep); 34234693Stm144005 34243859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 34254693Stm144005 "nxge_check_10g_link: Failed to check link port<%d>", 34264693Stm144005 portn)); 34273859Sml29623 return (status); 34283859Sml29623 } 34293859Sml29623 34303859Sml29623 34313859Sml29623 /* Declare link down */ 34323859Sml29623 34333859Sml29623 void 34343859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 34353859Sml29623 { 34364732Sdavemq p_nxge_stats_t statsp; 34374732Sdavemq char link_stat_msg[64]; 34384732Sdavemq 34393859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 34403859Sml29623 34414732Sdavemq statsp = nxgep->statsp; 34424732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 34434732Sdavemq statsp->mac_stats.xcvr_portn); 34444732Sdavemq 34454732Sdavemq if (nxge_no_msg == B_FALSE) { 34464732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 34474732Sdavemq } 34484732Sdavemq 34493859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 34503859Sml29623 34513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 34523859Sml29623 } 34533859Sml29623 34543859Sml29623 /* Declare link up */ 34553859Sml29623 34563859Sml29623 void 34573859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 34583859Sml29623 { 34594732Sdavemq p_nxge_stats_t statsp; 34604732Sdavemq char link_stat_msg[64]; 34613859Sml29623 uint32_t val; 34623859Sml29623 34633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 34643859Sml29623 34654732Sdavemq statsp = nxgep->statsp; 34664732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 34674732Sdavemq statsp->mac_stats.xcvr_portn, 34684732Sdavemq statsp->mac_stats.link_speed); 34694732Sdavemq 34704732Sdavemq if (statsp->mac_stats.link_T4) 34714732Sdavemq (void) strcat(link_stat_msg, "T4"); 34724732Sdavemq else if (statsp->mac_stats.link_duplex == 2) 34734732Sdavemq (void) strcat(link_stat_msg, "full duplex"); 34744732Sdavemq else 34754732Sdavemq (void) strcat(link_stat_msg, "half duplex"); 34764732Sdavemq 34773859Sml29623 (void) nxge_xif_init(nxgep); 34783859Sml29623 34793859Sml29623 /* Clean up symbol errors incurred during link transition */ 34804977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 34814977Sraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 34823859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34833859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 34843859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34853859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 34863859Sml29623 } 34873859Sml29623 34884732Sdavemq if (nxge_no_msg == B_FALSE) { 34894732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 34904732Sdavemq } 34914732Sdavemq 34923859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 34933859Sml29623 34943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 34953859Sml29623 } 34963859Sml29623 34973859Sml29623 /* 34983859Sml29623 * Calculate the bit in the multicast address filter 34993859Sml29623 * that selects the given * address. 35003859Sml29623 * Note: For GEM, the last 8-bits are used. 35013859Sml29623 */ 35023859Sml29623 uint32_t 35033859Sml29623 crc32_mchash(p_ether_addr_t addr) 35043859Sml29623 { 35053859Sml29623 uint8_t *cp; 35063859Sml29623 uint32_t crc; 35073859Sml29623 uint32_t c; 35083859Sml29623 int byte; 35093859Sml29623 int bit; 35103859Sml29623 35113859Sml29623 cp = (uint8_t *)addr; 35123859Sml29623 crc = (uint32_t)0xffffffff; 35133859Sml29623 for (byte = 0; byte < 6; byte++) { 35143859Sml29623 c = (uint32_t)cp[byte]; 35153859Sml29623 for (bit = 0; bit < 8; bit++) { 35163859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 35173859Sml29623 crc = (crc >> 1)^0xedb88320; 35183859Sml29623 else 35193859Sml29623 crc = (crc >> 1); 35203859Sml29623 c >>= 1; 35213859Sml29623 } 35223859Sml29623 } 35233859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 35243859Sml29623 } 35253859Sml29623 35263859Sml29623 /* Reset serdes */ 35273859Sml29623 35283859Sml29623 nxge_status_t 35293859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 35303859Sml29623 { 35313859Sml29623 npi_handle_t handle; 35323859Sml29623 35333859Sml29623 handle = nxgep->npi_handle; 35343859Sml29623 35353859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 35363859Sml29623 drv_usecwait(500); 35373859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 35383859Sml29623 35393859Sml29623 return (NXGE_OK); 35403859Sml29623 } 35413859Sml29623 35423859Sml29623 /* Monitor link status using interrupt or polling */ 35433859Sml29623 35443859Sml29623 nxge_status_t 35453859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 35463859Sml29623 { 35473859Sml29623 nxge_status_t status = NXGE_OK; 35483859Sml29623 35493859Sml29623 /* 35504693Stm144005 * Return immediately if this is an imaginary XMAC port. 35514693Stm144005 * (At least, we don't have 4-port XMAC cards yet.) 35523859Sml29623 */ 35534977Sraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 35544977Sraghus nxgep->mac.portmode == PORT_10G_SERDES) && 35554977Sraghus (nxgep->mac.portnum > 1)) 35563859Sml29623 return (NXGE_OK); 35573859Sml29623 35583859Sml29623 if (nxgep->statsp == NULL) { 35593859Sml29623 /* stats has not been allocated. */ 35603859Sml29623 return (NXGE_OK); 35613859Sml29623 } 35623859Sml29623 /* Don't check link if we're not in internal loopback mode */ 35633859Sml29623 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 35643859Sml29623 return (NXGE_OK); 35653859Sml29623 35663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 35674693Stm144005 "==> nxge_link_monitor port<%d> enable=%d", 35684693Stm144005 nxgep->mac.portnum, enable)); 35693859Sml29623 if (enable == LINK_MONITOR_START) { 35703859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 35713859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 35724693Stm144005 != NXGE_OK) 35733859Sml29623 goto fail; 35743859Sml29623 } else { 35754693Stm144005 timeout_id_t timerid; 35764693Stm144005 35774693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 35784693Stm144005 return (NXGE_OK); 35794693Stm144005 35804732Sdavemq if (nxgep->xcvr.check_link) { 35814732Sdavemq timerid = timeout( 35824732Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 35834693Stm144005 nxgep, 35844693Stm144005 drv_usectohz(LINK_MONITOR_PERIOD)); 35854732Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 35864732Sdavemq nxgep->nxge_link_poll_timerid = timerid; 35874732Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 35884732Sdavemq } else { 35894693Stm144005 return (NXGE_ERROR); 35903859Sml29623 } 35913859Sml29623 } 35923859Sml29623 } else { 35933859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 35943859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 35954693Stm144005 != NXGE_OK) 35963859Sml29623 goto fail; 35973859Sml29623 } else { 35984693Stm144005 clock_t rv; 35994693Stm144005 36004693Stm144005 MUTEX_ENTER(&nxgep->poll_lock); 36014693Stm144005 36024693Stm144005 /* If <timerid> == 0, the link monitor has */ 36034693Stm144005 /* never been started, or just now stopped. */ 36044693Stm144005 if (nxgep->nxge_link_poll_timerid == 0) { 36054693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 36064693Stm144005 return (NXGE_OK); 36074693Stm144005 } 36084693Stm144005 36094693Stm144005 nxgep->poll_state = LINK_MONITOR_STOPPING; 36104693Stm144005 rv = cv_timedwait(&nxgep->poll_cv, 36114693Stm144005 &nxgep->poll_lock, 36124693Stm144005 ddi_get_lbolt() + 36134693Stm144005 drv_usectohz(LM_WAIT_MULTIPLIER * 36144693Stm144005 LINK_MONITOR_PERIOD)); 36154693Stm144005 if (rv == -1) { 36164693Stm144005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36174693Stm144005 "==> stopping port %d: " 36184693Stm144005 "cv_timedwait(%d) timed out", 36194693Stm144005 nxgep->mac.portnum, nxgep->poll_state)); 36204693Stm144005 nxgep->poll_state = LINK_MONITOR_STOP; 36213859Sml29623 nxgep->nxge_link_poll_timerid = 0; 36223859Sml29623 } 36234693Stm144005 36244693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 36253859Sml29623 } 36263859Sml29623 } 36273859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36284693Stm144005 "<== nxge_link_monitor port<%d> enable=%d", 36294693Stm144005 nxgep->mac.portnum, enable)); 36303859Sml29623 return (NXGE_OK); 36313859Sml29623 fail: 36323859Sml29623 return (status); 36333859Sml29623 } 36343859Sml29623 36353859Sml29623 /* Set promiscous mode */ 36363859Sml29623 36373859Sml29623 nxge_status_t 36383859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 36393859Sml29623 { 36403859Sml29623 nxge_status_t status = NXGE_OK; 36413859Sml29623 36424732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 36433859Sml29623 36443859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 36453859Sml29623 36463859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 36473859Sml29623 36483859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 36493859Sml29623 goto fail; 36503859Sml29623 } 36513859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 36523859Sml29623 goto fail; 36533859Sml29623 } 36543859Sml29623 36553859Sml29623 RW_EXIT(&nxgep->filter_lock); 36563859Sml29623 36573859Sml29623 if (on) 36583859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 36593859Sml29623 else 36603859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 36613859Sml29623 36623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 36633859Sml29623 36643859Sml29623 return (NXGE_OK); 36653859Sml29623 fail: 36663859Sml29623 RW_EXIT(&nxgep->filter_lock); 36673859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 36684732Sdavemq "Unable to set promisc (%d)", on)); 36693859Sml29623 36703859Sml29623 return (status); 36713859Sml29623 } 36723859Sml29623 36733859Sml29623 /*ARGSUSED*/ 36743859Sml29623 uint_t 36753859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 36763859Sml29623 { 36773859Sml29623 #ifdef NXGE_DEBUG 36783859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 36793859Sml29623 #endif 36803859Sml29623 #if NXGE_MIF 36813859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 36823859Sml29623 uint32_t status; 36833859Sml29623 npi_handle_t handle; 36843859Sml29623 uint8_t portn; 36853859Sml29623 p_nxge_stats_t statsp; 36863859Sml29623 #endif 36873859Sml29623 36883859Sml29623 #ifdef NXGE_MIF 36893859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 36903859Sml29623 nxgep = ldvp->nxgep; 36913859Sml29623 } 36923859Sml29623 nxgep = ldvp->nxgep; 36933859Sml29623 #endif 36943859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 36953859Sml29623 36963859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 36973859Sml29623 return (DDI_INTR_CLAIMED); 36983859Sml29623 36993859Sml29623 mif_intr_fail: 37003859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 37013859Sml29623 return (DDI_INTR_UNCLAIMED); 37023859Sml29623 } 37033859Sml29623 37043859Sml29623 /*ARGSUSED*/ 37053859Sml29623 uint_t 37063859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 37073859Sml29623 { 37083859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 37093859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 37103859Sml29623 p_nxge_ldg_t ldgp; 37113859Sml29623 uint32_t status; 37123859Sml29623 npi_handle_t handle; 37133859Sml29623 uint8_t portn; 37143859Sml29623 p_nxge_stats_t statsp; 37153859Sml29623 npi_status_t rs = NPI_SUCCESS; 37163859Sml29623 37173859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 37183859Sml29623 nxgep = ldvp->nxgep; 37193859Sml29623 } 37203859Sml29623 37213859Sml29623 ldgp = ldvp->ldgp; 37223859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 37234732Sdavemq "group %d", ldgp->ldg)); 37243859Sml29623 37253859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 37263859Sml29623 /* 37273859Sml29623 * This interrupt handler is for a specific 37283859Sml29623 * mac port. 37293859Sml29623 */ 37303859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 37313859Sml29623 portn = nxgep->mac.portnum; 37323859Sml29623 37333859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 37344732Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 37353859Sml29623 37363859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 37373859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 37383859Sml29623 (xmac_tx_iconfig_t *)&status); 37393859Sml29623 if (rs != NPI_SUCCESS) 37403859Sml29623 goto npi_fail; 37413859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 37423859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 37433859Sml29623 statsp->xmac_stats.tx_underflow_err++; 37443859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37453859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 37463859Sml29623 } 37473859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 37483859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 37493859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37503859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 37513859Sml29623 } 37523859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 37533859Sml29623 statsp->xmac_stats.tx_overflow_err++; 37543859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37553859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 37563859Sml29623 } 37573859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 37583859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 37593859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37603859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 37613859Sml29623 } 37623859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 37633859Sml29623 statsp->xmac_stats.tx_byte_cnt += 37643859Sml29623 XTXMAC_BYTE_CNT_MASK; 37653859Sml29623 } 37663859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 37673859Sml29623 statsp->xmac_stats.tx_frame_cnt += 37683859Sml29623 XTXMAC_FRM_CNT_MASK; 37693859Sml29623 } 37703859Sml29623 } 37713859Sml29623 37723859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 37733859Sml29623 (xmac_rx_iconfig_t *)&status); 37743859Sml29623 if (rs != NPI_SUCCESS) 37753859Sml29623 goto npi_fail; 37763859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 37773859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 37783859Sml29623 statsp->xmac_stats.rx_overflow_err++; 37793859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 37803859Sml29623 statsp->xmac_stats.rx_underflow_err++; 37813859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37823859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 37833859Sml29623 } 37843859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 37853859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 37863859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 37873859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37883859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 37893859Sml29623 } 37903859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 37913859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 37923859Sml29623 MAC_LEN_ER_CNT_MASK; 37933859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 37943859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 37953859Sml29623 } 37963859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 37973859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 37983859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 37993859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38003859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 38013859Sml29623 } 38023859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 38033859Sml29623 statsp->xmac_stats.rx_byte_cnt += 38043859Sml29623 XRXMAC_BT_CNT_MASK; 38053859Sml29623 } 38063859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 38073859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 38083859Sml29623 XRXMAC_HIST_CNT1_MASK; 38093859Sml29623 } 38103859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 38113859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 38123859Sml29623 XRXMAC_HIST_CNT2_MASK; 38133859Sml29623 } 38143859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 38153859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 38163859Sml29623 XRXMAC_HIST_CNT3_MASK; 38173859Sml29623 } 38183859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 38193859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 38203859Sml29623 XRXMAC_HIST_CNT4_MASK; 38213859Sml29623 } 38223859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 38233859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 38243859Sml29623 XRXMAC_HIST_CNT5_MASK; 38253859Sml29623 } 38263859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 38273859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 38283859Sml29623 XRXMAC_HIST_CNT6_MASK; 38293859Sml29623 } 38303859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 38313859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 38323859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 38333859Sml29623 } 38343859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 38353859Sml29623 statsp->xmac_stats.rx_mult_cnt += 38363859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 38373859Sml29623 } 38383859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 38393859Sml29623 statsp->xmac_stats.rx_frag_cnt += 38403859Sml29623 XRXMAC_FRAG_CNT_MASK; 38413859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38423859Sml29623 NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 38433859Sml29623 } 38443859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 38453859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 38463859Sml29623 XRXMAC_AL_ER_CNT_MASK; 38473859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38483859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 38493859Sml29623 } 38503859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 38513859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 38523859Sml29623 XMAC_LINK_FLT_CNT_MASK; 38533859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38543859Sml29623 NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 38553859Sml29623 } 38563859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 38573859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 38583859Sml29623 } 38593859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 38603859Sml29623 statsp->xmac_stats.rx_localfault_err++; 38613859Sml29623 } 38623859Sml29623 } 38633859Sml29623 38643859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 38653859Sml29623 (xmac_ctl_iconfig_t *)&status); 38663859Sml29623 if (rs != NPI_SUCCESS) 38673859Sml29623 goto npi_fail; 38683859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 38693859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 38703859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 38713859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 38723859Sml29623 statsp->xmac_stats.tx_pause_state++; 38733859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 38743859Sml29623 statsp->xmac_stats.tx_nopause_state++; 38753859Sml29623 } 38763859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 38773859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 38783859Sml29623 (bmac_tx_iconfig_t *)&status); 38793859Sml29623 if (rs != NPI_SUCCESS) 38803859Sml29623 goto npi_fail; 38813859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 38823859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 38833859Sml29623 statsp->bmac_stats.tx_underrun_err++; 38843859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38853859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 38863859Sml29623 } 38873859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 38883859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 38893859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 38903859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 38913859Sml29623 } 38923859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 38933859Sml29623 statsp->bmac_stats.tx_byte_cnt += 38943859Sml29623 BTXMAC_BYTE_CNT_MASK; 38953859Sml29623 } 38963859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 38973859Sml29623 statsp->bmac_stats.tx_frame_cnt += 38983859Sml29623 BTXMAC_FRM_CNT_MASK; 38993859Sml29623 } 39003859Sml29623 } 39013859Sml29623 39023859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 39033859Sml29623 (bmac_rx_iconfig_t *)&status); 39043859Sml29623 if (rs != NPI_SUCCESS) 39053859Sml29623 goto npi_fail; 39063859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 39073859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 39083859Sml29623 statsp->bmac_stats.rx_overflow_err++; 39093859Sml29623 } 39103859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 39113859Sml29623 statsp->bmac_stats.rx_frame_cnt += 39123859Sml29623 RXMAC_FRM_CNT_MASK; 39133859Sml29623 } 39143859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 39153859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 39163859Sml29623 BMAC_CRC_ER_CNT_MASK; 39173859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 39183859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 39193859Sml29623 } 39203859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 39213859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 39223859Sml29623 MAC_LEN_ER_CNT_MASK; 39233859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 39243859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 39253859Sml29623 } 39263859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 39273859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 39283859Sml29623 BMAC_CD_VIO_CNT_MASK; 39293859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 39303859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 39313859Sml29623 } 39323859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 39333859Sml29623 statsp->bmac_stats.rx_byte_cnt += 39343859Sml29623 BRXMAC_BYTE_CNT_MASK; 39353859Sml29623 } 39363859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 39373859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 39383859Sml29623 BMAC_AL_ER_CNT_MASK; 39393859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 39403859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 39413859Sml29623 } 39423859Sml29623 39433859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 39443859Sml29623 (bmac_ctl_iconfig_t *)&status); 39453859Sml29623 if (rs != NPI_SUCCESS) 39463859Sml29623 goto npi_fail; 39473859Sml29623 39483859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 39493859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 39503859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 39513859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 39523859Sml29623 statsp->bmac_stats.tx_pause_state++; 39533859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 39543859Sml29623 statsp->bmac_stats.tx_nopause_state++; 39553859Sml29623 } 39563859Sml29623 } 39573859Sml29623 39583859Sml29623 if (ldgp->nldvs == 1) { 39593859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 39603859Sml29623 B_TRUE, ldgp->ldg_timer); 39613859Sml29623 } 39623859Sml29623 39633859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 39643859Sml29623 return (DDI_INTR_CLAIMED); 39653859Sml29623 39663859Sml29623 npi_fail: 39673859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 39683859Sml29623 return (DDI_INTR_UNCLAIMED); 39693859Sml29623 } 39703859Sml29623 39713859Sml29623 nxge_status_t 39723859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 39733859Sml29623 { 39743859Sml29623 uint8_t phy_port_addr; 39753859Sml29623 nxge_status_t status = NXGE_OK; 39763859Sml29623 boolean_t rx_sig_ok; 39773859Sml29623 boolean_t pcs_blk_lock; 39783859Sml29623 boolean_t link_align; 39793859Sml29623 uint16_t val1, val2, val3; 39803859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 39813859Sml29623 uint16_t val_debug; 39823859Sml29623 uint16_t val; 39833859Sml29623 #endif 39843859Sml29623 39853859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 39863859Sml29623 39873859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 39883859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 39893859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 39903859Sml29623 if ((val_debug & ~0x200) != 0) { 39913859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 39923859Sml29623 nxgep->mac.portnum, val_debug); 39933859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 39943859Sml29623 &val_debug); 39953859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 39963859Sml29623 nxgep->mac.portnum, val_debug); 39973859Sml29623 } 39983859Sml29623 39993859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 40003859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 40013859Sml29623 if (val != 0) 40023859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 40033859Sml29623 40043859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 40053859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 40063859Sml29623 if (val != 0) 40073859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 40083859Sml29623 40093859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 40103859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 40113859Sml29623 if (val != 0) 40123859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 40133859Sml29623 #endif 40143859Sml29623 40153859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 40163859Sml29623 40173859Sml29623 /* Check Device 1 Register 0xA bit0 */ 40183859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 40193859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 40203859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 40213859Sml29623 &val1); 40223859Sml29623 if (status != NXGE_OK) 40233859Sml29623 goto fail; 40243859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 40253859Sml29623 40263859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 40273859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 40283859Sml29623 BCM8704_PCS_DEV_ADDR, 40293859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 40303859Sml29623 &val2)) != NPI_SUCCESS) 40313859Sml29623 goto fail; 40323859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 40333859Sml29623 40343859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 40353859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 40363859Sml29623 BCM8704_PHYXS_ADDR, 40373859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 40383859Sml29623 &val3); 40393859Sml29623 if (status != NXGE_OK) 40403859Sml29623 goto fail; 40413859Sml29623 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 40423859Sml29623 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 40433859Sml29623 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 40443859Sml29623 40453859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 40463859Sml29623 /* Temp workaround for link down issue */ 40473859Sml29623 if (pcs_blk_lock == B_FALSE) { 40483859Sml29623 if (val2 != 0x4) { 40493859Sml29623 pcs_blk_lock = B_TRUE; 40503859Sml29623 cmn_err(CE_NOTE, 40513859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 40523859Sml29623 "Reg 0x20 = 0x%x\n", 40533859Sml29623 nxgep->mac.portnum, val2); 40543859Sml29623 } 40553859Sml29623 } 40563859Sml29623 40573859Sml29623 if (link_align == B_FALSE) { 40583859Sml29623 if (val3 != 0x140f) { 40593859Sml29623 link_align = B_TRUE; 40603859Sml29623 cmn_err(CE_NOTE, 40613859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 40623859Sml29623 "Reg 0x18 = 0x%x\n", 40633859Sml29623 nxgep->mac.portnum, val3); 40643859Sml29623 } 40653859Sml29623 } 40663859Sml29623 40673859Sml29623 if (rx_sig_ok == B_FALSE) { 40683859Sml29623 if ((val2 == 0) || (val3 == 0)) { 40693859Sml29623 rx_sig_ok = B_TRUE; 40703859Sml29623 cmn_err(CE_NOTE, 40713859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 40723859Sml29623 nxgep->mac.portnum); 40733859Sml29623 } 40743859Sml29623 } 40753859Sml29623 #endif 40763859Sml29623 40773859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 40783859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 40793859Sml29623 40803859Sml29623 return (NXGE_OK); 40813859Sml29623 fail: 40823859Sml29623 return (status); 40833859Sml29623 } 40843859Sml29623 40853859Sml29623 nxge_status_t 40863859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 40873859Sml29623 { 40883859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 40894732Sdavemq != NPI_SUCCESS) 40903859Sml29623 return (NXGE_ERROR); 40913859Sml29623 else 40923859Sml29623 return (NXGE_OK); 40933859Sml29623 } 40943859Sml29623 40953859Sml29623 nxge_status_t 40963859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 40973859Sml29623 { 40983859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 40994732Sdavemq != NPI_SUCCESS) 41003859Sml29623 return (NXGE_ERROR); 41013859Sml29623 else 41023859Sml29623 return (NXGE_OK); 41033859Sml29623 } 41044185Sspeer 41054732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 41064732Sdavemq 41074732Sdavemq static boolean_t 41084732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 41094732Sdavemq { 41104732Sdavemq int i; 41114732Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 41124732Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 41134732Sdavemq boolean_t found = B_FALSE; 41144732Sdavemq 41154732Sdavemq switch (type) { 41164732Sdavemq case CLAUSE_45_TYPE: 41174732Sdavemq for (i = 0; i < cl45_arr_len; i++) { 41184782Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 41194782Ssbehera (id & BCM_PHY_ID_MASK)) { 41204732Sdavemq found = B_TRUE; 41214732Sdavemq break; 41224732Sdavemq } 41234732Sdavemq } 41244732Sdavemq break; 41254732Sdavemq case CLAUSE_22_TYPE: 41264732Sdavemq for (i = 0; i < cl22_arr_len; i++) { 41274782Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 41284782Ssbehera (id & BCM_PHY_ID_MASK)) { 41294732Sdavemq found = B_TRUE; 41304732Sdavemq break; 41314732Sdavemq } 41324732Sdavemq } 41334732Sdavemq break; 41344732Sdavemq default: 41354732Sdavemq break; 41364732Sdavemq } 41374732Sdavemq 41384732Sdavemq return (found); 41394732Sdavemq } 41404732Sdavemq 41414977Sraghus static uint32_t 41424977Sraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 41434977Sraghus { 41444977Sraghus uint16_t val1 = 0; 41454977Sraghus uint16_t val2 = 0; 41464977Sraghus uint32_t pma_pmd_dev_id = 0; 41474977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 41484977Sraghus 41494977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 41504977Sraghus NXGE_DEV_ID_REG_1, &val1); 41514977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 41524977Sraghus NXGE_DEV_ID_REG_2, &val2); 41534977Sraghus 41544977Sraghus pma_pmd_dev_id = val1; 41554977Sraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 41564977Sraghus pma_pmd_dev_id |= val2; 41574977Sraghus 41584977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 41594977Sraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 41604977Sraghus 41614977Sraghus return (pma_pmd_dev_id); 41624977Sraghus } 41634977Sraghus 41644977Sraghus static uint32_t 41654977Sraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 41664977Sraghus { 41674977Sraghus uint16_t val1 = 0; 41684977Sraghus uint16_t val2 = 0; 41694977Sraghus uint32_t pcs_dev_id = 0; 41704977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 41714977Sraghus 41724977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 41734977Sraghus NXGE_DEV_ID_REG_1, &val1); 41744977Sraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 41754977Sraghus NXGE_DEV_ID_REG_2, &val2); 41764977Sraghus 41774977Sraghus pcs_dev_id = val1; 41784977Sraghus pcs_dev_id = (pcs_dev_id << 16); 41794977Sraghus pcs_dev_id |= val2; 41804977Sraghus 41814977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 41824977Sraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 41834977Sraghus 41844977Sraghus return (pcs_dev_id); 41854977Sraghus } 41864977Sraghus 41874977Sraghus static uint32_t 41884977Sraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 41894977Sraghus { 41904977Sraghus uint16_t val1 = 0; 41914977Sraghus uint16_t val2 = 0; 41924977Sraghus uint32_t phy_id = 0; 41934977Sraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 41944977Sraghus npi_status_t npi_status = NPI_SUCCESS; 41954977Sraghus 41964977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 41974977Sraghus &val1); 41984977Sraghus if (npi_status != NPI_SUCCESS) { 41994977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 42004977Sraghus "clause 22 read to reg 2 failed!!!")); 42014977Sraghus goto exit; 42024977Sraghus } 42034977Sraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 42044977Sraghus &val2); 42054977Sraghus if (npi_status != 0) { 42064977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 42074977Sraghus "clause 22 read to reg 3 failed!!!")); 42084977Sraghus goto exit; 42094977Sraghus } 42104977Sraghus phy_id = val1; 42114977Sraghus phy_id = (phy_id << 16); 42124977Sraghus phy_id |= val2; 42134977Sraghus 42144977Sraghus exit: 42154977Sraghus 42164977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 42174977Sraghus phy_port, phy_id)); 42184977Sraghus 42194977Sraghus return (phy_id); 42204977Sraghus } 42214977Sraghus 42224732Sdavemq /* 42234732Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 42244732Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 42254732Sdavemq * read. Then use the values obtained to determine the phy type of each port 42264732Sdavemq * and the Neptune type. 42274732Sdavemq */ 42284732Sdavemq 42294732Sdavemq nxge_status_t 42304732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 42314732Sdavemq { 42324732Sdavemq int i, j, k, l; 42334732Sdavemq uint32_t pma_pmd_dev_id = 0; 42344732Sdavemq uint32_t pcs_dev_id = 0; 42354732Sdavemq uint32_t phy_id = 0; 42364782Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 42374782Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 42384782Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 42394732Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 42404732Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 42414732Sdavemq uint8_t phy_fd[NXGE_MAX_PHY_PORTS]; 42424732Sdavemq uint8_t port_fd[NXGE_MAX_PHY_PORTS]; 42434732Sdavemq uint8_t total_port_fd, total_phy_fd; 42444732Sdavemq nxge_status_t status = NXGE_OK; 42454732Sdavemq int prt_id = -1; 42464732Sdavemq 42474732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 42484732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 42494732Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 42504732Sdavemq nxgep->niu_type)); 42514732Sdavemq 42524732Sdavemq j = k = l = 0; 42534732Sdavemq total_port_fd = total_phy_fd = 0; 42544732Sdavemq /* 42554732Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 42564732Sdavemq * for on chip serdes usages. 42574732Sdavemq */ 42584732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 42594977Sraghus 42604977Sraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 42614732Sdavemq 42624732Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 42634732Sdavemq pma_pmd_dev_fd[i] = 1; 42644732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 42654732Sdavemq "PMA/PMD dev found", i)); 42664782Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 42674782Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 42684782Ssbehera BCM_PHY_ID_MASK; 42694732Sdavemq j++; 42704732Sdavemq } 42714732Sdavemq } else { 42724732Sdavemq pma_pmd_dev_fd[i] = 0; 42734732Sdavemq } 42744732Sdavemq 42754977Sraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 42764732Sdavemq 42774732Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 42784732Sdavemq pcs_dev_fd[i] = 1; 42794732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 42804732Sdavemq "dev found", i)); 42814782Ssbehera if (k < NXGE_PORTS_NEPTUNE) { 42824782Ssbehera port_pcs_dev_id[k] = pcs_dev_id & 42834782Ssbehera BCM_PHY_ID_MASK; 42844732Sdavemq k++; 42854732Sdavemq } 42864732Sdavemq } else { 42874732Sdavemq pcs_dev_fd[i] = 0; 42884732Sdavemq } 42894732Sdavemq 42904732Sdavemq if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) 42914732Sdavemq port_fd[i] = 1; 42924732Sdavemq else 42934732Sdavemq port_fd[i] = 0; 42944732Sdavemq total_port_fd += port_fd[i]; 42954732Sdavemq 42964977Sraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 42974732Sdavemq 42984732Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 42994732Sdavemq phy_fd[i] = 1; 43004732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 43014732Sdavemq "found", i)); 43024782Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 43034782Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 43044732Sdavemq l++; 43054732Sdavemq } 43064732Sdavemq } else { 43074732Sdavemq phy_fd[i] = 0; 43084732Sdavemq } 43094732Sdavemq total_phy_fd += phy_fd[i]; 43104732Sdavemq } 43114732Sdavemq 43124732Sdavemq switch (total_port_fd) { 43134732Sdavemq case 2: 43144732Sdavemq switch (total_phy_fd) { 43154732Sdavemq case 2: 43164977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43174977Sraghus "Unsupported neptune type 1")); 43184977Sraghus goto error_exit; 43194732Sdavemq case 1: 43204732Sdavemq /* TODO - 2 10G, 1 1G */ 43214732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43224732Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 43234732Sdavemq goto error_exit; 43244732Sdavemq case 0: 43254732Sdavemq /* 2 10G */ 43264782Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 43274782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 43284782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 43294782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 43304977Sraghus 43314977Sraghus /* 43324977Sraghus * Check the first phy port address against 43334977Sraghus * the known phy start addresses to determine 43344977Sraghus * the platform type. 43354977Sraghus */ 43364977Sraghus for (i = NXGE_EXT_PHY_PORT_ST; 43374977Sraghus i < NXGE_MAX_PHY_PORTS; i++) { 43384977Sraghus if (port_fd[i] == 1) 43394977Sraghus break; 43404977Sraghus } 43414977Sraghus if (i == BCM8704_NEPTUNE_PORT_ADDR_BASE) { 43424977Sraghus hw_p->niu_type = NEPTUNE_2_10GF; 43434977Sraghus hw_p->platform_type = 43444977Sraghus P_NEPTUNE_ATLAS_2PORT; 43454977Sraghus } else { 43464977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43474977Sraghus "Unsupported neptune type 2 - 1")); 43484977Sraghus goto error_exit; 43494977Sraghus } 43504732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF; 43514732Sdavemq } else { 43524732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43534732Sdavemq "Unsupported neptune type 2")); 43544732Sdavemq goto error_exit; 43554732Sdavemq } 43564732Sdavemq break; 43574732Sdavemq case 4: 43584732Sdavemq /* Maramba with 2 XAUI */ 43594782Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 43604782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 43614782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 43624782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 43634782Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 43644782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 43654782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 43664782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 43674732Sdavemq 43684732Sdavemq /* 43694732Sdavemq * Check the first phy port address against 43704732Sdavemq * the known phy start addresses to determine 43714732Sdavemq * the platform type. 43724732Sdavemq */ 43734732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 43744732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 43754732Sdavemq if (phy_fd[i] == 1) 43764732Sdavemq break; 43774732Sdavemq } 43784732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 43794732Sdavemq hw_p->platform_type = 43804732Sdavemq P_NEPTUNE_MARAMBA_P0; 43814732Sdavemq } else if (i == 43824732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 43834732Sdavemq hw_p->platform_type = 43844732Sdavemq P_NEPTUNE_MARAMBA_P1; 43854732Sdavemq } else { 43864732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 43874732Sdavemq "Unknown port %d...Cannot " 43884732Sdavemq "determine platform type", i)); 43894977Sraghus goto error_exit; 43904732Sdavemq } 43914977Sraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 43924977Sraghus 43934732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43944732Sdavemq "Maramba with 2 XAUI")); 43954732Sdavemq } else { 43964732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43974732Sdavemq "Unsupported neptune type 3")); 43984732Sdavemq goto error_exit; 43994732Sdavemq } 44004732Sdavemq break; 44014732Sdavemq default: 44024732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44034732Sdavemq "Unsupported neptune type 5")); 44044732Sdavemq goto error_exit; 44054732Sdavemq } 44064782Ssbehera break; 44074732Sdavemq case 1: 44084732Sdavemq switch (total_phy_fd) { 44094732Sdavemq case 3: 44104977Sraghus /* 44114977Sraghus * TODO 3 1G, 1 10G mode. 44124977Sraghus * Differentiate between 1_1G_1_10G_2_1G and 44134977Sraghus * 1_10G_3_1G 44144977Sraghus */ 44154977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44164977Sraghus "Unsupported neptune type 7")); 44174977Sraghus goto error_exit; 44184732Sdavemq case 2: 44194732Sdavemq /* 44204732Sdavemq * TODO 2 1G, 1 10G mode. 44214732Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 44224732Sdavemq * 1_10G_2_1G 44234732Sdavemq */ 44244732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44254732Sdavemq "Unsupported neptune type 8")); 44264732Sdavemq goto error_exit; 44274732Sdavemq case 1: 44284732Sdavemq /* 44294732Sdavemq * TODO 1 1G, 1 10G mode. 44304732Sdavemq * Differentiate between 1_1G_1_10G and 44314732Sdavemq * 1_10G_1_1G 44324732Sdavemq */ 44334732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44344732Sdavemq "Unsupported neptune type 9")); 44354732Sdavemq goto error_exit; 44364732Sdavemq case 0: 44374732Sdavemq /* TODO 1 10G mode */ 44384732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44394732Sdavemq "Unsupported neptune type 10")); 44404732Sdavemq goto error_exit; 44414732Sdavemq case 4: 44424732Sdavemq /* Maramba with 1 XAUI */ 44434782Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 44444782Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 44454732Sdavemq 44464732Sdavemq /* 44474732Sdavemq * Check the first phy port address against 44484732Sdavemq * the known phy start addresses to determine 44494732Sdavemq * the platform type. 44504732Sdavemq */ 44514732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 44524732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 44534732Sdavemq if (phy_fd[i] == 1) 44544732Sdavemq break; 44554732Sdavemq } 44564732Sdavemq 44574732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 44584732Sdavemq hw_p->platform_type = 44594732Sdavemq P_NEPTUNE_MARAMBA_P0; 44604732Sdavemq } else if (i == 44614732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 44624732Sdavemq hw_p->platform_type = 44634732Sdavemq P_NEPTUNE_MARAMBA_P1; 44644732Sdavemq } else { 44654732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 44664732Sdavemq "Unknown port %d...Cannot " 44674732Sdavemq "determine platform type", i)); 44684977Sraghus goto error_exit; 44694977Sraghus } 44704977Sraghus 44714977Sraghus /* The 10G port is BCM8704 */ 44724977Sraghus for (i = NXGE_EXT_PHY_PORT_ST; 44734977Sraghus i < NXGE_MAX_PHY_PORTS; i++) { 44744977Sraghus if (port_fd[i] == 1) { 44754977Sraghus prt_id = i; 44764977Sraghus break; 44774977Sraghus } 44784977Sraghus } 44794977Sraghus 44804977Sraghus prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE; 44814977Sraghus if (prt_id == 0) { 44824977Sraghus hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 44834977Sraghus } else if (prt_id == 1) { 44844977Sraghus hw_p->niu_type = 44854977Sraghus NEPTUNE_1_1GC_1_10GF_2_1GC; 44864977Sraghus } else { 44874977Sraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44884977Sraghus "Unsupported neptune type 11")); 44894977Sraghus goto error_exit; 44904732Sdavemq } 44914732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44924732Sdavemq "Maramba with 1 XAUI")); 44934732Sdavemq } else { 44944732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44954732Sdavemq "Unsupported neptune type 12")); 44964732Sdavemq goto error_exit; 44974732Sdavemq } 44984732Sdavemq break; 44994732Sdavemq default: 45004732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45014732Sdavemq "Unsupported neptune type 13")); 45024732Sdavemq goto error_exit; 45034732Sdavemq } 45044732Sdavemq break; 45054732Sdavemq case 0: 45064732Sdavemq switch (total_phy_fd) { 45074732Sdavemq case 4: 45084782Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 45094782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 45104782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 45114782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 45124732Sdavemq 45134732Sdavemq /* 45144732Sdavemq * Check the first phy port address against 45154732Sdavemq * the known phy start addresses to determine 45164732Sdavemq * the platform type. 45174732Sdavemq */ 45184732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 45194732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 45204732Sdavemq if (phy_fd[i] == 1) 45214732Sdavemq break; 45224732Sdavemq } 45234732Sdavemq 45244732Sdavemq if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 45254732Sdavemq hw_p->platform_type = 45264732Sdavemq P_NEPTUNE_MARAMBA_P1; 45274977Sraghus } else if (i == 45284977Sraghus BCM5464_NEPTUNE_PORT_ADDR_BASE) { 45294977Sraghus hw_p->platform_type = 45304977Sraghus P_NEPTUNE_ATLAS_4PORT; 45314977Sraghus } else { 45324977Sraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 45334977Sraghus "Unknown port %d...Cannot " 45344977Sraghus "determine platform type", i)); 45354977Sraghus goto error_exit; 45364732Sdavemq } 45374977Sraghus hw_p->niu_type = NEPTUNE_4_1GC; 45384732Sdavemq } else { 45394732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45404732Sdavemq "Unsupported neptune type 14")); 45414732Sdavemq goto error_exit; 45424732Sdavemq } 45434732Sdavemq break; 45444732Sdavemq case 3: 45454732Sdavemq /* TODO 3 1G mode */ 45464732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45474732Sdavemq "Unsupported neptune type 15")); 45484732Sdavemq goto error_exit; 45494732Sdavemq case 2: 45504732Sdavemq /* TODO 2 1G mode */ 45514732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45524732Sdavemq "Unsupported neptune type 16")); 45534732Sdavemq goto error_exit; 45544732Sdavemq case 1: 45554732Sdavemq /* TODO 1 1G mode */ 45564732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45574732Sdavemq "Unsupported neptune type 17")); 45584732Sdavemq goto error_exit; 45594732Sdavemq default: 45604732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45614732Sdavemq "Unsupported neptune type 18, total phy fd %d", 45624732Sdavemq total_phy_fd)); 45634732Sdavemq goto error_exit; 45644732Sdavemq } 45654732Sdavemq break; 45664732Sdavemq default: 45674732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45684732Sdavemq "Unsupported neptune type 19")); 45694732Sdavemq goto error_exit; 45704732Sdavemq } 45714732Sdavemq 45724732Sdavemq scan_exit: 45734732Sdavemq 45744732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 45754732Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 45764732Sdavemq return (status); 45774732Sdavemq 45784732Sdavemq error_exit: 45794732Sdavemq return (NXGE_ERROR); 45804732Sdavemq } 45814732Sdavemq 45824185Sspeer boolean_t 45834185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 45844185Sspeer { 45854185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 45864185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 45874185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 45884185Sspeer return (B_FALSE); 45894185Sspeer else 45904185Sspeer return (B_TRUE); 45914185Sspeer } 45924732Sdavemq 45934732Sdavemq static void 45944732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 45954732Sdavemq 45964732Sdavemq npi_status_t rs = NPI_SUCCESS; 45974732Sdavemq uint8_t xcvr_portn; 45984732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 45994732Sdavemq 46004732Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 46014732Sdavemq 46024732Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 46034732Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 46044732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 46054732Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 46064732Sdavemq } 46074732Sdavemq /* 46084732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 46094732Sdavemq * swapped with ethernet port number. This is 46104732Sdavemq * designed for better signal integrity in routing. 46114732Sdavemq */ 46124732Sdavemq switch (portn) { 46134732Sdavemq case 0: 46144732Sdavemq xcvr_portn += 3; 46154732Sdavemq break; 46164732Sdavemq case 1: 46174732Sdavemq xcvr_portn += 2; 46184732Sdavemq break; 46194732Sdavemq case 2: 46204732Sdavemq xcvr_portn += 1; 46214732Sdavemq break; 46224732Sdavemq case 3: 46234732Sdavemq default: 46244732Sdavemq break; 46254732Sdavemq } 46264732Sdavemq 46274732Sdavemq MUTEX_ENTER(&nxge_mii_lock); 46284732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 46294732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 46304732Sdavemq if (rs != NPI_SUCCESS) { 46314732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 46324732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 46334732Sdavemq "returned error 0x[%x]", rs)); 46344732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 46354732Sdavemq return; 46364732Sdavemq } 46374732Sdavemq 46384732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 46394732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 46404732Sdavemq if (rs != NPI_SUCCESS) { 46414732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 46424732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 46434732Sdavemq "returned error 0x[%x]", rs)); 46444732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 46454732Sdavemq return; 46464732Sdavemq } 46474732Sdavemq 46484732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 46494732Sdavemq } 4650