144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2253560810Ssbehera * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <sys/nxge/nxge_impl.h> 2944961713Sgirish #include <sys/nxge/nxge_mac.h> 3044961713Sgirish 3198ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3298ecde52Stm #define LM_WAIT_MULTIPLIER 8 3398ecde52Stm 34*321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 35*321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 36*321febdeSsbehera 3744961713Sgirish extern uint32_t nxge_no_link_notify; 3859ac0c16Sdavemq extern boolean_t nxge_no_msg; 3944961713Sgirish extern uint32_t nxge_lb_dbg; 4044961713Sgirish extern boolean_t nxge_jumbo_enable; 414202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 4244961713Sgirish 4398ecde52Stm typedef enum { 4498ecde52Stm CHECK_LINK_RESCHEDULE, 4598ecde52Stm CHECK_LINK_STOP 4698ecde52Stm } check_link_state_t; 4798ecde52Stm 4898ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 4998ecde52Stm 5044961713Sgirish /* 5144961713Sgirish * Ethernet broadcast address definition. 5244961713Sgirish */ 5344961713Sgirish static ether_addr_st etherbroadcastaddr = 5444961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 5559ac0c16Sdavemq /* 5659ac0c16Sdavemq * Ethernet zero address definition. 5759ac0c16Sdavemq */ 5856d930aeSspeer static ether_addr_st etherzeroaddr = 5956d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 6059ac0c16Sdavemq /* 6159ac0c16Sdavemq * Supported chip types 6259ac0c16Sdavemq */ 632d17280bSsbehera static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID, BCM8706_DEV_ID}; 6459ac0c16Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 6559ac0c16Sdavemq 6659ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 6759ac0c16Sdavemq sizeof (uint32_t)) 6859ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 6959ac0c16Sdavemq sizeof (uint32_t)) 7059ac0c16Sdavemq /* 7159ac0c16Sdavemq * static functions 7259ac0c16Sdavemq */ 732e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 742e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 752e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 7659ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 772d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 7859ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 7959ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 8059ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 8159ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 8259ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 8359ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 8459ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 8559ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 8659ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 8759ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 8859ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 8959ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 902d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 912d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 9259ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 9359ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 9459ac0c16Sdavemq 9559ac0c16Sdavemq /* 9659ac0c16Sdavemq * xcvr tables for supported transceivers 9759ac0c16Sdavemq */ 9859ac0c16Sdavemq 992e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 10059ac0c16Sdavemq nxge_n2_serdes_init, 10159ac0c16Sdavemq nxge_10G_xcvr_init, 10259ac0c16Sdavemq nxge_10G_link_intr_stop, 10359ac0c16Sdavemq nxge_10G_link_intr_start, 10459ac0c16Sdavemq nxge_check_10g_link, 1052d17280bSsbehera PCS_XCVR 10659ac0c16Sdavemq }; 10759ac0c16Sdavemq 1082e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1092e59129aSraghus nxge_n2_serdes_init, 1102e59129aSraghus nxge_1G_xcvr_init, 1112e59129aSraghus nxge_1G_fiber_link_intr_stop, 1122e59129aSraghus nxge_1G_fiber_link_intr_start, 1132e59129aSraghus nxge_check_mii_link, 1142d17280bSsbehera PCS_XCVR 1152e59129aSraghus }; 1162e59129aSraghus 11759ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 11859ac0c16Sdavemq nxge_neptune_10G_serdes_init, 11959ac0c16Sdavemq nxge_10G_xcvr_init, 12059ac0c16Sdavemq nxge_10G_link_intr_stop, 12159ac0c16Sdavemq nxge_10G_link_intr_start, 12259ac0c16Sdavemq nxge_check_10g_link, 1232d17280bSsbehera PCS_XCVR 12459ac0c16Sdavemq }; 12559ac0c16Sdavemq 12659ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 12759ac0c16Sdavemq NULL, 12859ac0c16Sdavemq nxge_1G_xcvr_init, 12959ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 13059ac0c16Sdavemq nxge_1G_copper_link_intr_start, 13159ac0c16Sdavemq nxge_check_mii_link, 1322d17280bSsbehera INT_MII_XCVR 13359ac0c16Sdavemq }; 13459ac0c16Sdavemq 13559ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 13659ac0c16Sdavemq nxge_1G_serdes_init, 13759ac0c16Sdavemq nxge_1G_xcvr_init, 13859ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 13959ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 14059ac0c16Sdavemq nxge_check_mii_link, 1412d17280bSsbehera PCS_XCVR 14259ac0c16Sdavemq }; 14359ac0c16Sdavemq 14459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 14559ac0c16Sdavemq nxge_neptune_10G_serdes_init, 14659ac0c16Sdavemq NULL, 14759ac0c16Sdavemq NULL, 14859ac0c16Sdavemq NULL, 1492e59129aSraghus NULL, 1502d17280bSsbehera PCS_XCVR 15159ac0c16Sdavemq }; 15244961713Sgirish 15344961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t); 15444961713Sgirish 155d81011f0Ssbehera #ifdef NXGE_DEBUG 156d81011f0Ssbehera static void nxge_mii_dump(p_nxge_t); 157d81011f0Ssbehera #endif 158d81011f0Ssbehera static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 159d81011f0Ssbehera 1602e59129aSraghus nxge_status_t 1612e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 1622e59129aSraghus { 1632e59129aSraghus nxge_status_t status = NXGE_OK; 1642e59129aSraghus char *phy_type; 1652e59129aSraghus char *prop_val; 1662e59129aSraghus 1672e59129aSraghus nxgep->mac.portmode = 0; 1682d17280bSsbehera nxgep->xcvr_addr = 0; 1692e59129aSraghus 1702d17280bSsbehera /* 1712d17280bSsbehera * First check for hot swappable phy property. 1722d17280bSsbehera */ 1732d17280bSsbehera if (nxgep->hot_swappable_phy == B_TRUE) { 1742d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1752d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1762d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 1772d17280bSsbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 1782d17280bSsbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1792d17280bSsbehera "hot-swappable-phy") == 1) { 1802d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1812d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1822d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 1832d17280bSsbehera } else if (nxgep->niu_type == N2_NIU && 1842d17280bSsbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 1852d17280bSsbehera "hot-swappable-phy") == 1) { 1862d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 1872d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 1882d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 1892d17280bSsbehera } 1902d17280bSsbehera 1912d17280bSsbehera /* 1922d17280bSsbehera * MDIO polling support for Monza RTM card, Goa NEM card 1932d17280bSsbehera */ 1942d17280bSsbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 1952d17280bSsbehera 1962d17280bSsbehera uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1972d17280bSsbehera 1982d17280bSsbehera nxgep->hot_swappable_phy = B_TRUE; 1992d17280bSsbehera /* 2002d17280bSsbehera * If this is the 2nd NIU port, then check 2 addresses 2012d17280bSsbehera * to take care of the Goa NEM card. Port 1 can have addr 17 2022d17280bSsbehera * (in the eval board) or 20 (in the P0 board). 2032d17280bSsbehera */ 2042d17280bSsbehera if (portn == 1) { 2052d17280bSsbehera if (nxge_is_phy_present(nxgep, 2062d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR, BCM8706_DEV_ID, 2072d17280bSsbehera BCM_PHY_ID_MASK)) { 2082d17280bSsbehera nxgep->xcvr_addr = 2092d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR; 2102d17280bSsbehera goto found_phy; 2112d17280bSsbehera } 2122d17280bSsbehera } 2132d17280bSsbehera if (nxge_is_phy_present(nxgep, 2142d17280bSsbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 2152d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 2162d17280bSsbehera nxgep->xcvr_addr = (BCM8706_GOA_PORT_ADDR_BASE) + 2172d17280bSsbehera portn; 2182d17280bSsbehera goto found_phy; 2192d17280bSsbehera } 2202d17280bSsbehera 2212d17280bSsbehera nxgep->phy_absent = B_TRUE; 2222d17280bSsbehera goto check_phy_done; 2232d17280bSsbehera found_phy: 2242d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2252d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 2262d17280bSsbehera nxgep->phy_absent = B_FALSE; 2272d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 2282d17280bSsbehera "found for hot swappable phy")); 2292d17280bSsbehera check_phy_done: 2302d17280bSsbehera return (status); 2312d17280bSsbehera } 2322d17280bSsbehera 2332d17280bSsbehera /* Get phy-type property from the driver conf. file */ 2342e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 2352e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2362e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 2372e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2382e59129aSraghus "found conf file: phy-type %s", prop_val)); 2392e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 2402e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2412e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 2422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2432e59129aSraghus "found: 10G Serdes")); 2442e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 2452e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2462e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 2472e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 2482e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 2492e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 2502e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 2512e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 2522e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 2532e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2542e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 2552e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 256*321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 257*321febdeSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 258*321febdeSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 259*321febdeSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G FIBER Xcvr")); 2602e59129aSraghus } 2612e59129aSraghus 2622e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 2632e59129aSraghus "phy-type", prop_val); 2642e59129aSraghus ddi_prop_free(prop_val); 2652e59129aSraghus 2662e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 2672e59129aSraghus "Got phy type [0x%x] from conf file", 2682e59129aSraghus nxgep->mac.portmode)); 2692e59129aSraghus 2702e59129aSraghus return (NXGE_OK); 2712e59129aSraghus } 2722d17280bSsbehera 2732d17280bSsbehera /* Get phy-type property from OBP */ 2742e59129aSraghus if (nxgep->niu_type == N2_NIU) { 2752e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 2762e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 2772e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 2782e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 2792e59129aSraghus XPCS_XCVR; 2802e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 2812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2822e59129aSraghus "10G Fiber Xcvr")); 2832e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 2842e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 2852e59129aSraghus INT_MII_XCVR; 2862e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 2872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2882e59129aSraghus "1G Copper Xcvr")); 2892e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 2902e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 2912e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 2922e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2932e59129aSraghus "1G Fiber Xcvr")); 2942e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 2952e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 2962e59129aSraghus XPCS_XCVR; 2972e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 2982e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2992e59129aSraghus "10G Copper Xcvr")); 3002e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 3012e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3022e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3032e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3042e59129aSraghus "OBP: 10G Serdes")); 3052e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3062e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3072e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3082e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3092e59129aSraghus "OBP: 1G Serdes")); 3102e59129aSraghus } else { 3112e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3122e59129aSraghus "Unknown phy-type: %s", prop_val)); 3132e59129aSraghus ddi_prop_free(prop_val); 3142e59129aSraghus return (NXGE_ERROR); 3152e59129aSraghus } 3162e59129aSraghus status = NXGE_OK; 3172e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3182e59129aSraghus nxgep->dip, "phy-type", prop_val); 3192e59129aSraghus ddi_prop_free(prop_val); 3202e59129aSraghus 3212e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3222e59129aSraghus "Got phy type [0x%x] from OBP", 3232e59129aSraghus nxgep->mac.portmode)); 3242e59129aSraghus 3252e59129aSraghus return (status); 3262e59129aSraghus } else { 3272e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3282e59129aSraghus "Exiting...phy-type property not found")); 3292e59129aSraghus return (NXGE_ERROR); 3302e59129aSraghus } 3312e59129aSraghus } 3322e59129aSraghus 3332e59129aSraghus 3342e59129aSraghus if (!nxgep->vpd_info.present) { 3352e59129aSraghus return (NXGE_OK); 3362e59129aSraghus } 3372e59129aSraghus 3382e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 3392e59129aSraghus goto read_seeprom; 3402e59129aSraghus } 3412e59129aSraghus 3422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3432e59129aSraghus "Reading phy type from expansion ROM")); 3442e59129aSraghus /* 3452e59129aSraghus * Try to read the phy type from the vpd data read off the 3462e59129aSraghus * expansion ROM. 3472e59129aSraghus */ 3482e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 3492e59129aSraghus 350d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 3512e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3522e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 353d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 3542e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 3552e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 356d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 3572e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3582e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 359d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 3602e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 3612e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 362d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 363d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 364d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 365d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 366d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 367d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3682e59129aSraghus } else { 369d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3702e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3712e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 3722e59129aSraghus goto read_seeprom; 3732e59129aSraghus } 3742e59129aSraghus 3752e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 3762e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 3772e59129aSraghus 3782e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3792e59129aSraghus return (status); 3802e59129aSraghus 3812e59129aSraghus read_seeprom: 3822e59129aSraghus /* 3832e59129aSraghus * read the phy type from the SEEPROM - NCR registers 3842e59129aSraghus */ 3852e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 3862e59129aSraghus if (status != NXGE_OK) { 3872e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3882e59129aSraghus "Failed to get phy type")); 3892e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3902e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 3912e59129aSraghus } 3922e59129aSraghus 3932e59129aSraghus return (status); 3942e59129aSraghus 3952e59129aSraghus } 3962e59129aSraghus 39759ac0c16Sdavemq /* Set up the PHY specific values. */ 39859ac0c16Sdavemq 39959ac0c16Sdavemq nxge_status_t 40059ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 40159ac0c16Sdavemq { 40259ac0c16Sdavemq nxge_status_t status = NXGE_OK; 40359ac0c16Sdavemq uint32_t port_type; 40459ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4052e59129aSraghus uint32_t pcs_id = 0; 4062e59129aSraghus uint32_t pma_pmd_id = 0; 4072e59129aSraghus uint32_t phy_id = 0; 4082d17280bSsbehera uint16_t chip_id = 0; 40959ac0c16Sdavemq 41059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 41159ac0c16Sdavemq portn)); 41259ac0c16Sdavemq 4132e59129aSraghus switch (nxgep->niu_type) { 4142e59129aSraghus case N2_NIU: 4152e59129aSraghus switch (nxgep->mac.portmode) { 4162e59129aSraghus case PORT_1G_FIBER: 4172e59129aSraghus case PORT_1G_SERDES: 4182e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 4192d17280bSsbehera nxgep->xcvr_addr = portn; 4202e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 4212e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 4222e59129aSraghus "Serdes")); 4232e59129aSraghus break; 4242e59129aSraghus case PORT_10G_FIBER: 4252e59129aSraghus case PORT_10G_SERDES: 4262e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 4272d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 4282d17280bSsbehera nxgep->xcvr_addr = 4292d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 4302d17280bSsbehera } 4312e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 4322e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 4332e59129aSraghus "Serdes")); 4342e59129aSraghus break; 4352d17280bSsbehera case PORT_HSP_MODE: 4362d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 4372d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 4382d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 4392d17280bSsbehera "Swappable Xcvr (not present)")); 4402d17280bSsbehera break; 4412e59129aSraghus default: 4422e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4432e59129aSraghus "<== nxge_setup_xcvr_table: " 4442e59129aSraghus "Unable to determine NIU portmode")); 4452e59129aSraghus return (NXGE_ERROR); 4462e59129aSraghus } 4472e59129aSraghus break; 4482e59129aSraghus default: 4492e59129aSraghus if (nxgep->mac.portmode == 0) { 4502e59129aSraghus /* 4512e59129aSraghus * Would be the case for platforms like Maramba 4522e59129aSraghus * in which the phy type could not be got from conf 4532e59129aSraghus * file, OBP, VPD or Serial PROM. 4542e59129aSraghus */ 4552e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 4562e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4572e59129aSraghus "<== nxge_setup_xcvr_table:" 4582e59129aSraghus " Invalid Neptune type [0x%x]", 4592e59129aSraghus nxgep->niu_type)); 4602e59129aSraghus return (NXGE_ERROR); 4612e59129aSraghus } 4622e59129aSraghus 4632e59129aSraghus port_type = nxgep->niu_type >> 4642e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 4652e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 4662e59129aSraghus 4672e59129aSraghus switch (port_type) { 4682e59129aSraghus 4692e59129aSraghus case NXGE_PORT_1G_COPPER: 4702e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4712e59129aSraghus break; 4722e59129aSraghus case NXGE_PORT_10G_COPPER: 4732e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 4742e59129aSraghus break; 4752e59129aSraghus case NXGE_PORT_1G_FIBRE: 4762e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4772e59129aSraghus break; 4782e59129aSraghus case NXGE_PORT_10G_FIBRE: 4792e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 4802e59129aSraghus break; 4812e59129aSraghus case NXGE_PORT_1G_SERDES: 4822e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4832e59129aSraghus break; 4842e59129aSraghus case NXGE_PORT_10G_SERDES: 4852e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4862e59129aSraghus break; 4872e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 4882e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 4892e59129aSraghus break; 4902e59129aSraghus default: 4912e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4922e59129aSraghus "<== nxge_setup_xcvr_table: " 4932e59129aSraghus "Unknown port-type: 0x%x", port_type)); 4942e59129aSraghus return (NXGE_ERROR); 4952e59129aSraghus } 4962e59129aSraghus } 4972e59129aSraghus 4982e59129aSraghus switch (nxgep->mac.portmode) { 4992e59129aSraghus case PORT_1G_COPPER: 5002e59129aSraghus case PORT_1G_RGMII_FIBER: 50159ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 5022d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 50359ac0c16Sdavemq /* 50459ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 50559ac0c16Sdavemq * swapped with ethernet port number. This is 5062e59129aSraghus * designed for better signal integrity in 5072e59129aSraghus * routing. This is also the case for the 5082e59129aSraghus * on-board Neptune copper ports on the Maramba 5092e59129aSraghus * platform. 51059ac0c16Sdavemq */ 5112e59129aSraghus switch (nxgep->platform_type) { 5122e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 5132e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 5142e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 5152e59129aSraghus switch (portn) { 5162e59129aSraghus case 0: 5172d17280bSsbehera nxgep->xcvr_addr += 3; 5182e59129aSraghus break; 5192e59129aSraghus case 1: 5202d17280bSsbehera nxgep->xcvr_addr += 1; 5212e59129aSraghus break; 5222e59129aSraghus case 2: 5232d17280bSsbehera nxgep->xcvr_addr -= 1; 5242e59129aSraghus break; 5252e59129aSraghus case 3: 5262d17280bSsbehera nxgep->xcvr_addr -= 3; 5272e59129aSraghus break; 5282e59129aSraghus default: 5292e59129aSraghus return (NXGE_ERROR); 5302e59129aSraghus } 53159ac0c16Sdavemq break; 532d81011f0Ssbehera case P_NEPTUNE_ALONSO: 533d81011f0Ssbehera /* 534d81011f0Ssbehera * The Alonso Neptune, xcvr port numbers for 535d81011f0Ssbehera * ports 2 and 3 are not swapped. Port 2 has 536d81011f0Ssbehera * the BCM5464_PORT_BASE_ADDR and port 3 has 537d81011f0Ssbehera * next address. 538d81011f0Ssbehera */ 5392d17280bSsbehera nxgep->xcvr_addr = 5402d17280bSsbehera BCM5464_NEPTUNE_PORT_ADDR_BASE; 541d81011f0Ssbehera if (portn == 3) { 5422d17280bSsbehera nxgep->xcvr_addr += 1; 543d81011f0Ssbehera } 544d81011f0Ssbehera break; 54559ac0c16Sdavemq default: 5462e59129aSraghus break; 54759ac0c16Sdavemq } 548d81011f0Ssbehera 5492e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5502e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 5512e59129aSraghus "Copper" : "RGMII Fiber")); 55259ac0c16Sdavemq break; 5532e59129aSraghus case PORT_10G_COPPER: 55459ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 55559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 55659ac0c16Sdavemq break; 5572e59129aSraghus case PORT_1G_FIBER: 5582e59129aSraghus case PORT_1G_SERDES: 55959ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 5602d17280bSsbehera nxgep->xcvr_addr = portn; 5612e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 5622e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 5632e59129aSraghus "Fiber" : "Serdes")); 56459ac0c16Sdavemq break; 5652e59129aSraghus case PORT_10G_FIBER: 5662e59129aSraghus case PORT_10G_SERDES: 56759ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 5682d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 5692d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 5702d17280bSsbehera "nxgep->xcvr_addr = [%d]", 5712d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 5722d17280bSsbehera nxgep->xcvr_addr)); 5732d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5742d17280bSsbehera nxgep->xcvr_addr = 5752d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 5762d17280bSsbehera } 5772e59129aSraghus switch (nxgep->platform_type) { 5782e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 5792e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 58059ac0c16Sdavemq /* 58159ac0c16Sdavemq * Switch off LED for corresponding copper 58259ac0c16Sdavemq * port 58359ac0c16Sdavemq */ 58459ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 5852e59129aSraghus break; 5862e59129aSraghus default: 5872e59129aSraghus break; 58859ac0c16Sdavemq } 5892e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 5902e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 5912e59129aSraghus "Fiber" : "Serdes")); 59259ac0c16Sdavemq break; 5932d17280bSsbehera 5942d17280bSsbehera case PORT_HSP_MODE: 5952d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 5962d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 5972d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 5982d17280bSsbehera "Swappable Xcvr (not present)")); 5992d17280bSsbehera break; 60059ac0c16Sdavemq default: 60159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 60259ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 60359ac0c16Sdavemq return (NXGE_ERROR); 60459ac0c16Sdavemq } 60559ac0c16Sdavemq } 60659ac0c16Sdavemq 6072d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 6082d17280bSsbehera if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6092d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 6102d17280bSsbehera &chip_id)) == NXGE_OK) { 6112d17280bSsbehera 6122d17280bSsbehera switch (chip_id) { 6132d17280bSsbehera case BCM8704_CHIP_ID: 6142d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6152d17280bSsbehera "nxge_setup_xcvr_table: " 6162d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 6172d17280bSsbehera chip_id)); 6182d17280bSsbehera break; 6192d17280bSsbehera case BCM8706_CHIP_ID: 6202d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6212d17280bSsbehera "nxge_setup_xcvr_table: " 6222d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 6232d17280bSsbehera chip_id)); 6242d17280bSsbehera break; 6252d17280bSsbehera default: 6262d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6272d17280bSsbehera "nxge_setup_xcvr_table: " 6282d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 6292d17280bSsbehera chip_id)); 6302d17280bSsbehera break; 6312d17280bSsbehera } 6322d17280bSsbehera } 6332d17280bSsbehera } 6342d17280bSsbehera 63559ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 6362d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 6372d17280bSsbehera nxgep->chip_id = chip_id; 6382e59129aSraghus 6392e59129aSraghus /* 6402e59129aSraghus * Get the actual device ID value returned by MDIO read. 6412e59129aSraghus */ 6422e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 6432e59129aSraghus 6442d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 6452e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 6462e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 6472e59129aSraghus } else { 6482d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 6492e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 6502e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 6512e59129aSraghus } else { 6522e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 6532d17280bSsbehera nxgep->xcvr_addr); 6542e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6552e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 6562e59129aSraghus } 6572e59129aSraghus } 6582e59129aSraghus } 6592e59129aSraghus 66059ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 66159ac0c16Sdavemq 6622e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 6632d17280bSsbehera "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type, 6642d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 6652e59129aSraghus 66659ac0c16Sdavemq return (status); 66759ac0c16Sdavemq } 66859ac0c16Sdavemq 66944961713Sgirish /* Initialize the entire MAC and physical layer */ 67044961713Sgirish 67144961713Sgirish nxge_status_t 67244961713Sgirish nxge_mac_init(p_nxge_t nxgep) 67344961713Sgirish { 67444961713Sgirish uint8_t portn; 67544961713Sgirish nxge_status_t status = NXGE_OK; 67644961713Sgirish 67744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 67844961713Sgirish 67944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 68044961713Sgirish 68144961713Sgirish nxgep->mac.portnum = portn; 68244961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 68344961713Sgirish 68444961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 68544961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 68644961713Sgirish 68744961713Sgirish /* Initialize XIF to configure a network mode */ 68844961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 68944961713Sgirish goto fail; 69044961713Sgirish } 69144961713Sgirish 69244961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 69344961713Sgirish goto fail; 69444961713Sgirish } 69544961713Sgirish 69644961713Sgirish /* Initialize TX and RX MACs */ 69744961713Sgirish /* 69844961713Sgirish * Always perform XIF init first, before TX and RX MAC init 69944961713Sgirish */ 70044961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 70144961713Sgirish goto fail; 70244961713Sgirish 70344961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 70444961713Sgirish goto fail; 70544961713Sgirish 70644961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 70744961713Sgirish goto fail; 70844961713Sgirish 70944961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 71044961713Sgirish goto fail; 71144961713Sgirish 71244961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 71344961713Sgirish goto fail; 71444961713Sgirish 71544961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 71644961713Sgirish goto fail; 71744961713Sgirish 718cb9d3ae6Smisaki /* Initialize MAC control configuration */ 719cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 720cb9d3ae6Smisaki goto fail; 721cb9d3ae6Smisaki } 722cb9d3ae6Smisaki 72344961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 72444961713Sgirish 725d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 726d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 727d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 728d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 729d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 730d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 731d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 732d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 733d81011f0Ssbehera goto fail; 734d81011f0Ssbehera } 735d81011f0Ssbehera } 736d81011f0Ssbehera 7372e59129aSraghus 73844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 73944961713Sgirish 74044961713Sgirish return (NXGE_OK); 74144961713Sgirish fail: 74244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 74344961713Sgirish "nxge_mac_init: failed to initialize MAC port<%d>", 74444961713Sgirish portn)); 74544961713Sgirish return (status); 74644961713Sgirish } 74744961713Sgirish 74844961713Sgirish /* Initialize the Ethernet Link */ 74944961713Sgirish 75044961713Sgirish nxge_status_t 75144961713Sgirish nxge_link_init(p_nxge_t nxgep) 75244961713Sgirish { 75344961713Sgirish nxge_status_t status = NXGE_OK; 7542e59129aSraghus nxge_port_mode_t portmode; 75544961713Sgirish #ifdef NXGE_DEBUG 75644961713Sgirish uint8_t portn; 75744961713Sgirish 75844961713Sgirish portn = nxgep->mac.portnum; 75944961713Sgirish 76044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 76144961713Sgirish #endif 7622d17280bSsbehera if (nxgep->hot_swappable_phy && nxgep->phy_absent) { 7632d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: " 7642d17280bSsbehera "Phy not present, cannot initialize link")); 7652d17280bSsbehera return (status); 7662d17280bSsbehera } 76744961713Sgirish 7682e59129aSraghus portmode = nxgep->mac.portmode; 7692d17280bSsbehera 7702e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 7712e59129aSraghus (portmode != PORT_1G_SERDES)) { 77244961713Sgirish /* Workaround to get link up in both NIU ports */ 7732e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 77444961713Sgirish goto fail; 7752e59129aSraghus } 77644961713Sgirish } 77744961713Sgirish NXGE_DELAY(200000); 77844961713Sgirish /* Initialize internal serdes */ 77944961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 78044961713Sgirish goto fail; 78144961713Sgirish NXGE_DELAY(200000); 78244961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 78344961713Sgirish goto fail; 78444961713Sgirish 78544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 78644961713Sgirish 78744961713Sgirish return (NXGE_OK); 78844961713Sgirish 78944961713Sgirish fail: 79044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 79144961713Sgirish "nxge_link_init: ", 79244961713Sgirish "failed to initialize Ethernet link on port<%d>", 79344961713Sgirish portn)); 79444961713Sgirish 79544961713Sgirish return (status); 79644961713Sgirish } 79744961713Sgirish 79844961713Sgirish 79944961713Sgirish /* Initialize the XIF sub-block within the MAC */ 80044961713Sgirish 80144961713Sgirish nxge_status_t 80244961713Sgirish nxge_xif_init(p_nxge_t nxgep) 80344961713Sgirish { 80444961713Sgirish uint32_t xif_cfg = 0; 80544961713Sgirish npi_attr_t ap; 80644961713Sgirish uint8_t portn; 80744961713Sgirish nxge_port_t portt; 80844961713Sgirish nxge_port_mode_t portmode; 80944961713Sgirish p_nxge_stats_t statsp; 81044961713Sgirish npi_status_t rs = NPI_SUCCESS; 81144961713Sgirish npi_handle_t handle; 81244961713Sgirish 81344961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 81444961713Sgirish 81544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 81644961713Sgirish 81744961713Sgirish handle = nxgep->npi_handle; 81844961713Sgirish portmode = nxgep->mac.portmode; 81944961713Sgirish portt = nxgep->mac.porttype; 82044961713Sgirish statsp = nxgep->statsp; 82144961713Sgirish 822d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 823d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 824d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 825d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 826d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 827d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 828d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 829d81011f0Ssbehera } 830d81011f0Ssbehera 83144961713Sgirish if (portt == PORT_TYPE_XMAC) { 83244961713Sgirish 83344961713Sgirish /* Setup XIF Configuration for XMAC */ 83444961713Sgirish 83544961713Sgirish if ((portmode == PORT_10G_FIBER) || 8362e59129aSraghus (portmode == PORT_10G_COPPER) || 8372e59129aSraghus (portmode == PORT_10G_SERDES)) 83844961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 83944961713Sgirish 84044961713Sgirish if (portmode == PORT_1G_COPPER) { 84144961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 84244961713Sgirish } 84344961713Sgirish 84444961713Sgirish /* Set MAC Internal Loopback if necessary */ 84544961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 84644961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 84744961713Sgirish 84844961713Sgirish if (statsp->mac_stats.link_speed == 100) 84944961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 85044961713Sgirish 85144961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 85244961713Sgirish 8532e59129aSraghus if ((portmode == PORT_10G_FIBER) || 8542e59129aSraghus (portmode == PORT_10G_SERDES)) { 85544961713Sgirish if (statsp->mac_stats.link_up) { 85644961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 85744961713Sgirish } else { 85844961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 85944961713Sgirish } 86044961713Sgirish } 86144961713Sgirish 86244961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 86344961713Sgirish if (rs != NPI_SUCCESS) 86444961713Sgirish goto fail; 86544961713Sgirish 86644961713Sgirish nxgep->mac.xif_config = xif_cfg; 86744961713Sgirish 86844961713Sgirish /* Set Port Mode */ 86944961713Sgirish if ((portmode == PORT_10G_FIBER) || 8702e59129aSraghus (portmode == PORT_10G_COPPER) || 8712e59129aSraghus (portmode == PORT_10G_SERDES)) { 87244961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 87344961713Sgirish MAC_XGMII_MODE, rs); 87444961713Sgirish if (rs != NPI_SUCCESS) 87544961713Sgirish goto fail; 87644961713Sgirish if (statsp->mac_stats.link_up) { 87744961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 87844961713Sgirish goto fail; 87944961713Sgirish } else { 88044961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 88144961713Sgirish goto fail; 88244961713Sgirish } 88344961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 8842e59129aSraghus (portmode == PORT_1G_COPPER) || 885d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 886d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 887d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 888d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 889d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 89044961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 89144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 89244961713Sgirish MAC_GMII_MODE, rs); 89344961713Sgirish } else { 89444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 89544961713Sgirish MAC_MII_MODE, rs); 89644961713Sgirish } 89744961713Sgirish if (rs != NPI_SUCCESS) 89844961713Sgirish goto fail; 89944961713Sgirish } else { 90044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 90144961713Sgirish "nxge_xif_init: Unknown port mode (%d)" 90244961713Sgirish " for port<%d>", portmode, portn)); 90344961713Sgirish goto fail; 90444961713Sgirish } 90544961713Sgirish 906d81011f0Ssbehera /* Enable ATCA mode */ 907d81011f0Ssbehera 90844961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 90944961713Sgirish 91044961713Sgirish /* Setup XIF Configuration for BMAC */ 91144961713Sgirish 912d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 913d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 91444961713Sgirish if (statsp->mac_stats.link_speed == 100) 91544961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 91644961713Sgirish } 91744961713Sgirish 91844961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 91944961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 92044961713Sgirish 92144961713Sgirish if (statsp->mac_stats.link_speed == 1000) 92244961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 92344961713Sgirish 92444961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 92544961713Sgirish 92644961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 92744961713Sgirish if (rs != NPI_SUCCESS) 92844961713Sgirish goto fail; 92944961713Sgirish nxgep->mac.xif_config = xif_cfg; 93044961713Sgirish } 93144961713Sgirish 93244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 93344961713Sgirish return (NXGE_OK); 93444961713Sgirish fail: 93544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 93644961713Sgirish "nxge_xif_init: Failed to initialize XIF port<%d>", 93744961713Sgirish portn)); 93844961713Sgirish return (NXGE_ERROR | rs); 93944961713Sgirish } 94044961713Sgirish 94144961713Sgirish /* Initialize the PCS sub-block in the MAC */ 94244961713Sgirish 94344961713Sgirish nxge_status_t 94444961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 94544961713Sgirish { 94644961713Sgirish pcs_cfg_t pcs_cfg; 94744961713Sgirish uint32_t val; 94844961713Sgirish uint8_t portn; 94944961713Sgirish nxge_port_mode_t portmode; 95044961713Sgirish npi_handle_t handle; 95144961713Sgirish p_nxge_stats_t statsp; 95244961713Sgirish npi_status_t rs = NPI_SUCCESS; 95344961713Sgirish 95444961713Sgirish handle = nxgep->npi_handle; 95544961713Sgirish portmode = nxgep->mac.portmode; 95644961713Sgirish portn = nxgep->mac.portnum; 95744961713Sgirish statsp = nxgep->statsp; 95844961713Sgirish 95944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 96044961713Sgirish 9612e59129aSraghus if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 9622e59129aSraghus if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 9632e59129aSraghus goto fail; 9642e59129aSraghus } 9652e59129aSraghus 96644961713Sgirish /* Initialize port's PCS */ 96744961713Sgirish pcs_cfg.value = 0; 96844961713Sgirish pcs_cfg.bits.w0.enable = 1; 96944961713Sgirish pcs_cfg.bits.w0.mask = 1; 97044961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 97144961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 97244961713Sgirish 9732e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9742e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 9752e59129aSraghus portn, pcs_cfg.value)); 97644961713Sgirish } else if ((portmode == PORT_10G_FIBER) || 9772e59129aSraghus (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 97844961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 97944961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 98044961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 98144961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 98244961713Sgirish 98344961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 98444961713Sgirish goto fail; 98544961713Sgirish 98644961713Sgirish /* Set XPCS Internal Loopback if necessary */ 98744961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 98844961713Sgirish XPCS_REG_CONTROL1, &val)) 98944961713Sgirish != NPI_SUCCESS) 99044961713Sgirish goto fail; 99144961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 99244961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 99344961713Sgirish val |= XPCS_CTRL1_LOOPBK; 99444961713Sgirish else 99544961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 99644961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 99744961713Sgirish XPCS_REG_CONTROL1, val)) 99844961713Sgirish != NPI_SUCCESS) 99944961713Sgirish goto fail; 100044961713Sgirish 100144961713Sgirish /* Clear descw errors */ 100244961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 100344961713Sgirish XPCS_REG_DESCWERR_COUNTER, 0)) 100444961713Sgirish != NPI_SUCCESS) 100544961713Sgirish goto fail; 100644961713Sgirish /* Clear symbol errors */ 100744961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 100844961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 100944961713Sgirish != NPI_SUCCESS) 101044961713Sgirish goto fail; 101144961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 101244961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 101344961713Sgirish != NPI_SUCCESS) 101444961713Sgirish goto fail; 101544961713Sgirish 1016d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1017d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1018d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1019d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 102044961713Sgirish if (portn < 4) { 102144961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 102244961713Sgirish PCS_DATAPATH_MODE_MII); 102344961713Sgirish } 102444961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 102544961713Sgirish goto fail; 102644961713Sgirish 102744961713Sgirish } else { 102844961713Sgirish goto fail; 102944961713Sgirish } 103044961713Sgirish pass: 103144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 103244961713Sgirish return (NXGE_OK); 103344961713Sgirish fail: 103444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 103544961713Sgirish "nxge_pcs_init: Failed to initialize PCS port<%d>", 103644961713Sgirish portn)); 103744961713Sgirish return (NXGE_ERROR | rs); 103844961713Sgirish } 103944961713Sgirish 1040cb9d3ae6Smisaki /* 1041cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1042cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1043cb9d3ae6Smisaki */ 1044cb9d3ae6Smisaki nxge_status_t 1045cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1046cb9d3ae6Smisaki { 1047cb9d3ae6Smisaki uint8_t portn; 1048cb9d3ae6Smisaki nxge_port_t portt; 1049cb9d3ae6Smisaki p_nxge_stats_t statsp; 1050cb9d3ae6Smisaki npi_handle_t handle; 1051cb9d3ae6Smisaki uint32_t val; 1052cb9d3ae6Smisaki 1053cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1054cb9d3ae6Smisaki 1055cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1056cb9d3ae6Smisaki portn)); 1057cb9d3ae6Smisaki 1058cb9d3ae6Smisaki handle = nxgep->npi_handle; 1059cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1060cb9d3ae6Smisaki statsp = nxgep->statsp; 1061cb9d3ae6Smisaki 1062cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 1063cb9d3ae6Smisaki /* Readin the current XMAC Config Register for XMAC */ 1064cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1065cb9d3ae6Smisaki 1066cb9d3ae6Smisaki /* 1067cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1068cb9d3ae6Smisaki * XMAC only supports receive-pause 1069cb9d3ae6Smisaki */ 1070cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1071cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1072cb9d3ae6Smisaki /* 1073cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1074cb9d3ae6Smisaki * is 0, enable receive pause. 1075cb9d3ae6Smisaki */ 1076cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1077cb9d3ae6Smisaki } else { 1078cb9d3ae6Smisaki /* 1079cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1080cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1081cb9d3ae6Smisaki * not supported. 1082cb9d3ae6Smisaki */ 1083cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1084cb9d3ae6Smisaki } 1085cb9d3ae6Smisaki } else { 1086cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1087cb9d3ae6Smisaki /* 1088cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1089cb9d3ae6Smisaki * is 1, enable receive pause. 1090cb9d3ae6Smisaki */ 1091cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1092cb9d3ae6Smisaki } else { 1093cb9d3ae6Smisaki /* 1094cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1095cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1096cb9d3ae6Smisaki * not supported 1097cb9d3ae6Smisaki */ 1098cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1099cb9d3ae6Smisaki } 1100cb9d3ae6Smisaki } 1101cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1102cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 1103cb9d3ae6Smisaki /* Readin the current MAC CTRL Config Register for BMAC */ 1104cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1105cb9d3ae6Smisaki 1106cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1107cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1108cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1109cb9d3ae6Smisaki /* 1110cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1111cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1112cb9d3ae6Smisaki * is not supported 1113cb9d3ae6Smisaki */ 1114cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1115cb9d3ae6Smisaki } else { 1116cb9d3ae6Smisaki /* 1117cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1118cb9d3ae6Smisaki * is 0, enable receive pause and disable 1119cb9d3ae6Smisaki * send pause. 1120cb9d3ae6Smisaki */ 1121cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1122cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1123cb9d3ae6Smisaki } 1124cb9d3ae6Smisaki } else { 1125cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1126cb9d3ae6Smisaki /* 1127cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1128cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1129cb9d3ae6Smisaki * not supported. 1130cb9d3ae6Smisaki */ 1131cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1132cb9d3ae6Smisaki } else { 1133cb9d3ae6Smisaki /* 1134cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1135cb9d3ae6Smisaki * is 0, pause capability is not available in 1136cb9d3ae6Smisaki * either direction. 1137cb9d3ae6Smisaki */ 1138cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 1139cb9d3ae6Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1140cb9d3ae6Smisaki } 1141cb9d3ae6Smisaki } 1142cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1143cb9d3ae6Smisaki } 1144cb9d3ae6Smisaki 1145cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1146cb9d3ae6Smisaki portn)); 1147cb9d3ae6Smisaki 1148cb9d3ae6Smisaki return (NXGE_OK); 1149cb9d3ae6Smisaki } 1150cb9d3ae6Smisaki 115144961713Sgirish /* Initialize the Internal Serdes */ 115244961713Sgirish 115344961713Sgirish nxge_status_t 115444961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 115544961713Sgirish { 115644961713Sgirish p_nxge_stats_t statsp; 115744961713Sgirish #ifdef NXGE_DEBUG 115844961713Sgirish uint8_t portn; 115944961713Sgirish #endif 116044961713Sgirish nxge_status_t status = NXGE_OK; 116144961713Sgirish 116244961713Sgirish #ifdef NXGE_DEBUG 116344961713Sgirish portn = nxgep->mac.portnum; 116444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 116559ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 116644961713Sgirish #endif 116744961713Sgirish 116859ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 116959ac0c16Sdavemq statsp = nxgep->statsp; 117059ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 117159ac0c16Sdavemq if (status != NXGE_OK) 117244961713Sgirish goto fail; 117359ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 117444961713Sgirish } 117544961713Sgirish 117644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 117759ac0c16Sdavemq portn)); 117844961713Sgirish 117944961713Sgirish return (NXGE_OK); 118044961713Sgirish 118144961713Sgirish fail: 118244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 118359ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 118459ac0c16Sdavemq portn)); 118544961713Sgirish 118644961713Sgirish return (status); 118744961713Sgirish } 118844961713Sgirish 118944961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 119044961713Sgirish 119159ac0c16Sdavemq static nxge_status_t 119244961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 119344961713Sgirish { 119444961713Sgirish uint8_t portn; 119544961713Sgirish int chan; 119644961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 11972e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 119844961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 119944961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 120044961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 120144961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 12022e59129aSraghus #ifdef NXGE_DEBUG 12032e59129aSraghus esr_ti_testcfg_t cfg; 12042e59129aSraghus #endif 120544961713Sgirish esr_ti_testcfg_t test_cfg; 120644961713Sgirish nxge_status_t status = NXGE_OK; 120744961713Sgirish 120844961713Sgirish portn = nxgep->mac.portnum; 120944961713Sgirish 121044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 121144961713Sgirish portn)); 121244961713Sgirish 121344961713Sgirish tx_cfg_l.value = 0; 121444961713Sgirish tx_cfg_h.value = 0; 121544961713Sgirish rx_cfg_l.value = 0; 121644961713Sgirish rx_cfg_h.value = 0; 121744961713Sgirish pll_cfg_l.value = 0; 12182e59129aSraghus pll_sts_l.value = 0; 121944961713Sgirish test_cfg.value = 0; 122044961713Sgirish 12212e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 12222e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 122344961713Sgirish /* 0x0E01 */ 122444961713Sgirish tx_cfg_l.bits.entx = 1; 122544961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 122644961713Sgirish 122744961713Sgirish /* 0x9101 */ 122844961713Sgirish rx_cfg_l.bits.enrx = 1; 122944961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 123044961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 123144961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 123244961713Sgirish 123344961713Sgirish /* 0x0008 */ 123444961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 123544961713Sgirish 123644961713Sgirish /* Set loopback mode if necessary */ 123744961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 123844961713Sgirish tx_cfg_l.bits.entest = 1; 123944961713Sgirish rx_cfg_l.bits.entest = 1; 124044961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 124144961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 124244961713Sgirish ESR_N2_DEV_ADDR, 124344961713Sgirish ESR_N2_TEST_CFG_REG, test_cfg.value)) 124444961713Sgirish != NXGE_OK) 124544961713Sgirish goto fail; 124644961713Sgirish } 124744961713Sgirish 124844961713Sgirish /* Use default PLL value */ 124944961713Sgirish 12502e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 12512e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 125244961713Sgirish 125344961713Sgirish /* 0x0E21 */ 125444961713Sgirish tx_cfg_l.bits.entx = 1; 125544961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 125644961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 125744961713Sgirish 125844961713Sgirish /* 0x9121 */ 125944961713Sgirish rx_cfg_l.bits.enrx = 1; 126044961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 126144961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 126244961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 126344961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 126444961713Sgirish 12652e59129aSraghus if (portn == 0) { 12662e59129aSraghus /* 0x8 */ 12672e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 12682e59129aSraghus } 126944961713Sgirish 127044961713Sgirish /* MPY = 0x100 */ 127144961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 127244961713Sgirish 127344961713Sgirish /* Set PLL */ 127444961713Sgirish pll_cfg_l.bits.enpll = 1; 12752e59129aSraghus pll_sts_l.bits.enpll = 1; 127644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 127744961713Sgirish ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 127844961713Sgirish != NXGE_OK) 127944961713Sgirish goto fail; 12802e59129aSraghus 12812e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 12822e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 12832e59129aSraghus goto fail; 12842e59129aSraghus 12852e59129aSraghus #ifdef NXGE_DEBUG 12862e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12872e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 12882e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12892e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 12902e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 12912e59129aSraghus 12922e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 12932e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 12942e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12952e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 12962e59129aSraghus portn, pll_sts_l.value, cfg.value)); 12972e59129aSraghus #endif 12982e59129aSraghus 12992e59129aSraghus /* Set loopback mode if necessary */ 13002e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 13012e59129aSraghus tx_cfg_l.bits.entest = 1; 13022e59129aSraghus rx_cfg_l.bits.entest = 1; 13032e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 13042e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13052e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 13062e59129aSraghus portn, test_cfg.value)); 13072e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 13082e59129aSraghus ESR_N2_DEV_ADDR, 13092e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 13102e59129aSraghus goto fail; 13112e59129aSraghus } 13122e59129aSraghus } 131344961713Sgirish } else { 131444961713Sgirish goto fail; 131544961713Sgirish } 131644961713Sgirish 131744961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 131844961713Sgirish 131944961713Sgirish NXGE_DELAY(20); 132044961713Sgirish 132144961713Sgirish /* init TX channels */ 132244961713Sgirish for (chan = 0; chan < 4; chan++) { 132344961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 132444961713Sgirish ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 132544961713Sgirish != NXGE_OK) 132644961713Sgirish goto fail; 132744961713Sgirish 132844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 132944961713Sgirish ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 133044961713Sgirish != NXGE_OK) 133144961713Sgirish goto fail; 13322e59129aSraghus 13332e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13342e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 13352e59129aSraghus portn, chan, tx_cfg_l.value)); 13362e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13372e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 13382e59129aSraghus portn, chan, tx_cfg_h.value)); 133944961713Sgirish } 134044961713Sgirish 134144961713Sgirish /* init RX channels */ 134244961713Sgirish for (chan = 0; chan < 4; chan++) { 134344961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 134444961713Sgirish ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 134544961713Sgirish != NXGE_OK) 134644961713Sgirish goto fail; 134744961713Sgirish 134844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 134944961713Sgirish ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 135044961713Sgirish != NXGE_OK) 135144961713Sgirish goto fail; 13522e59129aSraghus 13532e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13542e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 13552e59129aSraghus portn, chan, rx_cfg_l.value)); 13562e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13572e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 13582e59129aSraghus portn, chan, rx_cfg_h.value)); 135944961713Sgirish } 136044961713Sgirish 136144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 136244961713Sgirish portn)); 136344961713Sgirish 136444961713Sgirish return (NXGE_OK); 136544961713Sgirish fail: 13662d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13672d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 13682d17280bSsbehera portn)); 136944961713Sgirish 137044961713Sgirish return (status); 137144961713Sgirish } 137244961713Sgirish 137359ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 137444961713Sgirish 137559ac0c16Sdavemq static nxge_status_t 137659ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 137744961713Sgirish { 137844961713Sgirish npi_handle_t handle; 137944961713Sgirish uint8_t portn; 1380*321febdeSsbehera int chan, i; 138144961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 138244961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 138344961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 138444961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 138544961713Sgirish uint64_t val; 138644961713Sgirish uint16_t val16l; 138744961713Sgirish uint16_t val16h; 138844961713Sgirish nxge_status_t status = NXGE_OK; 138944961713Sgirish 139044961713Sgirish portn = nxgep->mac.portnum; 139144961713Sgirish 139244961713Sgirish if ((portn != 0) && (portn != 1)) 139344961713Sgirish return (NXGE_OK); 139444961713Sgirish 139559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 139659ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 139744961713Sgirish 139844961713Sgirish handle = nxgep->npi_handle; 139959ac0c16Sdavemq switch (portn) { 140059ac0c16Sdavemq case 0: 14014202ea4bSsbehera /* Reset Serdes */ 14024202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 14034202ea4bSsbehera NXGE_DELAY(20); 14044202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14054202ea4bSsbehera NXGE_DELAY(2000); 14064202ea4bSsbehera 14074202ea4bSsbehera /* Configure Serdes to 10G mode */ 14084202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 14094202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 14104202ea4bSsbehera 141159ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 141259ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 141359ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 141459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 141559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 141659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 141759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 141859ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 141959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 142059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 142159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 142259ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 142359ac0c16Sdavemq 142459ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 142559ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 142659ac0c16Sdavemq ESR_REG_WR(handle, 142759ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 142859ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 142959ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 143059ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 143159ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 143259ac0c16Sdavemq } else { 143359ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 143444961713Sgirish } 143559ac0c16Sdavemq break; 143659ac0c16Sdavemq case 1: 14374202ea4bSsbehera /* Reset Serdes */ 14384202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 14394202ea4bSsbehera NXGE_DELAY(20); 14404202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 14414202ea4bSsbehera NXGE_DELAY(2000); 14424202ea4bSsbehera 14434202ea4bSsbehera /* Configure Serdes to 10G mode */ 14444202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 14454202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 14464202ea4bSsbehera 144759ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 144859ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 144959ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 145059ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 145159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 145259ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 145359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 145459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 145559ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 145659ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 145759ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 145859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 145959ac0c16Sdavemq 146059ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 146159ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 146259ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 146359ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 146459ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 146559ac0c16Sdavemq } else { 146659ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 146744961713Sgirish } 146859ac0c16Sdavemq break; 146959ac0c16Sdavemq default: 147059ac0c16Sdavemq /* Nothing to do here */ 147159ac0c16Sdavemq goto done; 147259ac0c16Sdavemq } 147344961713Sgirish 147459ac0c16Sdavemq /* init TX RX channels */ 147559ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 147659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 147759ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 147859ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 147944961713Sgirish goto fail; 148059ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 148259ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 148344961713Sgirish goto fail; 148459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148559ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 148659ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 148759ac0c16Sdavemq goto fail; 148859ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 148959ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 149059ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 149159ac0c16Sdavemq goto fail; 149259ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 149359ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 149459ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 149559ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 149659ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 149759ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 149859ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 149944961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 150059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 150159ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 150244961713Sgirish goto fail; 150344961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 150459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 150559ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 150644961713Sgirish goto fail; 150759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 150859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 150959ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 151044961713Sgirish goto fail; 151159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 151259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 151359ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 151444961713Sgirish goto fail; 151544961713Sgirish } 151644961713Sgirish 151759ac0c16Sdavemq /* Apply Tx core reset */ 151859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 151959ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 152059ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 152159ac0c16Sdavemq goto fail; 152259ac0c16Sdavemq 152359ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 152459ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 152559ac0c16Sdavemq NXGE_OK) 152659ac0c16Sdavemq goto fail; 152759ac0c16Sdavemq 152859ac0c16Sdavemq NXGE_DELAY(200); 152959ac0c16Sdavemq 153059ac0c16Sdavemq /* Apply Rx core reset */ 153159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 153259ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 153359ac0c16Sdavemq NXGE_OK) 153459ac0c16Sdavemq goto fail; 153559ac0c16Sdavemq 153659ac0c16Sdavemq NXGE_DELAY(200); 153759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 153859ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 153959ac0c16Sdavemq goto fail; 154059ac0c16Sdavemq 154159ac0c16Sdavemq NXGE_DELAY(200); 154259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 154359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 154459ac0c16Sdavemq &val16l)) != NXGE_OK) 154559ac0c16Sdavemq goto fail; 154659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 154759ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 154859ac0c16Sdavemq goto fail; 154959ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 155059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1551d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1552d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 1553d81011f0Ssbehera portn, val16l, val16h)); 155459ac0c16Sdavemq } 155559ac0c16Sdavemq 155659ac0c16Sdavemq if (portn == 0) { 1557*321febdeSsbehera /* Wait for serdes to be ready */ 1558*321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1559*321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1560*321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 1561*321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1562*321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 1563*321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 1564*321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 1565*321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 1566*321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 1567*321febdeSsbehera 1568*321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1569*321febdeSsbehera else 1570*321febdeSsbehera break; 1571*321febdeSsbehera } 1572*321febdeSsbehera 1573*321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1574*321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1575*321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1576*321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 1577*321febdeSsbehera goto fail; 157859ac0c16Sdavemq } 157959ac0c16Sdavemq } else if (portn == 1) { 1580*321febdeSsbehera /* Wait for serdes to be ready */ 1581*321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1582*321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1583*321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 1584*321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1585*321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 1586*321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 1587*321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 1588*321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 1589*321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 1590*321febdeSsbehera 1591*321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1592*321febdeSsbehera else 1593*321febdeSsbehera break; 1594*321febdeSsbehera } 1595*321febdeSsbehera 1596*321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1597*321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1598*321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1599*321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 1600*321febdeSsbehera goto fail; 160144961713Sgirish } 160244961713Sgirish } 160344961713Sgirish 160444961713Sgirish done: 160559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 160659ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 160759ac0c16Sdavemq 160844961713Sgirish return (NXGE_OK); 160944961713Sgirish fail: 16102d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 161159ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 161259ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 161344961713Sgirish 161444961713Sgirish return (status); 161544961713Sgirish } 161644961713Sgirish 161759ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 161844961713Sgirish 161959ac0c16Sdavemq static nxge_status_t 162059ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 162144961713Sgirish { 162259ac0c16Sdavemq npi_handle_t handle; 162359ac0c16Sdavemq uint8_t portn; 1624d81011f0Ssbehera int chan; 1625d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1626d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1627d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 1628d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 162959ac0c16Sdavemq uint64_t val; 1630d81011f0Ssbehera uint16_t val16l; 1631d81011f0Ssbehera uint16_t val16h; 1632d81011f0Ssbehera nxge_status_t status = NXGE_OK; 163344961713Sgirish 163444961713Sgirish portn = nxgep->mac.portnum; 163544961713Sgirish 163659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 163759ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 163844961713Sgirish 163959ac0c16Sdavemq handle = nxgep->npi_handle; 164044961713Sgirish 164159ac0c16Sdavemq switch (portn) { 164259ac0c16Sdavemq case 0: 1643d81011f0Ssbehera /* Assert the reset register */ 1644d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1645d81011f0Ssbehera val |= ESR_RESET_0; 1646d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1647d81011f0Ssbehera 1648d81011f0Ssbehera /* Set the PLL register to 0x79 */ 1649d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1650d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1651d81011f0Ssbehera 1652d81011f0Ssbehera /* Set the control register to 0x249249f */ 1653d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1654d81011f0Ssbehera 1655d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 1656d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1657d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 1658d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1659d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1660d81011f0Ssbehera } else { 1661d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1662d81011f0Ssbehera } 1663d81011f0Ssbehera 1664d81011f0Ssbehera /* Deassert the reset register */ 1665d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1666d81011f0Ssbehera val &= ~ESR_RESET_0; 1667d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 166859ac0c16Sdavemq break; 1669d81011f0Ssbehera 167059ac0c16Sdavemq case 1: 1671d81011f0Ssbehera /* Assert the reset register */ 1672d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1673d81011f0Ssbehera val |= ESR_RESET_1; 1674d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1675d81011f0Ssbehera 1676d81011f0Ssbehera /* Set PLL register to 0x79 */ 1677d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1678d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1679d81011f0Ssbehera 1680d81011f0Ssbehera /* Set the control register to 0x249249f */ 1681d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1682d81011f0Ssbehera 1683d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 1684d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1685d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 1686d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1687d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1688d81011f0Ssbehera } else { 1689d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 1690d81011f0Ssbehera } 1691d81011f0Ssbehera 1692d81011f0Ssbehera /* Deassert the reset register */ 1693d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1694d81011f0Ssbehera val &= ~ESR_RESET_1; 1695d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 169659ac0c16Sdavemq break; 1697d81011f0Ssbehera 169859ac0c16Sdavemq default: 1699d81011f0Ssbehera /* Nothing to do here */ 1700d81011f0Ssbehera goto done; 1701d81011f0Ssbehera } 1702d81011f0Ssbehera 1703d81011f0Ssbehera /* init TX RX channels */ 1704d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 1705d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1706d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1707d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 1708d81011f0Ssbehera goto fail; 1709d81011f0Ssbehera } 1710d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1711d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1712d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 1713d81011f0Ssbehera goto fail; 1714d81011f0Ssbehera } 1715d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1716d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1717d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 1718d81011f0Ssbehera goto fail; 1719d81011f0Ssbehera } 1720d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 1721d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1722d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 1723d81011f0Ssbehera goto fail; 1724d81011f0Ssbehera } 1725d81011f0Ssbehera 1726d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 1727d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 1728d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 1729d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 1730d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 1731d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 1732d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 1733d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1734d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1735d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 1736d81011f0Ssbehera goto fail; 1737d81011f0Ssbehera } 1738d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1739d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1740d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 1741d81011f0Ssbehera goto fail; 1742d81011f0Ssbehera } 1743d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1744d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1745d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 1746d81011f0Ssbehera goto fail; 1747d81011f0Ssbehera } 1748d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 1749d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1750d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 1751d81011f0Ssbehera goto fail; 1752d81011f0Ssbehera } 1753d81011f0Ssbehera } 1754d81011f0Ssbehera 1755d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1756d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 1757d81011f0Ssbehera goto fail; 1758d81011f0Ssbehera } 1759d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1760d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1761d81011f0Ssbehera goto fail; 1762d81011f0Ssbehera } 1763d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1764d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 1765d81011f0Ssbehera goto fail; 1766d81011f0Ssbehera } 1767d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1768d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 176959ac0c16Sdavemq goto fail; 177044961713Sgirish } 177144961713Sgirish 1772d81011f0Ssbehera /* Apply Tx core reset */ 1773d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1774d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 1775d81011f0Ssbehera goto fail; 1776d81011f0Ssbehera } 1777d81011f0Ssbehera 1778d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1779d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 1780d81011f0Ssbehera NXGE_OK) { 1781d81011f0Ssbehera goto fail; 1782d81011f0Ssbehera } 1783d81011f0Ssbehera 1784d81011f0Ssbehera NXGE_DELAY(200); 1785d81011f0Ssbehera 1786d81011f0Ssbehera /* Apply Rx core reset */ 1787d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1788d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 1789d81011f0Ssbehera NXGE_OK) { 1790d81011f0Ssbehera goto fail; 1791d81011f0Ssbehera } 1792d81011f0Ssbehera 1793d81011f0Ssbehera NXGE_DELAY(200); 1794d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1795d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 1796d81011f0Ssbehera goto fail; 1797d81011f0Ssbehera } 1798d81011f0Ssbehera 1799d81011f0Ssbehera NXGE_DELAY(200); 1800d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1801d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 1802d81011f0Ssbehera goto fail; 1803d81011f0Ssbehera } 1804d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1805d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 1806d81011f0Ssbehera goto fail; 1807d81011f0Ssbehera } 1808d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 1809d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1810d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1811d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 1812d81011f0Ssbehera status = NXGE_ERROR; 1813d81011f0Ssbehera goto fail; 1814d81011f0Ssbehera } 1815d81011f0Ssbehera 1816d81011f0Ssbehera NXGE_DELAY(200); 1817d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1818d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1819d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 1820d81011f0Ssbehera "val 0x%x", portn, val)); 1821d81011f0Ssbehera if (portn == 0) { 1822d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 1823d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 1824d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1825d81011f0Ssbehera "nxge_neptune_serdes_init: " 1826d81011f0Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 1827d81011f0Ssbehera portn, (val & ESR_SIG_P0_BITS_MASK))); 1828d81011f0Ssbehera status = NXGE_ERROR; 1829d81011f0Ssbehera goto fail; 1830d81011f0Ssbehera } 1831d81011f0Ssbehera } else if (portn == 1) { 1832d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 1833d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 1834d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1835d81011f0Ssbehera "nxge_neptune_serdes_init: " 1836d81011f0Ssbehera "Failed to get Serdes up for port<%d> val 0x%x", 1837d81011f0Ssbehera portn, (val & ESR_SIG_P1_BITS_MASK))); 1838d81011f0Ssbehera status = NXGE_ERROR; 1839d81011f0Ssbehera goto fail; 1840d81011f0Ssbehera } 1841d81011f0Ssbehera } 1842d81011f0Ssbehera done: 184359ac0c16Sdavemq 184459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 184559ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 184644961713Sgirish return (NXGE_OK); 184759ac0c16Sdavemq fail: 1848d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 184959ac0c16Sdavemq "nxge_1G_serdes_init: " 185059ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 185159ac0c16Sdavemq portn)); 185259ac0c16Sdavemq 1853d81011f0Ssbehera return (status); 185444961713Sgirish } 185544961713Sgirish 18562d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 185744961713Sgirish 185859ac0c16Sdavemq static nxge_status_t 18592d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 186044961713Sgirish { 186144961713Sgirish uint16_t val; 186244961713Sgirish #ifdef NXGE_DEBUG 186314ea4bb7Ssd uint8_t portn; 186444961713Sgirish uint16_t val1; 186544961713Sgirish #endif 186644961713Sgirish uint8_t phy_port_addr; 186744961713Sgirish pmd_tx_control_t tx_ctl; 186844961713Sgirish control_t ctl; 186944961713Sgirish phyxs_control_t phyxs_ctl; 187044961713Sgirish pcs_control_t pcs_ctl; 187144961713Sgirish uint32_t delay = 0; 187244961713Sgirish optics_dcntr_t op_ctr; 187344961713Sgirish nxge_status_t status = NXGE_OK; 187414ea4bb7Ssd #ifdef NXGE_DEBUG 187544961713Sgirish portn = nxgep->mac.portnum; 187614ea4bb7Ssd #endif 18772d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 187859ac0c16Sdavemq portn)); 187944961713Sgirish 188059ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 188159ac0c16Sdavemq 188259ac0c16Sdavemq /* Reset the transceiver */ 188359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 188459ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 188559ac0c16Sdavemq goto fail; 188659ac0c16Sdavemq 188759ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 188859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 188959ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 189059ac0c16Sdavemq goto fail; 189159ac0c16Sdavemq 189259ac0c16Sdavemq do { 189359ac0c16Sdavemq drv_usecwait(500); 189459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 189559ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 189659ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 189759ac0c16Sdavemq goto fail; 189859ac0c16Sdavemq delay++; 189959ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 190059ac0c16Sdavemq if (delay == 100) { 190159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 190259ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 190359ac0c16Sdavemq status = NXGE_ERROR; 190459ac0c16Sdavemq goto fail; 190559ac0c16Sdavemq } 190644961713Sgirish 190759ac0c16Sdavemq /* Set to 0x7FBF */ 190859ac0c16Sdavemq ctl.value = 0; 190959ac0c16Sdavemq ctl.bits.res1 = 0x3F; 191059ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 191159ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 191259ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 191359ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 191459ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 191559ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 191659ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 191759ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 191859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 191959ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 192059ac0c16Sdavemq != NXGE_OK) 192159ac0c16Sdavemq goto fail; 192259ac0c16Sdavemq 192359ac0c16Sdavemq /* Set to 0x164 */ 192459ac0c16Sdavemq tx_ctl.value = 0; 192559ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 192659ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 192759ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 192859ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 192959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 193059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 193159ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 193259ac0c16Sdavemq goto fail; 193344961713Sgirish /* 193459ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 193559ac0c16Sdavemq * back these registers twice after written. 193644961713Sgirish */ 193759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 193859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 193959ac0c16Sdavemq != NXGE_OK) 194059ac0c16Sdavemq goto fail; 194144961713Sgirish 194259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 194359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 194459ac0c16Sdavemq != NXGE_OK) 194559ac0c16Sdavemq goto fail; 194644961713Sgirish 194759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 194859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 194959ac0c16Sdavemq != NXGE_OK) 195059ac0c16Sdavemq goto fail; 195144961713Sgirish 195259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 195359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 195459ac0c16Sdavemq != NXGE_OK) 195559ac0c16Sdavemq goto fail; 195644961713Sgirish 195759ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 195859ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 195959ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 196059ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 196159ac0c16Sdavemq goto fail; 1962cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 1963cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 1964cb9d3ae6Smisaki } else { 1965cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 1966cb9d3ae6Smisaki } 196759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 196859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 196959ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 197059ac0c16Sdavemq goto fail; 197144961713Sgirish 197259ac0c16Sdavemq NXGE_DELAY(1000000); 197344961713Sgirish 197459ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 197559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 197659ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 197759ac0c16Sdavemq != NXGE_OK) 197859ac0c16Sdavemq goto fail; 197959ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 198059ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 198159ac0c16Sdavemq else 198259ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 198359ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 198459ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 198559ac0c16Sdavemq != NXGE_OK) 198659ac0c16Sdavemq goto fail; 198744961713Sgirish 198859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 198959ac0c16Sdavemq if (status != NXGE_OK) 199059ac0c16Sdavemq goto fail; 199159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 199259ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 199359ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 199459ac0c16Sdavemq if (status != NXGE_OK) 199559ac0c16Sdavemq goto fail; 199659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 199759ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 199859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 199959ac0c16Sdavemq if (status != NXGE_OK) 200059ac0c16Sdavemq goto fail; 200159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 200259ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 200344961713Sgirish 200459ac0c16Sdavemq #ifdef NXGE_DEBUG 200559ac0c16Sdavemq /* Diagnose link issue if link is not up */ 200659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 200759ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 200859ac0c16Sdavemq &val); 200959ac0c16Sdavemq if (status != NXGE_OK) 201059ac0c16Sdavemq goto fail; 201144961713Sgirish 201259ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 201344961713Sgirish BCM8704_USER_DEV3_ADDR, 201459ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 201559ac0c16Sdavemq &val); 201659ac0c16Sdavemq if (status != NXGE_OK) 201759ac0c16Sdavemq goto fail; 201844961713Sgirish 201959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 202044961713Sgirish BCM8704_USER_DEV3_ADDR, 202159ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 202259ac0c16Sdavemq &val1); 202359ac0c16Sdavemq if (status != NXGE_OK) 202459ac0c16Sdavemq goto fail; 202544961713Sgirish 202659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 202744961713Sgirish BCM8704_USER_DEV3_ADDR, 202859ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 202959ac0c16Sdavemq &val1); 203059ac0c16Sdavemq if (status != NXGE_OK) 203159ac0c16Sdavemq goto fail; 203244961713Sgirish 203359ac0c16Sdavemq if (val != 0x3FC) { 203459ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 203559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 203659ac0c16Sdavemq "Cable not connected to peer or bad" 203759ac0c16Sdavemq " cable on port<%d>\n", portn)); 203859ac0c16Sdavemq } else if (val == 0x639C) { 203959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 204059ac0c16Sdavemq "Optical module (XFP) is bad or absent" 204159ac0c16Sdavemq " on port<%d>\n", portn)); 204259ac0c16Sdavemq } 204359ac0c16Sdavemq } 204459ac0c16Sdavemq #endif 204544961713Sgirish 20462d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 20472d17280bSsbehera portn)); 20482d17280bSsbehera return (NXGE_OK); 20492d17280bSsbehera 20502d17280bSsbehera fail: 20512d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20522d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 20532d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 20542d17280bSsbehera return (NXGE_ERROR); 20552d17280bSsbehera } 20562d17280bSsbehera 20572d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 20582d17280bSsbehera 20592d17280bSsbehera static nxge_status_t 20602d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 20612d17280bSsbehera { 20622d17280bSsbehera uint8_t phy_port_addr; 20632d17280bSsbehera phyxs_control_t phyxs_ctl; 20642d17280bSsbehera pcs_control_t pcs_ctl; 20652d17280bSsbehera uint32_t delay = 0; 20662d17280bSsbehera optics_dcntr_t op_ctr; 20672d17280bSsbehera nxge_status_t status = NXGE_OK; 20682d17280bSsbehera #ifdef NXGE_DEBUG 20692d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 20702d17280bSsbehera #endif 20712d17280bSsbehera 20722d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 20732d17280bSsbehera portn)); 20742d17280bSsbehera 20752d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 20762d17280bSsbehera 20772d17280bSsbehera /* Reset the transceiver */ 20782d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20792d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 20802d17280bSsbehera goto fail; 20812d17280bSsbehera 20822d17280bSsbehera phyxs_ctl.bits.reset = 1; 20832d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 20842d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 20852d17280bSsbehera goto fail; 20862d17280bSsbehera do { 20872d17280bSsbehera drv_usecwait(500); 20882d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 20892d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 20902d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 20912d17280bSsbehera goto fail; 20922d17280bSsbehera delay++; 20932d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 20942d17280bSsbehera 20952d17280bSsbehera if (delay == 100) { 20962d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 20972d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 20982d17280bSsbehera status = NXGE_ERROR; 20992d17280bSsbehera goto fail; 21002d17280bSsbehera } 21012d17280bSsbehera 21022d17280bSsbehera NXGE_DELAY(1000000); 21032d17280bSsbehera 21042d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 21052d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21062d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 21072d17280bSsbehera != NXGE_OK) 21082d17280bSsbehera goto fail; 21092d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 21102d17280bSsbehera pcs_ctl.bits.loopback = 1; 21112d17280bSsbehera else 21122d17280bSsbehera pcs_ctl.bits.loopback = 0; 21132d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21142d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 21152d17280bSsbehera != NXGE_OK) 21162d17280bSsbehera goto fail; 21172d17280bSsbehera 21182d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 21192d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 21202d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21212d17280bSsbehera &op_ctr.value)) != NXGE_OK) 21222d17280bSsbehera goto fail; 21232d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 21242d17280bSsbehera op_ctr.bits.res2 = 0x1; 21252d17280bSsbehera 21262d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 21272d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 21282d17280bSsbehera op_ctr.value)) != NXGE_OK) 21292d17280bSsbehera goto fail; 21302d17280bSsbehera 21312d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 21322d17280bSsbehera portn)); 21332d17280bSsbehera return (NXGE_OK); 21342d17280bSsbehera 21352d17280bSsbehera fail: 21362d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21372d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 21382d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 21392d17280bSsbehera return (status); 21402d17280bSsbehera } 21412d17280bSsbehera 21422d17280bSsbehera /* Initialize the 10G Transceiver */ 21432d17280bSsbehera 21442d17280bSsbehera static nxge_status_t 21452d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 21462d17280bSsbehera { 21472d17280bSsbehera p_nxge_stats_t statsp; 21482d17280bSsbehera nxge_status_t status = NXGE_OK; 21492d17280bSsbehera #ifdef NXGE_DEBUG 21502d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 21512d17280bSsbehera #endif 21522d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 21532d17280bSsbehera portn)); 21542d17280bSsbehera 21552d17280bSsbehera statsp = nxgep->statsp; 21562d17280bSsbehera 21572d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_SERDES) { 21582d17280bSsbehera goto done; 21592d17280bSsbehera } 21602d17280bSsbehera 21612d17280bSsbehera /* Disable Link LEDs */ 21622d17280bSsbehera if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 21632d17280bSsbehera goto fail; 21642d17280bSsbehera 21652d17280bSsbehera /* Set Clause 45 */ 21662d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 21672d17280bSsbehera 21682d17280bSsbehera switch (nxgep->chip_id) { 21692d17280bSsbehera case BCM8704_CHIP_ID: 21702d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21712d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 21722d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 21732d17280bSsbehera break; 21742d17280bSsbehera case BCM8706_CHIP_ID: 21752d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 21762d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 21772d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 21782d17280bSsbehera break; 21792d17280bSsbehera default: 21802d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 21812d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 21822d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 21832d17280bSsbehera goto fail; 21842d17280bSsbehera } 21852d17280bSsbehera 21862d17280bSsbehera if (status != NXGE_OK) { 21872d17280bSsbehera goto fail; 21882d17280bSsbehera } 21892e59129aSraghus done: 219059ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 219159ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 219244961713Sgirish 219359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 219459ac0c16Sdavemq portn)); 219559ac0c16Sdavemq return (NXGE_OK); 219644961713Sgirish 219759ac0c16Sdavemq fail: 21982d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 219959ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 22002d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 22012d17280bSsbehera return (NXGE_ERROR); 220259ac0c16Sdavemq } 220344961713Sgirish 220459ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 220544961713Sgirish 220659ac0c16Sdavemq static nxge_status_t 220759ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 220859ac0c16Sdavemq { 220959ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 221059ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 221159ac0c16Sdavemq nxge_status_t status = NXGE_OK; 221244961713Sgirish 22132e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 22142e59129aSraghus statsp->mac_stats.cap_1000fdx = 22152e59129aSraghus param_arr[param_anar_1000fdx].value; 22162e59129aSraghus goto done; 22172e59129aSraghus } 22182e59129aSraghus 221959ac0c16Sdavemq /* Set Clause 22 */ 222059ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 222144961713Sgirish 222259ac0c16Sdavemq /* Set capability flags */ 222359ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 22242e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 22252e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 22262e59129aSraghus statsp->mac_stats.cap_100fdx = 22272e59129aSraghus param_arr[param_anar_100fdx].value; 22282e59129aSraghus statsp->mac_stats.cap_10fdx = 22292e59129aSraghus param_arr[param_anar_10fdx].value; 22302e59129aSraghus } 223144961713Sgirish 223259ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 22332e59129aSraghus done: 223459ac0c16Sdavemq return (status); 223559ac0c16Sdavemq } 223659ac0c16Sdavemq 223759ac0c16Sdavemq /* Initialize transceiver */ 223859ac0c16Sdavemq 223959ac0c16Sdavemq nxge_status_t 224059ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 224159ac0c16Sdavemq { 224259ac0c16Sdavemq p_nxge_stats_t statsp; 224359ac0c16Sdavemq #ifdef NXGE_DEBUG 224459ac0c16Sdavemq uint8_t portn; 224544961713Sgirish #endif 224644961713Sgirish 224759ac0c16Sdavemq nxge_status_t status = NXGE_OK; 224859ac0c16Sdavemq #ifdef NXGE_DEBUG 224959ac0c16Sdavemq portn = nxgep->mac.portnum; 225059ac0c16Sdavemq #endif 225159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 225259ac0c16Sdavemq statsp = nxgep->statsp; 225344961713Sgirish 225459ac0c16Sdavemq /* 225559ac0c16Sdavemq * Initialize the xcvr statistics. 225659ac0c16Sdavemq */ 225759ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 225859ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 225959ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 226059ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 226159ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 226259ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 226359ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 226459ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 226559ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 226659ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 226759ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 226859ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 226959ac0c16Sdavemq 227059ac0c16Sdavemq /* 227159ac0c16Sdavemq * Initialize the link statistics. 227259ac0c16Sdavemq */ 227359ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 227459ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 227559ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 227644961713Sgirish 227759ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 227859ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 227959ac0c16Sdavemq if (status != NXGE_OK) 228044961713Sgirish goto fail; 228159ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 228244961713Sgirish } 228344961713Sgirish 228459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 228559ac0c16Sdavemq portn)); 228644961713Sgirish return (NXGE_OK); 228744961713Sgirish 228844961713Sgirish fail: 228944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 229059ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 229159ac0c16Sdavemq portn)); 229244961713Sgirish return (status); 229344961713Sgirish } 229444961713Sgirish 22952e59129aSraghus /* Look for transceiver type */ 22962e59129aSraghus 22972e59129aSraghus nxge_status_t 22982e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 22992e59129aSraghus { 2300d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 2301d81011f0Ssbehera nxgep->mac.portnum)); 23022e59129aSraghus 23032e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 23042e59129aSraghus return (NXGE_ERROR); 23052e59129aSraghus 23062e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 23072e59129aSraghus return (NXGE_ERROR); 23082e59129aSraghus 23092e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 23102e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 23112e59129aSraghus return (NXGE_OK); 23122e59129aSraghus } 231344961713Sgirish 231444961713Sgirish /* Initialize the TxMAC sub-block */ 231544961713Sgirish 231644961713Sgirish nxge_status_t 231744961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 231844961713Sgirish { 231944961713Sgirish npi_attr_t ap; 232044961713Sgirish uint8_t portn; 232144961713Sgirish nxge_port_mode_t portmode; 232244961713Sgirish nxge_port_t portt; 232344961713Sgirish npi_handle_t handle; 232444961713Sgirish npi_status_t rs = NPI_SUCCESS; 232544961713Sgirish 232644961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 232744961713Sgirish portt = nxgep->mac.porttype; 232844961713Sgirish handle = nxgep->npi_handle; 232944961713Sgirish portmode = nxgep->mac.portmode; 233044961713Sgirish 233144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 233244961713Sgirish portn)); 233344961713Sgirish 233444961713Sgirish /* Set Max and Min Frame Size */ 233514ea4bb7Ssd if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 233644961713Sgirish SET_MAC_ATTR2(handle, ap, portn, 23374202ea4bSsbehera MAC_PORT_FRAME_SIZE, 64, nxge_jumbo_mtu, rs); 233844961713Sgirish } else { 23394202ea4bSsbehera /* 23404202ea4bSsbehera * Set the maxframe size to 1522 (1518 + 4) to account for 23414202ea4bSsbehera * VLAN tagged packets 23424202ea4bSsbehera */ 234344961713Sgirish SET_MAC_ATTR2(handle, ap, portn, 23444202ea4bSsbehera MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 234544961713Sgirish } 234644961713Sgirish 234744961713Sgirish if (rs != NPI_SUCCESS) 234844961713Sgirish goto fail; 234914ea4bb7Ssd if (nxgep->param_arr[param_accept_jumbo].value || 235014ea4bb7Ssd nxgep->mac.is_jumbo == B_TRUE) 23514202ea4bSsbehera nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu; 235244961713Sgirish else 235344961713Sgirish nxgep->mac.maxframesize = 0x5EE + 4; 235444961713Sgirish nxgep->mac.minframesize = 64; 235544961713Sgirish 235644961713Sgirish if (portt == PORT_TYPE_XMAC) { 235744961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 235844961713Sgirish 0)) != NPI_SUCCESS) 235944961713Sgirish goto fail; 236044961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 236144961713Sgirish if ((portmode == PORT_10G_FIBER) || 23622e59129aSraghus (portmode == PORT_10G_COPPER) || 23632e59129aSraghus (portmode == PORT_10G_SERDES)) { 236444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 236544961713Sgirish XGMII_IPG_12_15, rs); 236644961713Sgirish if (rs != NPI_SUCCESS) 236744961713Sgirish goto fail; 236844961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 236944961713Sgirish } else { 237044961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 237144961713Sgirish MII_GMII_IPG_12, rs); 237244961713Sgirish if (rs != NPI_SUCCESS) 237344961713Sgirish goto fail; 237444961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 237544961713Sgirish } 237644961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 237744961713Sgirish CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 237844961713Sgirish goto fail; 237944961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 238044961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 238144961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 238244961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 238344961713Sgirish 238444961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 238544961713Sgirish != NPI_SUCCESS) 238644961713Sgirish goto fail; 238744961713Sgirish 238844961713Sgirish } else { 238944961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 239044961713Sgirish 0)) != NPI_SUCCESS) 239144961713Sgirish goto fail; 239244961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 239344961713Sgirish 239444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 239544961713Sgirish rs); 239644961713Sgirish if (rs != NPI_SUCCESS) 239744961713Sgirish goto fail; 239844961713Sgirish nxgep->mac.ctrltype = 0x8808; 239944961713Sgirish 240044961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 240144961713Sgirish if (rs != NPI_SUCCESS) 240244961713Sgirish goto fail; 240344961713Sgirish nxgep->mac.pa_size = 0x7; 240444961713Sgirish 240544961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 240644961713Sgirish CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 240744961713Sgirish goto fail; 240844961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 240944961713Sgirish } 241044961713Sgirish 241144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 241244961713Sgirish portn)); 241344961713Sgirish 241444961713Sgirish return (NXGE_OK); 241544961713Sgirish fail: 241644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 241744961713Sgirish "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 241844961713Sgirish portn)); 241944961713Sgirish 242044961713Sgirish return (NXGE_ERROR | rs); 242144961713Sgirish } 242244961713Sgirish 242344961713Sgirish /* Initialize the RxMAC sub-block */ 242444961713Sgirish 242544961713Sgirish nxge_status_t 242644961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 242744961713Sgirish { 242844961713Sgirish npi_attr_t ap; 242944961713Sgirish uint32_t i; 243044961713Sgirish uint16_t hashtab_e; 243144961713Sgirish p_hash_filter_t hash_filter; 243244961713Sgirish nxge_port_t portt; 243344961713Sgirish uint8_t portn; 243444961713Sgirish npi_handle_t handle; 243544961713Sgirish npi_status_t rs = NPI_SUCCESS; 243644961713Sgirish uint16_t *addr16p; 243744961713Sgirish uint16_t addr0, addr1, addr2; 243844961713Sgirish xmac_rx_config_t xconfig; 243944961713Sgirish bmac_rx_config_t bconfig; 244044961713Sgirish 244144961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 244244961713Sgirish 244344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 244444961713Sgirish portn)); 244544961713Sgirish handle = nxgep->npi_handle; 244644961713Sgirish portt = nxgep->mac.porttype; 244744961713Sgirish 244844961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 244944961713Sgirish addr0 = ntohs(addr16p[2]); 245044961713Sgirish addr1 = ntohs(addr16p[1]); 245144961713Sgirish addr2 = ntohs(addr16p[0]); 245244961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 245344961713Sgirish rs); 245444961713Sgirish 245544961713Sgirish if (rs != NPI_SUCCESS) 245644961713Sgirish goto fail; 245744961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 245844961713Sgirish if (rs != NPI_SUCCESS) 245944961713Sgirish goto fail; 246044961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 246144961713Sgirish if (rs != NPI_SUCCESS) 246244961713Sgirish goto fail; 246344961713Sgirish 246444961713Sgirish /* 246544961713Sgirish * Load the multicast hash filter bits. 246644961713Sgirish */ 246744961713Sgirish hash_filter = nxgep->hash_filter; 246844961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 246944961713Sgirish if (hash_filter != NULL) { 247044961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 247144961713Sgirish (NMCFILTER_REGS - 1) - i]; 247244961713Sgirish } else { 247344961713Sgirish hashtab_e = 0; 247444961713Sgirish } 247544961713Sgirish 247644961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 247744961713Sgirish (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 247844961713Sgirish goto fail; 247944961713Sgirish } 248044961713Sgirish 248144961713Sgirish if (portt == PORT_TYPE_XMAC) { 248244961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 248344961713Sgirish 0)) != NPI_SUCCESS) 248444961713Sgirish goto fail; 248544961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 248644961713Sgirish 248744961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 248844961713Sgirish 248944961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 2490a3c5bd6dSspeer CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 2491a3c5bd6dSspeer ~CFG_XMAC_RX_STRIP_CRC; 249244961713Sgirish 249344961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 249444961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 249544961713Sgirish 249644961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 249744961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 249844961713Sgirish 249944961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 250044961713Sgirish 250144961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 250244961713Sgirish xconfig)) != NPI_SUCCESS) 250344961713Sgirish goto fail; 250444961713Sgirish nxgep->mac.rx_config = xconfig; 250544961713Sgirish 250644961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 250744961713Sgirish 250844961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 250944961713Sgirish != NPI_SUCCESS) 251044961713Sgirish goto fail; 251144961713Sgirish } else { 251244961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 251344961713Sgirish 251444961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 251544961713Sgirish 0) != NPI_SUCCESS) 251644961713Sgirish goto fail; 251744961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 251844961713Sgirish 2519a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 2520a3c5bd6dSspeer ~CFG_BMAC_RX_STRIP_CRC; 252144961713Sgirish 252244961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 252344961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 252444961713Sgirish 252544961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 252644961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 252744961713Sgirish 252844961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 252944961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 253044961713Sgirish bconfig)) != NPI_SUCCESS) 253144961713Sgirish goto fail; 253244961713Sgirish nxgep->mac.rx_config = bconfig; 253344961713Sgirish 253444961713Sgirish /* Always enable comparison of mac unique address */ 253544961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 253644961713Sgirish != NPI_SUCCESS) 253744961713Sgirish goto fail; 253844961713Sgirish } 253944961713Sgirish 254044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 254144961713Sgirish portn)); 254244961713Sgirish 254344961713Sgirish return (NXGE_OK); 254444961713Sgirish 254544961713Sgirish fail: 254644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 254744961713Sgirish "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 254844961713Sgirish portn)); 254944961713Sgirish 255044961713Sgirish return (NXGE_ERROR | rs); 255144961713Sgirish } 255244961713Sgirish 255344961713Sgirish /* Enable TXMAC */ 255444961713Sgirish 255544961713Sgirish nxge_status_t 255644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 255744961713Sgirish { 255844961713Sgirish npi_handle_t handle; 255944961713Sgirish npi_status_t rs = NPI_SUCCESS; 256044961713Sgirish nxge_status_t status = NXGE_OK; 256144961713Sgirish 256244961713Sgirish handle = nxgep->npi_handle; 256344961713Sgirish 256444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 256544961713Sgirish nxgep->mac.portnum)); 256644961713Sgirish 256744961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 256844961713Sgirish goto fail; 256944961713Sgirish 257044961713Sgirish /* based on speed */ 257144961713Sgirish nxgep->msg_min = ETHERMIN; 257244961713Sgirish 257344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 257444961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 257544961713Sgirish CFG_XMAC_TX)) != NPI_SUCCESS) 257644961713Sgirish goto fail; 257744961713Sgirish } else { 257844961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 257944961713Sgirish CFG_BMAC_TX)) != NPI_SUCCESS) 258044961713Sgirish goto fail; 258144961713Sgirish } 258244961713Sgirish 258344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 258444961713Sgirish nxgep->mac.portnum)); 258544961713Sgirish 258644961713Sgirish return (NXGE_OK); 258744961713Sgirish fail: 258844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 258944961713Sgirish "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 259044961713Sgirish nxgep->mac.portnum)); 259144961713Sgirish if (rs != NPI_SUCCESS) 259244961713Sgirish return (NXGE_ERROR | rs); 259344961713Sgirish else 259444961713Sgirish return (status); 259544961713Sgirish } 259644961713Sgirish 259744961713Sgirish /* Disable TXMAC */ 259844961713Sgirish 259944961713Sgirish nxge_status_t 260044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 260144961713Sgirish { 260244961713Sgirish npi_handle_t handle; 260344961713Sgirish npi_status_t rs = NPI_SUCCESS; 260444961713Sgirish 260544961713Sgirish handle = nxgep->npi_handle; 260644961713Sgirish 260744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 260844961713Sgirish nxgep->mac.portnum)); 260944961713Sgirish 261044961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 261144961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 261244961713Sgirish nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 261344961713Sgirish goto fail; 261444961713Sgirish } else { 261544961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 261644961713Sgirish nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 261744961713Sgirish goto fail; 261844961713Sgirish } 261944961713Sgirish 262044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 262144961713Sgirish nxgep->mac.portnum)); 262244961713Sgirish return (NXGE_OK); 262344961713Sgirish fail: 262444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 262544961713Sgirish "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 262644961713Sgirish nxgep->mac.portnum)); 262744961713Sgirish return (NXGE_ERROR | rs); 262844961713Sgirish } 262944961713Sgirish 263044961713Sgirish /* Enable RXMAC */ 263144961713Sgirish 263244961713Sgirish nxge_status_t 263344961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 263444961713Sgirish { 263544961713Sgirish npi_handle_t handle; 263644961713Sgirish uint8_t portn; 263744961713Sgirish npi_status_t rs = NPI_SUCCESS; 263844961713Sgirish nxge_status_t status = NXGE_OK; 263944961713Sgirish 264044961713Sgirish handle = nxgep->npi_handle; 264144961713Sgirish portn = nxgep->mac.portnum; 264244961713Sgirish 264344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 264444961713Sgirish portn)); 264544961713Sgirish 264644961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 264744961713Sgirish goto fail; 264844961713Sgirish 264944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 265044961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 265144961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 265244961713Sgirish goto fail; 265344961713Sgirish } else { 265444961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 265544961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 265644961713Sgirish goto fail; 265744961713Sgirish } 265844961713Sgirish 265944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 266044961713Sgirish portn)); 266144961713Sgirish 266244961713Sgirish return (NXGE_OK); 266344961713Sgirish fail: 266444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 266544961713Sgirish "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 266644961713Sgirish portn)); 266744961713Sgirish 266844961713Sgirish if (rs != NPI_SUCCESS) 266944961713Sgirish return (NXGE_ERROR | rs); 267044961713Sgirish else 267144961713Sgirish return (status); 267244961713Sgirish } 267344961713Sgirish 267444961713Sgirish /* Disable RXMAC */ 267544961713Sgirish 267644961713Sgirish nxge_status_t 267744961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 267844961713Sgirish { 267944961713Sgirish npi_handle_t handle; 268044961713Sgirish uint8_t portn; 268144961713Sgirish npi_status_t rs = NPI_SUCCESS; 268244961713Sgirish 268344961713Sgirish handle = nxgep->npi_handle; 268444961713Sgirish portn = nxgep->mac.portnum; 268544961713Sgirish 268644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 268744961713Sgirish portn)); 268844961713Sgirish 268944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 269044961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 269144961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 269244961713Sgirish goto fail; 269344961713Sgirish } else { 269444961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 269544961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 269644961713Sgirish goto fail; 269744961713Sgirish } 269844961713Sgirish 269944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 270044961713Sgirish portn)); 270144961713Sgirish return (NXGE_OK); 270244961713Sgirish fail: 270344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 270444961713Sgirish "nxgep_rx_mac_disable: ", 270544961713Sgirish "Failed to disable port<%d> RxMAC", 270644961713Sgirish portn)); 270744961713Sgirish 270844961713Sgirish return (NXGE_ERROR | rs); 270944961713Sgirish } 271044961713Sgirish 271144961713Sgirish /* Reset TXMAC */ 271244961713Sgirish 271344961713Sgirish nxge_status_t 271444961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 271544961713Sgirish { 271644961713Sgirish npi_handle_t handle; 271744961713Sgirish uint8_t portn; 271844961713Sgirish npi_status_t rs = NPI_SUCCESS; 271944961713Sgirish 272044961713Sgirish handle = nxgep->npi_handle; 272144961713Sgirish portn = nxgep->mac.portnum; 272244961713Sgirish 272344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 272444961713Sgirish portn)); 272544961713Sgirish 272644961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 272744961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 272844961713Sgirish != NPI_SUCCESS) 272944961713Sgirish goto fail; 273044961713Sgirish } else { 273144961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 273244961713Sgirish != NPI_SUCCESS) 273344961713Sgirish goto fail; 273444961713Sgirish } 273544961713Sgirish 273644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 273744961713Sgirish portn)); 273844961713Sgirish 273944961713Sgirish return (NXGE_OK); 274044961713Sgirish fail: 274144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 274244961713Sgirish "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 274344961713Sgirish portn)); 274444961713Sgirish 274544961713Sgirish return (NXGE_ERROR | rs); 274644961713Sgirish } 274744961713Sgirish 274844961713Sgirish /* Reset RXMAC */ 274944961713Sgirish 275044961713Sgirish nxge_status_t 275144961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 275244961713Sgirish { 275344961713Sgirish npi_handle_t handle; 275444961713Sgirish uint8_t portn; 275544961713Sgirish npi_status_t rs = NPI_SUCCESS; 275644961713Sgirish 275744961713Sgirish handle = nxgep->npi_handle; 275844961713Sgirish portn = nxgep->mac.portnum; 275944961713Sgirish 276044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 276144961713Sgirish portn)); 276244961713Sgirish 276344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 276444961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 276544961713Sgirish != NPI_SUCCESS) 276644961713Sgirish goto fail; 276744961713Sgirish } else { 276844961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 276944961713Sgirish != NPI_SUCCESS) 277044961713Sgirish goto fail; 277144961713Sgirish } 277244961713Sgirish 277344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 277444961713Sgirish portn)); 277544961713Sgirish 277659ac0c16Sdavemq return (NXGE_OK); 277759ac0c16Sdavemq fail: 277859ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 277959ac0c16Sdavemq "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 278059ac0c16Sdavemq portn)); 278159ac0c16Sdavemq return (NXGE_ERROR | rs); 278259ac0c16Sdavemq } 278359ac0c16Sdavemq 278459ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 278559ac0c16Sdavemq 278659ac0c16Sdavemq static nxge_status_t 278759ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 278859ac0c16Sdavemq { 278959ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 279059ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 279159ac0c16Sdavemq 279259ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 279359ac0c16Sdavemq 279459ac0c16Sdavemq if (rs != NPI_SUCCESS) 279559ac0c16Sdavemq return (NXGE_ERROR | rs); 279659ac0c16Sdavemq else 279759ac0c16Sdavemq return (NXGE_OK); 279859ac0c16Sdavemq } 279959ac0c16Sdavemq 280059ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 280159ac0c16Sdavemq 280259ac0c16Sdavemq static nxge_status_t 280359ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 280459ac0c16Sdavemq { 280559ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 280659ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 280759ac0c16Sdavemq 280859ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 280959ac0c16Sdavemq 281059ac0c16Sdavemq if (rs != NPI_SUCCESS) 281159ac0c16Sdavemq return (NXGE_ERROR | rs); 281259ac0c16Sdavemq else 281359ac0c16Sdavemq return (NXGE_OK); 281459ac0c16Sdavemq } 281559ac0c16Sdavemq 281659ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 281759ac0c16Sdavemq 281859ac0c16Sdavemq static nxge_status_t 281959ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 282059ac0c16Sdavemq { 282159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 282259ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 282359ac0c16Sdavemq 282459ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 282559ac0c16Sdavemq if (rs != NPI_SUCCESS) 282659ac0c16Sdavemq return (NXGE_ERROR | rs); 282759ac0c16Sdavemq else 282859ac0c16Sdavemq return (NXGE_OK); 282959ac0c16Sdavemq } 283059ac0c16Sdavemq 283159ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 283259ac0c16Sdavemq 283359ac0c16Sdavemq static nxge_status_t 283459ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 283559ac0c16Sdavemq { 283659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 283759ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 283859ac0c16Sdavemq 283959ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 284059ac0c16Sdavemq 284159ac0c16Sdavemq if (rs != NPI_SUCCESS) 284259ac0c16Sdavemq return (NXGE_ERROR | rs); 284359ac0c16Sdavemq else 284459ac0c16Sdavemq return (NXGE_OK); 284559ac0c16Sdavemq } 284659ac0c16Sdavemq 284759ac0c16Sdavemq /* 1G copper link interrupt start routine */ 284859ac0c16Sdavemq 284959ac0c16Sdavemq static nxge_status_t 285059ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 285159ac0c16Sdavemq { 285259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 285359ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 285459ac0c16Sdavemq 285559ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 28566b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 285759ac0c16Sdavemq 285859ac0c16Sdavemq if (rs != NPI_SUCCESS) 285959ac0c16Sdavemq return (NXGE_ERROR | rs); 286059ac0c16Sdavemq else 286159ac0c16Sdavemq return (NXGE_OK); 286244961713Sgirish } 286344961713Sgirish 286459ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 286559ac0c16Sdavemq 286659ac0c16Sdavemq static nxge_status_t 286759ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 286859ac0c16Sdavemq { 286959ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 287059ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 287159ac0c16Sdavemq 287259ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 287359ac0c16Sdavemq 287459ac0c16Sdavemq if (rs != NPI_SUCCESS) 287559ac0c16Sdavemq return (NXGE_ERROR | rs); 287659ac0c16Sdavemq else 287759ac0c16Sdavemq return (NXGE_OK); 287859ac0c16Sdavemq } 287944961713Sgirish 288059ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 288144961713Sgirish 288244961713Sgirish nxge_status_t 288344961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 288444961713Sgirish { 288559ac0c16Sdavemq uint8_t portn; 288659ac0c16Sdavemq nxge_status_t status = NXGE_OK; 288744961713Sgirish 288844961713Sgirish portn = nxgep->mac.portnum; 288944961713Sgirish 289044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 289159ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 289259ac0c16Sdavemq return (NXGE_OK); 289344961713Sgirish 289459ac0c16Sdavemq if (enable == LINK_INTR_START) 289559ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 289659ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 289759ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 289859ac0c16Sdavemq if (status != NXGE_OK) 289959ac0c16Sdavemq goto fail; 290044961713Sgirish 290144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 290244961713Sgirish 290344961713Sgirish return (NXGE_OK); 290444961713Sgirish fail: 290544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 290644961713Sgirish "nxge_link_intr: Failed to set port<%d> mif intr mode", 290744961713Sgirish portn)); 290844961713Sgirish 290959ac0c16Sdavemq return (status); 291044961713Sgirish } 291144961713Sgirish 291244961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 291344961713Sgirish 291444961713Sgirish nxge_status_t 291544961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 291644961713Sgirish { 291744961713Sgirish p_nxge_param_t param_arr; 291844961713Sgirish p_nxge_stats_t statsp; 291944961713Sgirish uint8_t xcvr_portn; 292044961713Sgirish p_mii_regs_t mii_regs; 292144961713Sgirish mii_bmcr_t bmcr; 292244961713Sgirish mii_bmsr_t bmsr; 292344961713Sgirish mii_anar_t anar; 292444961713Sgirish mii_gcr_t gcr; 292544961713Sgirish mii_esr_t esr; 292644961713Sgirish mii_aux_ctl_t bcm5464r_aux; 292744961713Sgirish int status = NXGE_OK; 292844961713Sgirish 292944961713Sgirish uint_t delay; 293044961713Sgirish 293144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 293244961713Sgirish 293344961713Sgirish param_arr = nxgep->param_arr; 293444961713Sgirish statsp = nxgep->statsp; 293544961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 293644961713Sgirish 293744961713Sgirish mii_regs = NULL; 293844961713Sgirish 293944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 294044961713Sgirish "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 294144961713Sgirish 2942d81011f0Ssbehera /* 2943d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 2944d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 2945d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 2946d81011f0Ssbehera */ 2947d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 2948d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 2949d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 2950d81011f0Ssbehera } 2951d81011f0Ssbehera 295244961713Sgirish /* 295344961713Sgirish * Reset the transceiver. 295444961713Sgirish */ 295544961713Sgirish delay = 0; 295644961713Sgirish bmcr.value = 0; 295744961713Sgirish bmcr.bits.reset = 1; 295844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 2959adfcba55Sjoycey #if defined(__i386) 2960adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2961adfcba55Sjoycey #else 296244961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2963adfcba55Sjoycey #endif 296444961713Sgirish goto fail; 296544961713Sgirish do { 296644961713Sgirish drv_usecwait(500); 296744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 2968adfcba55Sjoycey #if defined(__i386) 2969adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 2970adfcba55Sjoycey #else 297144961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 2972adfcba55Sjoycey #endif 297344961713Sgirish != NXGE_OK) 297444961713Sgirish goto fail; 297544961713Sgirish delay++; 297644961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 297744961713Sgirish if (delay == 1000) { 297844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 297944961713Sgirish goto fail; 298044961713Sgirish } 298144961713Sgirish 298244961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 2983adfcba55Sjoycey #if defined(__i386) 2984adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 2985adfcba55Sjoycey #else 298644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 2987adfcba55Sjoycey #endif 298844961713Sgirish &bmsr.value)) != NXGE_OK) 298944961713Sgirish goto fail; 299044961713Sgirish 299144961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 299244961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 299344961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 299444961713Sgirish param_arr[param_anar_100hdx].value = 0; 299544961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 299644961713Sgirish param_arr[param_anar_10hdx].value = 0; 299744961713Sgirish 299844961713Sgirish /* 299958324dfcSspeer * Initialize the xcvr statistics. 300044961713Sgirish */ 300144961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 300244961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 300344961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 300444961713Sgirish statsp->mac_stats.cap_100hdx = 0; 300544961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 300644961713Sgirish statsp->mac_stats.cap_10hdx = 0; 300744961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 300844961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 300944961713Sgirish 301044961713Sgirish /* 301144961713Sgirish * Initialise the xcvr advertised capability statistics. 301244961713Sgirish */ 301344961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 301444961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 301544961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 301644961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 301744961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 301844961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 301944961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 302044961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 302144961713Sgirish statsp->mac_stats.adv_cap_asmpause = 302244961713Sgirish param_arr[param_anar_asmpause].value; 302344961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 302444961713Sgirish 302544961713Sgirish 302644961713Sgirish /* 302744961713Sgirish * Check for extended status just in case we're 302844961713Sgirish * running a Gigibit phy. 302944961713Sgirish */ 303044961713Sgirish if (bmsr.bits.extend_status) { 303144961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3032adfcba55Sjoycey #if defined(__i386) 3033adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 3034adfcba55Sjoycey #else 303544961713Sgirish (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 3036adfcba55Sjoycey #endif 303744961713Sgirish != NXGE_OK) 303844961713Sgirish goto fail; 303944961713Sgirish param_arr[param_anar_1000fdx].value &= 304044961713Sgirish esr.bits.link_1000fdx; 304144961713Sgirish param_arr[param_anar_1000hdx].value = 0; 304244961713Sgirish 304344961713Sgirish statsp->mac_stats.cap_1000fdx = 304444961713Sgirish (esr.bits.link_1000Xfdx || 304544961713Sgirish esr.bits.link_1000fdx); 304644961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 304744961713Sgirish } else { 304844961713Sgirish param_arr[param_anar_1000fdx].value = 0; 304944961713Sgirish param_arr[param_anar_1000hdx].value = 0; 305044961713Sgirish } 305144961713Sgirish 305244961713Sgirish /* 305344961713Sgirish * Initialize 1G Statistics once the capability is established. 305444961713Sgirish */ 305544961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 305644961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 305744961713Sgirish 305844961713Sgirish /* 305944961713Sgirish * Initialise the link statistics. 306044961713Sgirish */ 306144961713Sgirish statsp->mac_stats.link_T4 = 0; 306244961713Sgirish statsp->mac_stats.link_asmpause = 0; 306344961713Sgirish statsp->mac_stats.link_pause = 0; 306444961713Sgirish statsp->mac_stats.link_speed = 0; 306544961713Sgirish statsp->mac_stats.link_duplex = 0; 306644961713Sgirish statsp->mac_stats.link_up = 0; 306744961713Sgirish 306844961713Sgirish /* 306944961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 307044961713Sgirish */ 307144961713Sgirish bmcr.value = 0; 307244961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3073adfcba55Sjoycey #if defined(__i386) 3074adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3075adfcba55Sjoycey #else 307644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3077adfcba55Sjoycey #endif 307844961713Sgirish goto fail; 307944961713Sgirish 308044961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 308144961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 308244961713Sgirish bmcr.bits.loopback = 1; 308344961713Sgirish bmcr.bits.enable_autoneg = 0; 308444961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 308544961713Sgirish bmcr.bits.speed_1000_sel = 1; 308644961713Sgirish bmcr.bits.duplex_mode = 1; 308744961713Sgirish param_arr[param_autoneg].value = 0; 308844961713Sgirish } else { 308944961713Sgirish bmcr.bits.loopback = 0; 309044961713Sgirish } 309144961713Sgirish 309244961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 309344961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 309444961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 309544961713Sgirish param_arr[param_autoneg].value = 0; 309644961713Sgirish bcm5464r_aux.value = 0; 309744961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 309844961713Sgirish bcm5464r_aux.bits.write_1 = 1; 309944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 310044961713Sgirish BCM5464R_AUX_CTL, bcm5464r_aux.value)) 310144961713Sgirish != NXGE_OK) 310244961713Sgirish goto fail; 310344961713Sgirish } 310444961713Sgirish 310544961713Sgirish if (param_arr[param_autoneg].value) { 310644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 310744961713Sgirish "Restarting Auto-negotiation.")); 310844961713Sgirish /* 310944961713Sgirish * Setup our Auto-negotiation advertisement register. 311044961713Sgirish */ 311144961713Sgirish anar.value = 0; 311244961713Sgirish anar.bits.selector = 1; 311344961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 311444961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 311544961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 311644961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 311744961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 311844961713Sgirish anar.bits.cap_asmpause = 0; 311944961713Sgirish anar.bits.cap_pause = 0; 312044961713Sgirish if (param_arr[param_anar_1000fdx].value || 312144961713Sgirish param_arr[param_anar_100fdx].value || 312244961713Sgirish param_arr[param_anar_10fdx].value) { 312344961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 312444961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 312544961713Sgirish } 312644961713Sgirish 312744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3128adfcba55Sjoycey #if defined(__i386) 3129adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 3130adfcba55Sjoycey #else 313144961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 3132adfcba55Sjoycey #endif 313344961713Sgirish != NXGE_OK) 313444961713Sgirish goto fail; 313544961713Sgirish if (bmsr.bits.extend_status) { 313644961713Sgirish gcr.value = 0; 313744961713Sgirish gcr.bits.ms_mode_en = 313844961713Sgirish param_arr[param_master_cfg_enable].value; 313944961713Sgirish gcr.bits.master = 314044961713Sgirish param_arr[param_master_cfg_value].value; 314144961713Sgirish gcr.bits.link_1000fdx = 314244961713Sgirish param_arr[param_anar_1000fdx].value; 314344961713Sgirish gcr.bits.link_1000hdx = 314444961713Sgirish param_arr[param_anar_1000hdx].value; 314544961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3146adfcba55Sjoycey #if defined(__i386) 3147adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 3148adfcba55Sjoycey #else 314944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 3150adfcba55Sjoycey #endif 315144961713Sgirish != NXGE_OK) 315244961713Sgirish goto fail; 315344961713Sgirish } 315444961713Sgirish 315544961713Sgirish bmcr.bits.enable_autoneg = 1; 315644961713Sgirish bmcr.bits.restart_autoneg = 1; 315744961713Sgirish 315844961713Sgirish } else { 315944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 316044961713Sgirish bmcr.bits.speed_1000_sel = 316144961713Sgirish param_arr[param_anar_1000fdx].value | 316244961713Sgirish param_arr[param_anar_1000hdx].value; 316344961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 316444961713Sgirish (param_arr[param_anar_100fdx].value | 316544961713Sgirish param_arr[param_anar_100hdx].value); 316644961713Sgirish if (bmcr.bits.speed_1000_sel) { 316744961713Sgirish statsp->mac_stats.link_speed = 1000; 316844961713Sgirish gcr.value = 0; 316944961713Sgirish gcr.bits.ms_mode_en = 317044961713Sgirish param_arr[param_master_cfg_enable].value; 317144961713Sgirish gcr.bits.master = 317244961713Sgirish param_arr[param_master_cfg_value].value; 317344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3174adfcba55Sjoycey #if defined(__i386) 3175adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 3176adfcba55Sjoycey #else 317744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 3178adfcba55Sjoycey #endif 317944961713Sgirish gcr.value)) 318044961713Sgirish != NXGE_OK) 318144961713Sgirish goto fail; 318244961713Sgirish if (param_arr[param_anar_1000fdx].value) { 318344961713Sgirish bmcr.bits.duplex_mode = 1; 318444961713Sgirish statsp->mac_stats.link_duplex = 2; 318544961713Sgirish } else 318644961713Sgirish statsp->mac_stats.link_duplex = 1; 318744961713Sgirish } else if (bmcr.bits.speed_sel) { 318844961713Sgirish statsp->mac_stats.link_speed = 100; 318944961713Sgirish if (param_arr[param_anar_100fdx].value) { 319044961713Sgirish bmcr.bits.duplex_mode = 1; 319144961713Sgirish statsp->mac_stats.link_duplex = 2; 319244961713Sgirish } else 319344961713Sgirish statsp->mac_stats.link_duplex = 1; 319444961713Sgirish } else { 319544961713Sgirish statsp->mac_stats.link_speed = 10; 319644961713Sgirish if (param_arr[param_anar_10fdx].value) { 319744961713Sgirish bmcr.bits.duplex_mode = 1; 319844961713Sgirish statsp->mac_stats.link_duplex = 2; 319944961713Sgirish } else 320044961713Sgirish statsp->mac_stats.link_duplex = 1; 320144961713Sgirish } 320244961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 320344961713Sgirish statsp->mac_stats.link_asmpause = 320444961713Sgirish statsp->mac_stats.cap_asmpause; 320544961713Sgirish statsp->mac_stats.link_pause = 320644961713Sgirish statsp->mac_stats.cap_pause; 320744961713Sgirish } 320844961713Sgirish 320944961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 321044961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 321144961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 321244961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 321344961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 321444961713Sgirish gcr.value = 0; 321544961713Sgirish gcr.bits.ms_mode_en = 1; 321644961713Sgirish gcr.bits.master = 1; 321744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3218adfcba55Sjoycey #if defined(__i386) 3219adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 3220adfcba55Sjoycey #else 322144961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 3222adfcba55Sjoycey #endif 322344961713Sgirish gcr.value)) 322444961713Sgirish != NXGE_OK) 322544961713Sgirish goto fail; 322644961713Sgirish bmcr.value = 0; 322744961713Sgirish bmcr.bits.speed_1000_sel = 1; 322844961713Sgirish statsp->mac_stats.link_speed = 1000; 322944961713Sgirish } else if (statsp->port_stats.lb_mode 323044961713Sgirish == nxge_lb_ext100) { 323144961713Sgirish /* BCM5464R 100mbps external loopback mode */ 323244961713Sgirish bmcr.value = 0; 323344961713Sgirish bmcr.bits.speed_sel = 1; 323444961713Sgirish bmcr.bits.duplex_mode = 1; 323544961713Sgirish statsp->mac_stats.link_speed = 100; 323644961713Sgirish } else if (statsp->port_stats.lb_mode 323744961713Sgirish == nxge_lb_ext10) { 323844961713Sgirish /* BCM5464R 10mbps external loopback mode */ 323944961713Sgirish bmcr.value = 0; 324044961713Sgirish bmcr.bits.duplex_mode = 1; 324144961713Sgirish statsp->mac_stats.link_speed = 10; 324244961713Sgirish } 324344961713Sgirish } 324444961713Sgirish } 324544961713Sgirish 324644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3247adfcba55Sjoycey #if defined(__i386) 3248adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 3249adfcba55Sjoycey #else 325044961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), 3251adfcba55Sjoycey #endif 325244961713Sgirish bmcr.value)) != NXGE_OK) 325344961713Sgirish goto fail; 325444961713Sgirish 325544961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3256adfcba55Sjoycey #if defined(__i386) 3257adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3258adfcba55Sjoycey #else 325944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3260adfcba55Sjoycey #endif 326144961713Sgirish goto fail; 326244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 326344961713Sgirish 326444961713Sgirish /* 326544961713Sgirish * Initialize the xcvr status kept in the context structure. 326644961713Sgirish */ 326744961713Sgirish nxgep->soft_bmsr.value = 0; 326844961713Sgirish 326944961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3270adfcba55Sjoycey #if defined(__i386) 3271adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 3272adfcba55Sjoycey #else 327344961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 3274adfcba55Sjoycey #endif 327544961713Sgirish &nxgep->bmsr.value)) != NXGE_OK) 327644961713Sgirish goto fail; 327744961713Sgirish 327844961713Sgirish statsp->mac_stats.xcvr_inits++; 327944961713Sgirish nxgep->bmsr.value = 0; 328044961713Sgirish 328144961713Sgirish fail: 328244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 328344961713Sgirish "<== nxge_mii_xcvr_init status 0x%x", status)); 328444961713Sgirish return (status); 328544961713Sgirish } 328644961713Sgirish 3287d81011f0Ssbehera nxge_status_t 3288d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 3289d81011f0Ssbehera { 3290d81011f0Ssbehera p_nxge_param_t param_arr; 3291d81011f0Ssbehera p_nxge_stats_t statsp; 3292d81011f0Ssbehera uint8_t xcvr_portn; 3293d81011f0Ssbehera p_mii_regs_t mii_regs; 3294d81011f0Ssbehera mii_bmcr_t bmcr; 3295d81011f0Ssbehera mii_bmsr_t bmsr; 3296d81011f0Ssbehera mii_gcr_t gcr; 3297d81011f0Ssbehera mii_esr_t esr; 3298d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 3299d81011f0Ssbehera int status = NXGE_OK; 3300d81011f0Ssbehera 3301d81011f0Ssbehera uint_t delay; 3302d81011f0Ssbehera 3303d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 3304d81011f0Ssbehera 3305d81011f0Ssbehera param_arr = nxgep->param_arr; 3306d81011f0Ssbehera statsp = nxgep->statsp; 3307d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 3308d81011f0Ssbehera 3309d81011f0Ssbehera mii_regs = NULL; 3310d81011f0Ssbehera 3311d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3312d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 3313d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3314d81011f0Ssbehera 3315d81011f0Ssbehera /* 3316d81011f0Ssbehera * Reset the transceiver. 3317d81011f0Ssbehera */ 3318d81011f0Ssbehera delay = 0; 3319d81011f0Ssbehera bmcr.value = 0; 3320d81011f0Ssbehera bmcr.bits.reset = 1; 3321d81011f0Ssbehera 3322d81011f0Ssbehera #if defined(__i386) 3323d81011f0Ssbehera 3324d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3325d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3326d81011f0Ssbehera goto fail; 3327d81011f0Ssbehera #else 3328d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3329d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3330d81011f0Ssbehera goto fail; 3331d81011f0Ssbehera #endif 3332d81011f0Ssbehera do { 3333d81011f0Ssbehera drv_usecwait(500); 3334d81011f0Ssbehera #if defined(__i386) 3335d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3336d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 3337d81011f0Ssbehera != NXGE_OK) 3338d81011f0Ssbehera goto fail; 3339d81011f0Ssbehera #else 3340d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3341d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 3342d81011f0Ssbehera != NXGE_OK) 3343d81011f0Ssbehera goto fail; 3344d81011f0Ssbehera #endif 3345d81011f0Ssbehera delay++; 3346d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 3347d81011f0Ssbehera if (delay == 1000) { 3348d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 3349d81011f0Ssbehera goto fail; 3350d81011f0Ssbehera } 3351d81011f0Ssbehera 3352d81011f0Ssbehera #if defined(__i386) 3353d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3354d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3355d81011f0Ssbehera goto fail; 3356d81011f0Ssbehera #else 3357d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3358d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3359d81011f0Ssbehera goto fail; 3360d81011f0Ssbehera #endif 3361d81011f0Ssbehera 3362d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 3363d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 3364d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 3365d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 3366d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 3367d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 3368d81011f0Ssbehera 3369d81011f0Ssbehera /* 3370d81011f0Ssbehera * Initialize the xcvr statistics. 3371d81011f0Ssbehera */ 3372d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 3373d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 3374d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 3375d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 3376d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 3377d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 3378d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 3379d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3380d81011f0Ssbehera 3381d81011f0Ssbehera /* 3382d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 3383d81011f0Ssbehera */ 3384d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 3385d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3386d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3387d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 3388d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 3389d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 3390d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 3391d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 3392d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 3393d81011f0Ssbehera param_arr[param_anar_asmpause].value; 3394d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3395d81011f0Ssbehera 3396d81011f0Ssbehera /* 3397d81011f0Ssbehera * Check for extended status just in case we're 3398d81011f0Ssbehera * running a Gigibit phy. 3399d81011f0Ssbehera */ 3400d81011f0Ssbehera if (bmsr.bits.extend_status) { 3401d81011f0Ssbehera #if defined(__i386) 3402d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3403d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 3404d81011f0Ssbehera NXGE_OK) 3405d81011f0Ssbehera goto fail; 3406d81011f0Ssbehera #else 3407d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3408d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 3409d81011f0Ssbehera NXGE_OK) 3410d81011f0Ssbehera goto fail; 3411d81011f0Ssbehera #endif 3412d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 3413d81011f0Ssbehera esr.bits.link_1000fdx; 3414d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 3415d81011f0Ssbehera 3416d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 3417d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 3418d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 3419d81011f0Ssbehera } else { 3420d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 3421d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 3422d81011f0Ssbehera } 3423d81011f0Ssbehera 3424d81011f0Ssbehera /* 3425d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 3426d81011f0Ssbehera */ 3427d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3428d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3429d81011f0Ssbehera 3430d81011f0Ssbehera /* 3431d81011f0Ssbehera * Initialize the link statistics. 3432d81011f0Ssbehera */ 3433d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 3434d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 3435d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 3436d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 3437d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 3438d81011f0Ssbehera statsp->mac_stats.link_up = 0; 3439d81011f0Ssbehera 3440d81011f0Ssbehera /* 3441d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 3442d81011f0Ssbehera */ 3443d81011f0Ssbehera bmcr.value = 0; 3444d81011f0Ssbehera #if defined(__i386) 3445d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3446d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3447d81011f0Ssbehera goto fail; 3448d81011f0Ssbehera #else 3449d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3450d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3451d81011f0Ssbehera goto fail; 3452d81011f0Ssbehera #endif 3453d81011f0Ssbehera 3454d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 3455d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 3456d81011f0Ssbehera bmcr.bits.loopback = 1; 3457d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 3458d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 3459d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3460d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 3461d81011f0Ssbehera param_arr[param_autoneg].value = 0; 3462d81011f0Ssbehera } else { 3463d81011f0Ssbehera bmcr.bits.loopback = 0; 3464d81011f0Ssbehera } 3465d81011f0Ssbehera 3466d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 3467d81011f0Ssbehera param_arr[param_autoneg].value = 0; 3468d81011f0Ssbehera bcm5464r_aux.value = 0; 3469d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 3470d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 3471d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3472d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 3473d81011f0Ssbehera goto fail; 3474d81011f0Ssbehera } 3475d81011f0Ssbehera 3476d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 3477d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3478d81011f0Ssbehera bmcr.bits.speed_sel = 0; 3479d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 3480d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 3481d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 3482d81011f0Ssbehera 3483d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 3484d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 3485d81011f0Ssbehera gcr.value = 0; 3486d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 3487d81011f0Ssbehera gcr.bits.master = 1; 3488d81011f0Ssbehera #if defined(__i386) 3489d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3490d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 3491d81011f0Ssbehera gcr.value)) != NXGE_OK) 3492d81011f0Ssbehera goto fail; 3493d81011f0Ssbehera #else 3494d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3495d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 3496d81011f0Ssbehera gcr.value)) != NXGE_OK) 3497d81011f0Ssbehera goto fail; 3498d81011f0Ssbehera #endif 3499d81011f0Ssbehera bmcr.value = 0; 3500d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 3501d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 3502d81011f0Ssbehera } 3503d81011f0Ssbehera 3504d81011f0Ssbehera #if defined(__i386) 3505d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3506d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 3507d81011f0Ssbehera bmcr.value)) != NXGE_OK) 3508d81011f0Ssbehera goto fail; 3509d81011f0Ssbehera #else 3510d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3511d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 3512d81011f0Ssbehera bmcr.value)) != NXGE_OK) 3513d81011f0Ssbehera goto fail; 3514d81011f0Ssbehera #endif 3515d81011f0Ssbehera 3516d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3517d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 3518d81011f0Ssbehera bmcr.value)); 3519d81011f0Ssbehera 3520d81011f0Ssbehera #if defined(__i386) 3521d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3522d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3523d81011f0Ssbehera goto fail; 3524d81011f0Ssbehera #else 3525d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3526d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3527d81011f0Ssbehera goto fail; 3528d81011f0Ssbehera #endif 3529d81011f0Ssbehera 3530d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3531d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 3532d81011f0Ssbehera 3533d81011f0Ssbehera /* 3534d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 3535d81011f0Ssbehera */ 3536d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 3537d81011f0Ssbehera #if defined(__i386) 3538d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3539d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 3540d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 3541d81011f0Ssbehera goto fail; 3542d81011f0Ssbehera #else 3543d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3544d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 3545d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 3546d81011f0Ssbehera goto fail; 3547d81011f0Ssbehera #endif 3548d81011f0Ssbehera 3549d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 3550d81011f0Ssbehera nxgep->bmsr.value = 0; 3551d81011f0Ssbehera 3552d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3553d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3554d81011f0Ssbehera return (status); 3555d81011f0Ssbehera 3556d81011f0Ssbehera fail: 3557d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3558d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3559d81011f0Ssbehera return (status); 3560d81011f0Ssbehera } 3561d81011f0Ssbehera 356244961713Sgirish /* Read from a MII compliant register */ 356344961713Sgirish 356444961713Sgirish nxge_status_t 356544961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 356644961713Sgirish uint16_t *value) 356744961713Sgirish { 356844961713Sgirish npi_status_t rs = NPI_SUCCESS; 356944961713Sgirish 357044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 357144961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 357244961713Sgirish 3573*321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 357444961713Sgirish 3575d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3576d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 357744961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 357844961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 357944961713Sgirish goto fail; 35802e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 35812e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 358244961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 358344961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 358444961713Sgirish goto fail; 358544961713Sgirish } else 358644961713Sgirish goto fail; 358744961713Sgirish 3588*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 358944961713Sgirish 359044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 359144961713Sgirish "xcvr_reg<%d> value=0x%x", 359244961713Sgirish xcvr_portn, xcvr_reg, *value)); 359344961713Sgirish return (NXGE_OK); 359444961713Sgirish fail: 3595*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 359644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 359744961713Sgirish "nxge_mii_read: Failed to read mii on xcvr %d", 359844961713Sgirish xcvr_portn)); 359944961713Sgirish 360044961713Sgirish return (NXGE_ERROR | rs); 360144961713Sgirish } 360244961713Sgirish 360344961713Sgirish /* Write to a MII compliant Register */ 360444961713Sgirish 360544961713Sgirish nxge_status_t 360644961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 360744961713Sgirish uint16_t value) 360844961713Sgirish { 360944961713Sgirish npi_status_t rs = NPI_SUCCESS; 361044961713Sgirish 361144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 361244961713Sgirish "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 361344961713Sgirish value)); 361444961713Sgirish 3615*321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 361644961713Sgirish 3617d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3618d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 361944961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 362044961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 362144961713Sgirish goto fail; 36222e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 36232e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 362444961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 362544961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 362644961713Sgirish goto fail; 362744961713Sgirish } else 362844961713Sgirish goto fail; 362944961713Sgirish 3630*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 363144961713Sgirish 363244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 363344961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 363444961713Sgirish return (NXGE_OK); 363544961713Sgirish fail: 3636*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 363744961713Sgirish 363844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 363944961713Sgirish "nxge_mii_write: Failed to write mii on xcvr %d", 364044961713Sgirish xcvr_portn)); 364144961713Sgirish 364244961713Sgirish return (NXGE_ERROR | rs); 364344961713Sgirish } 364444961713Sgirish 364544961713Sgirish /* Perform read from Clause45 serdes / transceiver device */ 364644961713Sgirish 364744961713Sgirish nxge_status_t 364844961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 364944961713Sgirish uint16_t xcvr_reg, uint16_t *value) 365044961713Sgirish { 365144961713Sgirish npi_status_t rs = NPI_SUCCESS; 365244961713Sgirish 365344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 365444961713Sgirish xcvr_portn)); 365544961713Sgirish 365653560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 365744961713Sgirish 365844961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 365944961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 366044961713Sgirish goto fail; 366144961713Sgirish 366253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 366344961713Sgirish 366444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 366544961713Sgirish xcvr_portn)); 366644961713Sgirish return (NXGE_OK); 366744961713Sgirish fail: 366853560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 366944961713Sgirish 367044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 367144961713Sgirish "nxge_mdio_read: Failed to read mdio on xcvr %d", 367244961713Sgirish xcvr_portn)); 367344961713Sgirish 367444961713Sgirish return (NXGE_ERROR | rs); 367544961713Sgirish } 367644961713Sgirish 367744961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 367844961713Sgirish 367944961713Sgirish nxge_status_t 368044961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 368144961713Sgirish uint16_t xcvr_reg, uint16_t value) 368244961713Sgirish { 368344961713Sgirish npi_status_t rs = NPI_SUCCESS; 368444961713Sgirish 368544961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 368644961713Sgirish xcvr_portn)); 368744961713Sgirish 368853560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 368944961713Sgirish 369044961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 369144961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 369244961713Sgirish goto fail; 369344961713Sgirish 369453560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 369544961713Sgirish 369644961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 369744961713Sgirish xcvr_portn)); 369844961713Sgirish return (NXGE_OK); 369944961713Sgirish fail: 370053560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 370144961713Sgirish 370244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 370344961713Sgirish "nxge_mdio_write: Failed to write mdio on xcvr %d", 370444961713Sgirish xcvr_portn)); 370544961713Sgirish 370644961713Sgirish return (NXGE_ERROR | rs); 370744961713Sgirish } 370844961713Sgirish 370944961713Sgirish 371044961713Sgirish /* Check MII to see if there is any link status change */ 371144961713Sgirish 371244961713Sgirish nxge_status_t 3713a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 3714a3c5bd6dSspeer nxge_link_state_t *link_up) 371544961713Sgirish { 371644961713Sgirish p_nxge_param_t param_arr; 371744961713Sgirish p_nxge_stats_t statsp; 371844961713Sgirish p_mii_regs_t mii_regs; 371944961713Sgirish p_mii_bmsr_t soft_bmsr; 372044961713Sgirish mii_anar_t anar; 372144961713Sgirish mii_anlpar_t anlpar; 372244961713Sgirish mii_anar_t an_common; 372344961713Sgirish mii_aner_t aner; 372444961713Sgirish mii_gsr_t gsr; 372544961713Sgirish nxge_status_t status = NXGE_OK; 372644961713Sgirish 372744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 372844961713Sgirish 372944961713Sgirish mii_regs = NULL; 373044961713Sgirish param_arr = nxgep->param_arr; 373144961713Sgirish statsp = nxgep->statsp; 373244961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 3733a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 373444961713Sgirish 3735d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3736d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 3737d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 3738d81011f0Ssbehera 373944961713Sgirish if (bmsr_ints.bits.link_status) { 3740d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3741d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 3742d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 374344961713Sgirish if (bmsr.bits.link_status) { 374444961713Sgirish soft_bmsr->bits.link_status = 1; 3745d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3746d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 3747d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 374844961713Sgirish } else { 374944961713Sgirish statsp->mac_stats.link_up = 0; 375044961713Sgirish soft_bmsr->bits.link_status = 0; 375144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 375244961713Sgirish "Link down cable problem")); 3753a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 375444961713Sgirish } 375544961713Sgirish } 375644961713Sgirish 3757d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 3758d81011f0Ssbehera param_arr[param_autoneg].value) { 375944961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 376044961713Sgirish if (bmsr.bits.auto_neg_complete) 376144961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 376244961713Sgirish else 376344961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 376444961713Sgirish } 376544961713Sgirish if (soft_bmsr->bits.link_status == 0) { 376644961713Sgirish statsp->mac_stats.link_T4 = 0; 376744961713Sgirish statsp->mac_stats.link_speed = 0; 376844961713Sgirish statsp->mac_stats.link_duplex = 0; 376944961713Sgirish statsp->mac_stats.link_asmpause = 0; 377044961713Sgirish statsp->mac_stats.link_pause = 0; 377144961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 377244961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 377344961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 377444961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 377544961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 377644961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 377744961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 377844961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 377944961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 378044961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 378144961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 378244961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 378344961713Sgirish } 378444961713Sgirish } else 378544961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 378644961713Sgirish 378744961713Sgirish if ((bmsr_ints.bits.link_status || 378844961713Sgirish bmsr_ints.bits.auto_neg_complete) && 378944961713Sgirish soft_bmsr->bits.link_status && 379044961713Sgirish soft_bmsr->bits.auto_neg_complete) { 379144961713Sgirish statsp->mac_stats.link_up = 1; 3792d81011f0Ssbehera 3793d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3794d81011f0Ssbehera "==> nxge_mii_check " 3795d81011f0Ssbehera "(auto negotiation complete or link up) " 3796d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 3797d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 3798d81011f0Ssbehera 3799d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 3800d81011f0Ssbehera param_arr[param_autoneg].value) { 380144961713Sgirish if ((status = nxge_mii_read(nxgep, 380244961713Sgirish statsp->mac_stats.xcvr_portn, 3803adfcba55Sjoycey #if defined(__i386) 3804adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 3805adfcba55Sjoycey #else 380644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), 3807adfcba55Sjoycey #endif 380844961713Sgirish &anar.value)) != NXGE_OK) 380944961713Sgirish goto fail; 381044961713Sgirish if ((status = nxge_mii_read(nxgep, 381144961713Sgirish statsp->mac_stats.xcvr_portn, 3812adfcba55Sjoycey #if defined(__i386) 3813adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 3814adfcba55Sjoycey #else 381544961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anlpar), 3816adfcba55Sjoycey #endif 381744961713Sgirish &anlpar.value)) != NXGE_OK) 381844961713Sgirish goto fail; 381944961713Sgirish if ((status = nxge_mii_read(nxgep, 382044961713Sgirish statsp->mac_stats.xcvr_portn, 3821adfcba55Sjoycey #if defined(__i386) 3822adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 3823adfcba55Sjoycey #else 382444961713Sgirish (uint8_t)(uint64_t)(&mii_regs->aner), 3825adfcba55Sjoycey #endif 382644961713Sgirish &aner.value)) != NXGE_OK) 382744961713Sgirish goto fail; 382844961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 382944961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 383044961713Sgirish statsp->mac_stats.lp_cap_100fdx = 383144961713Sgirish anlpar.bits.cap_100fdx; 383244961713Sgirish statsp->mac_stats.lp_cap_100hdx = 383344961713Sgirish anlpar.bits.cap_100hdx; 383444961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 383544961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 383644961713Sgirish statsp->mac_stats.lp_cap_asmpause = 383744961713Sgirish anlpar.bits.cap_asmpause; 383844961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 383944961713Sgirish an_common.value = anar.value & anlpar.value; 384044961713Sgirish if (param_arr[param_anar_1000fdx].value || 384144961713Sgirish param_arr[param_anar_1000hdx].value) { 384244961713Sgirish if ((status = nxge_mii_read(nxgep, 384344961713Sgirish statsp->mac_stats.xcvr_portn, 3844adfcba55Sjoycey #if defined(__i386) 3845adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 3846adfcba55Sjoycey #else 384744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gsr), 3848adfcba55Sjoycey #endif 384944961713Sgirish &gsr.value)) 385044961713Sgirish != NXGE_OK) 385144961713Sgirish goto fail; 385244961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 385344961713Sgirish gsr.bits.link_1000fdx; 385444961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 385544961713Sgirish gsr.bits.link_1000hdx; 385644961713Sgirish if (param_arr[param_anar_1000fdx].value && 385744961713Sgirish gsr.bits.link_1000fdx) { 385844961713Sgirish statsp->mac_stats.link_speed = 1000; 385944961713Sgirish statsp->mac_stats.link_duplex = 2; 386044961713Sgirish } else if ( 386144961713Sgirish param_arr[param_anar_1000hdx].value && 386244961713Sgirish gsr.bits.link_1000hdx) { 386344961713Sgirish statsp->mac_stats.link_speed = 1000; 386444961713Sgirish statsp->mac_stats.link_duplex = 1; 386544961713Sgirish } 386644961713Sgirish } 386744961713Sgirish if ((an_common.value != 0) && 386844961713Sgirish !(statsp->mac_stats.link_speed)) { 386944961713Sgirish if (an_common.bits.cap_100T4) { 387044961713Sgirish statsp->mac_stats.link_T4 = 1; 387144961713Sgirish statsp->mac_stats.link_speed = 100; 387244961713Sgirish statsp->mac_stats.link_duplex = 1; 387344961713Sgirish } else if (an_common.bits.cap_100fdx) { 387444961713Sgirish statsp->mac_stats.link_speed = 100; 387544961713Sgirish statsp->mac_stats.link_duplex = 2; 387644961713Sgirish } else if (an_common.bits.cap_100hdx) { 387744961713Sgirish statsp->mac_stats.link_speed = 100; 387844961713Sgirish statsp->mac_stats.link_duplex = 1; 387944961713Sgirish } else if (an_common.bits.cap_10fdx) { 388044961713Sgirish statsp->mac_stats.link_speed = 10; 388144961713Sgirish statsp->mac_stats.link_duplex = 2; 388244961713Sgirish } else if (an_common.bits.cap_10hdx) { 388344961713Sgirish statsp->mac_stats.link_speed = 10; 388444961713Sgirish statsp->mac_stats.link_duplex = 1; 388544961713Sgirish } else { 388644961713Sgirish goto fail; 388744961713Sgirish } 388844961713Sgirish } 388944961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 389044961713Sgirish statsp->mac_stats.link_asmpause = 389144961713Sgirish an_common.bits.cap_asmpause; 389244961713Sgirish if (statsp->mac_stats.link_asmpause) 389344961713Sgirish if ((statsp->mac_stats.cap_pause == 0) && 389444961713Sgirish (statsp->mac_stats.lp_cap_pause 389544961713Sgirish == 1)) 389644961713Sgirish statsp->mac_stats.link_pause 389744961713Sgirish = 0; 389844961713Sgirish else 389944961713Sgirish statsp->mac_stats.link_pause 390044961713Sgirish = 1; 390144961713Sgirish else 390244961713Sgirish statsp->mac_stats.link_pause = 390344961713Sgirish an_common.bits.cap_pause; 390444961713Sgirish } 3905d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3906d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 3907d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 390844961713Sgirish } 3909a3c5bd6dSspeer *link_up = LINK_IS_UP; 3910a3c5bd6dSspeer } 3911a3c5bd6dSspeer 3912a3c5bd6dSspeer if (nxgep->link_notify) { 3913a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 3914a3c5bd6dSspeer LINK_IS_DOWN); 3915a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 391644961713Sgirish } 391744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 391844961713Sgirish return (NXGE_OK); 391944961713Sgirish fail: 392044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 392144961713Sgirish "nxge_mii_check: Unable to check MII")); 392244961713Sgirish return (status); 392344961713Sgirish } 392444961713Sgirish 39252e59129aSraghus /* Check PCS to see if there is any link status change */ 39262e59129aSraghus nxge_status_t 39272e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 39282e59129aSraghus { 39292e59129aSraghus p_nxge_stats_t statsp; 39302e59129aSraghus nxge_status_t status = NXGE_OK; 39312e59129aSraghus boolean_t linkup; 39322e59129aSraghus 39332e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 39342e59129aSraghus 39352e59129aSraghus statsp = nxgep->statsp; 39362e59129aSraghus *link_up = LINK_NO_CHANGE; 39372e59129aSraghus 39382e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 39392e59129aSraghus if (linkup) { 39402e59129aSraghus if (nxgep->link_notify || 39412e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 39422e59129aSraghus statsp->mac_stats.link_up = 1; 39432e59129aSraghus statsp->mac_stats.link_speed = 1000; 39442e59129aSraghus statsp->mac_stats.link_duplex = 2; 39452e59129aSraghus *link_up = LINK_IS_UP; 39462e59129aSraghus nxgep->link_notify = B_FALSE; 39472e59129aSraghus } 39482e59129aSraghus } else { 39492e59129aSraghus if (nxgep->link_notify || 39502e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 39512e59129aSraghus statsp->mac_stats.link_up = 0; 39522e59129aSraghus statsp->mac_stats.link_speed = 0; 39532e59129aSraghus statsp->mac_stats.link_duplex = 0; 39542e59129aSraghus *link_up = LINK_IS_DOWN; 39552e59129aSraghus nxgep->link_notify = B_FALSE; 39562e59129aSraghus } 39572e59129aSraghus } 39582e59129aSraghus 39592e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 39602e59129aSraghus return (NXGE_OK); 39612e59129aSraghus fail: 39622e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 39632e59129aSraghus "nxge_pcs_check: Unable to check PCS")); 39642e59129aSraghus return (status); 39652e59129aSraghus } 39662e59129aSraghus 396744961713Sgirish /* Add a multicast address entry into the HW hash table */ 396844961713Sgirish 396944961713Sgirish nxge_status_t 397044961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 397144961713Sgirish { 397244961713Sgirish uint32_t mchash; 397344961713Sgirish p_hash_filter_t hash_filter; 397444961713Sgirish uint16_t hash_bit; 397544961713Sgirish boolean_t rx_init = B_FALSE; 397644961713Sgirish uint_t j; 397744961713Sgirish nxge_status_t status = NXGE_OK; 397844961713Sgirish 397944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 398044961713Sgirish 398144961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 398244961713Sgirish mchash = crc32_mchash(addrp); 398344961713Sgirish if (nxgep->hash_filter == NULL) { 398444961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 398544961713Sgirish "Allocating hash filter storage.")); 398644961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 398744961713Sgirish KM_SLEEP); 398844961713Sgirish } 398944961713Sgirish hash_filter = nxgep->hash_filter; 399044961713Sgirish j = mchash / HASH_REG_WIDTH; 399144961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 399244961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 399344961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 399444961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 399544961713Sgirish hash_filter->hash_ref_cnt++; 399644961713Sgirish rx_init = B_TRUE; 399744961713Sgirish } 399844961713Sgirish if (rx_init) { 399944961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 400044961713Sgirish goto fail; 400144961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 400244961713Sgirish goto fail; 400344961713Sgirish } 400444961713Sgirish 400544961713Sgirish RW_EXIT(&nxgep->filter_lock); 400644961713Sgirish 400744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 400844961713Sgirish 400944961713Sgirish return (NXGE_OK); 401044961713Sgirish fail: 401144961713Sgirish RW_EXIT(&nxgep->filter_lock); 401244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 401344961713Sgirish "Unable to add multicast address")); 401444961713Sgirish return (status); 401544961713Sgirish } 401644961713Sgirish 401744961713Sgirish /* Remove a multicast address entry from the HW hash table */ 401844961713Sgirish 401944961713Sgirish nxge_status_t 402044961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 402144961713Sgirish { 402244961713Sgirish uint32_t mchash; 402344961713Sgirish p_hash_filter_t hash_filter; 402444961713Sgirish uint16_t hash_bit; 402544961713Sgirish boolean_t rx_init = B_FALSE; 402644961713Sgirish uint_t j; 402744961713Sgirish nxge_status_t status = NXGE_OK; 402844961713Sgirish 402944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 403044961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 403144961713Sgirish mchash = crc32_mchash(addrp); 403244961713Sgirish if (nxgep->hash_filter == NULL) { 403344961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 403444961713Sgirish "Hash filter already de_allocated.")); 403544961713Sgirish RW_EXIT(&nxgep->filter_lock); 403644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 403744961713Sgirish return (NXGE_OK); 403844961713Sgirish } 403944961713Sgirish hash_filter = nxgep->hash_filter; 404044961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 404144961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 404244961713Sgirish j = mchash / HASH_REG_WIDTH; 404344961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 404444961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 404544961713Sgirish hash_filter->hash_ref_cnt--; 404644961713Sgirish rx_init = B_TRUE; 404744961713Sgirish } 404844961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 404944961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 405044961713Sgirish "De-allocating hash filter storage.")); 405144961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 405244961713Sgirish nxgep->hash_filter = NULL; 405344961713Sgirish } 405444961713Sgirish 405544961713Sgirish if (rx_init) { 405644961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 405744961713Sgirish goto fail; 405844961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 405944961713Sgirish goto fail; 406044961713Sgirish } 406144961713Sgirish RW_EXIT(&nxgep->filter_lock); 406244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 406344961713Sgirish 406444961713Sgirish return (NXGE_OK); 406544961713Sgirish fail: 406644961713Sgirish RW_EXIT(&nxgep->filter_lock); 406744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 406844961713Sgirish "Unable to remove multicast address")); 406944961713Sgirish 407044961713Sgirish return (status); 407144961713Sgirish } 407244961713Sgirish 407344961713Sgirish /* Set MAC address into MAC address HW registers */ 407444961713Sgirish 407544961713Sgirish nxge_status_t 407644961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 407744961713Sgirish { 407844961713Sgirish nxge_status_t status = NXGE_OK; 407944961713Sgirish 408044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 408144961713Sgirish 408244961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 408344961713Sgirish /* 408444961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 408544961713Sgirish */ 408644961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 408744961713Sgirish (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 408844961713Sgirish (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 408944961713Sgirish goto nxge_set_mac_addr_exit; 409044961713Sgirish } 409144961713Sgirish nxgep->ouraddr = *addrp; 409244961713Sgirish /* 409344961713Sgirish * Set new interface local address and re-init device. 409444961713Sgirish * This is destructive to any other streams attached 409544961713Sgirish * to this device. 409644961713Sgirish */ 409744961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 409844961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 409944961713Sgirish goto fail; 410044961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 410144961713Sgirish goto fail; 410244961713Sgirish 410344961713Sgirish RW_EXIT(&nxgep->filter_lock); 410444961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 410544961713Sgirish goto nxge_set_mac_addr_end; 410644961713Sgirish nxge_set_mac_addr_exit: 410744961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 410844961713Sgirish nxge_set_mac_addr_end: 410944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 411044961713Sgirish 411144961713Sgirish return (NXGE_OK); 411244961713Sgirish fail: 411344961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 411444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 411544961713Sgirish "Unable to set mac address")); 411644961713Sgirish return (status); 411744961713Sgirish } 411844961713Sgirish 411998ecde52Stm static 412098ecde52Stm check_link_state_t 412198ecde52Stm nxge_check_link_stop( 412298ecde52Stm nxge_t *nxge) 412398ecde52Stm { 412498ecde52Stm /* If the poll has been cancelled, return STOP. */ 412598ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 412698ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 412798ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 412898ecde52Stm nxge->nxge_link_poll_timerid = 0; 412998ecde52Stm cv_broadcast(&nxge->poll_cv); 413098ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 413198ecde52Stm 413298ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 413398ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 413498ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 413598ecde52Stm nxge->mac.portnum)); 413698ecde52Stm return (CHECK_LINK_STOP); 413798ecde52Stm } 413898ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 413998ecde52Stm 414098ecde52Stm return (CHECK_LINK_RESCHEDULE); 414198ecde52Stm } 414298ecde52Stm 414344961713Sgirish /* Check status of MII (MIF or PCS) link */ 414444961713Sgirish 414559ac0c16Sdavemq static nxge_status_t 414644961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 414744961713Sgirish { 414844961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 414944961713Sgirish mii_anlpar_t anlpar; 415044961713Sgirish mii_gsr_t gsr; 415144961713Sgirish p_mii_regs_t mii_regs; 415244961713Sgirish nxge_status_t status = NXGE_OK; 415344961713Sgirish uint8_t portn; 4154a3c5bd6dSspeer nxge_link_state_t link_up; 415544961713Sgirish 415698ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 415798ecde52Stm return (NXGE_ERROR); 415898ecde52Stm 415998ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 416098ecde52Stm return (NXGE_OK); 416198ecde52Stm 416244961713Sgirish portn = nxgep->mac.portnum; 416344961713Sgirish 416444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 416598ecde52Stm portn)); 416644961713Sgirish 416744961713Sgirish mii_regs = NULL; 416844961713Sgirish 416944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 417044961713Sgirish 417144961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 417244961713Sgirish goto nxge_check_mii_link_exit; 417344961713Sgirish 41742e59129aSraghus switch (nxgep->mac.portmode) { 41752e59129aSraghus default: 4176d81011f0Ssbehera bmsr_data.value = 0; 417744961713Sgirish if ((status = nxge_mii_read(nxgep, 41782e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4179adfcba55Sjoycey #if defined(__i386) 4180adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 4181adfcba55Sjoycey #else 41822e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 4183adfcba55Sjoycey #endif 41842e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 418544961713Sgirish goto fail; 418644961713Sgirish } 418744961713Sgirish 4188d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4189d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 4190d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 41912d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 4192d81011f0Ssbehera 41932e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 41942e59129aSraghus if ((status = nxge_mii_read(nxgep, 41952e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4196adfcba55Sjoycey #if defined(__i386) 4197adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 4198adfcba55Sjoycey #else 41992e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 4200adfcba55Sjoycey #endif 42012e59129aSraghus &gsr.value)) != NXGE_OK) 42022e59129aSraghus goto fail; 42032e59129aSraghus if ((status = nxge_mii_read(nxgep, 42042e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4205adfcba55Sjoycey #if defined(__i386) 4206adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 4207adfcba55Sjoycey #else 42082e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 4209adfcba55Sjoycey #endif 42102e59129aSraghus &anlpar.value)) != NXGE_OK) 42112e59129aSraghus goto fail; 4212d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 4213d81011f0Ssbehera 4214d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 4215d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 4216d81011f0Ssbehera gsr.bits.link_1000fdx) || 4217d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 4218d81011f0Ssbehera gsr.bits.link_1000hdx) || 4219d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 4220d81011f0Ssbehera anlpar.bits.cap_100T4) || 4221d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 4222d81011f0Ssbehera anlpar.bits.cap_100fdx) || 4223d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 4224d81011f0Ssbehera anlpar.bits.cap_100hdx) || 4225d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 4226d81011f0Ssbehera anlpar.bits.cap_10fdx) || 4227d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 4228d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 4229d81011f0Ssbehera bmsr_data.bits.link_status = 0; 4230d81011f0Ssbehera } 42312e59129aSraghus } 42322e59129aSraghus } 423344961713Sgirish 42342e59129aSraghus /* Workaround for link down issue */ 42352e59129aSraghus if (bmsr_data.value == 0) { 42362e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 42372e59129aSraghus goto nxge_check_mii_link_exit; 42382e59129aSraghus } 42392e59129aSraghus 4240d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4241d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 4242d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 42432d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 4244d81011f0Ssbehera 42452e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 42462e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 4247d81011f0Ssbehera 4248d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4249d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 4250d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 42512d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 4252d81011f0Ssbehera 42532e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 42542e59129aSraghus &link_up)) != NXGE_OK) { 42552e59129aSraghus goto fail; 42562e59129aSraghus } 42572e59129aSraghus break; 42582e59129aSraghus 42592e59129aSraghus case PORT_1G_SERDES: 42602e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 42612e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 42622e59129aSraghus if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 42632e59129aSraghus != NXGE_OK) { 42642e59129aSraghus goto fail; 42652e59129aSraghus } 42662e59129aSraghus break; 42672e59129aSraghus } 426844961713Sgirish 426944961713Sgirish nxge_check_mii_link_exit: 427044961713Sgirish RW_EXIT(&nxgep->filter_lock); 4271a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 4272a3c5bd6dSspeer nxge_link_is_up(nxgep); 4273a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 4274a3c5bd6dSspeer nxge_link_is_down(nxgep); 4275a3c5bd6dSspeer } 427644961713Sgirish 427744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 427844961713Sgirish 427944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 42802e59129aSraghus portn)); 428144961713Sgirish return (NXGE_OK); 428244961713Sgirish 428344961713Sgirish fail: 428444961713Sgirish RW_EXIT(&nxgep->filter_lock); 428544961713Sgirish 428644961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 428744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 42882e59129aSraghus "nxge_check_mii_link: Failed to check link port<%d>", 42892e59129aSraghus portn)); 429044961713Sgirish return (status); 429144961713Sgirish } 429244961713Sgirish 429344961713Sgirish 429444961713Sgirish /*ARGSUSED*/ 429559ac0c16Sdavemq static nxge_status_t 429644961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 429744961713Sgirish { 429844961713Sgirish uint8_t portn; 429944961713Sgirish nxge_status_t status = NXGE_OK; 4300763fcc44Ssbehera boolean_t link_up; 43012e59129aSraghus uint32_t val; 43022e59129aSraghus npi_status_t rs; 430344961713Sgirish 430498ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 430598ecde52Stm return (NXGE_ERROR); 430698ecde52Stm 430798ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 430898ecde52Stm return (NXGE_OK); 430998ecde52Stm 431044961713Sgirish portn = nxgep->mac.portnum; 4311d81011f0Ssbehera val = 0; 4312d81011f0Ssbehera rs = NPI_SUCCESS; 431344961713Sgirish 431444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 431598ecde52Stm portn)); 431644961713Sgirish 43172e59129aSraghus switch (nxgep->mac.portmode) { 43182e59129aSraghus default: 43192d17280bSsbehera /* 43202d17280bSsbehera * Check if the phy is present in case of hot swappable phy 43212d17280bSsbehera */ 43222d17280bSsbehera if (nxgep->hot_swappable_phy) { 43232d17280bSsbehera boolean_t phy_present_now = B_FALSE; 43242d17280bSsbehera 43252d17280bSsbehera /* 43262d17280bSsbehera * If this is the 2nd Goa port, then check 2 addresses 43272d17280bSsbehera * to take care of the Goa NEM card requirements. 43282d17280bSsbehera */ 43292d17280bSsbehera if (portn == 1) { 43302d17280bSsbehera if (nxge_is_phy_present(nxgep, 43312d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR, 43322d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 43332d17280bSsbehera phy_present_now = B_TRUE; 43342d17280bSsbehera nxgep->xcvr_addr = 43352d17280bSsbehera BCM8706_ALT_GOA_PORT1_ADDR; 43362d17280bSsbehera goto phy_check_done; 43372d17280bSsbehera } 43382d17280bSsbehera } 43392d17280bSsbehera if (nxge_is_phy_present(nxgep, 43402d17280bSsbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn, 43412d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 43422d17280bSsbehera nxgep->xcvr_addr = 43432d17280bSsbehera (BCM8706_GOA_PORT_ADDR_BASE) + portn; 43442d17280bSsbehera phy_present_now = B_TRUE; 43452d17280bSsbehera } 43462d17280bSsbehera 43472d17280bSsbehera phy_check_done: 43482d17280bSsbehera if (nxgep->phy_absent) { 43492d17280bSsbehera if (phy_present_now) { 43502d17280bSsbehera /* 43512d17280bSsbehera * Detect, Initialize phy and do link up 43522d17280bSsbehera * set xcvr vals, link_init, nxge_init 43532d17280bSsbehera */ 43542d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43552d17280bSsbehera "Hot swappable phy DETECTED!!")); 43562d17280bSsbehera nxgep->phy_absent = B_FALSE; 43572d17280bSsbehera (void) nxge_xcvr_find(nxgep); 43582d17280bSsbehera (void) nxge_link_init(nxgep); 43592d17280bSsbehera if (!(nxgep->drv_state & 43602d17280bSsbehera STATE_HW_INITIALIZED)) { 43612d17280bSsbehera status = nxge_init(nxgep); 43622d17280bSsbehera if (status != NXGE_OK) { 43632d17280bSsbehera NXGE_ERROR_MSG((nxgep, 43642d17280bSsbehera NXGE_ERR_CTL, 43652d17280bSsbehera "Hot swappable " 43662d17280bSsbehera "phy present, but" 43672d17280bSsbehera " driver init" 43682d17280bSsbehera " failed...")); 43692d17280bSsbehera goto fail; 43702d17280bSsbehera } 43712d17280bSsbehera } 43722d17280bSsbehera } 43732d17280bSsbehera 43742d17280bSsbehera goto start_link_check; 43752d17280bSsbehera 43762d17280bSsbehera } else if (!phy_present_now) { 43772d17280bSsbehera /* 43782d17280bSsbehera * Phy gone, bring link down reset xcvr vals 43792d17280bSsbehera */ 43802d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43812d17280bSsbehera "Hot swappable phy REMOVED!!")); 43822d17280bSsbehera nxgep->phy_absent = B_TRUE; 43832d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 43842d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 43852d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 43862d17280bSsbehera nxge_link_is_down(nxgep); 43872d17280bSsbehera nxgep->link_notify = B_FALSE; 43882d17280bSsbehera 43892d17280bSsbehera (void) nxge_xcvr_find(nxgep); 43902d17280bSsbehera 43912d17280bSsbehera goto start_link_check; 43922d17280bSsbehera 43932d17280bSsbehera } 43942d17280bSsbehera } 43952d17280bSsbehera 43962e59129aSraghus status = nxge_check_bcm8704_link(nxgep, &link_up); 43972e59129aSraghus if (status != NXGE_OK) 43982e59129aSraghus goto fail; 43992e59129aSraghus break; 44002e59129aSraghus case PORT_10G_SERDES: 44012e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4402763fcc44Ssbehera XPCS_REG_STATUS, &val); 44032e59129aSraghus if (rs != 0) 44042e59129aSraghus goto fail; 44052e59129aSraghus 44062e59129aSraghus link_up = B_FALSE; 4407763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 4408763fcc44Ssbehera link_up = B_TRUE; 44092e59129aSraghus } 44102e59129aSraghus 44112e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44122e59129aSraghus "==> nxge_check_10g_link port<%d> " 4413763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 4414763fcc44Ssbehera portn, val, link_up)); 44152e59129aSraghus 44162e59129aSraghus break; 44172e59129aSraghus } 441844961713Sgirish 441944961713Sgirish if (link_up) { 4420a3c5bd6dSspeer if (nxgep->link_notify || 4421a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 0) { 442244961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 442344961713Sgirish goto fail; 442444961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 442544961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 442644961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 442744961713Sgirish 442844961713Sgirish nxge_link_is_up(nxgep); 4429a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 443044961713Sgirish } 443144961713Sgirish } else { 4432a3c5bd6dSspeer if (nxgep->link_notify || 4433a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 1) { 443444961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 443544961713Sgirish goto fail; 443644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44372e59129aSraghus "Link down cable problem")); 443844961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 443944961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 444044961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 444144961713Sgirish 444244961713Sgirish nxge_link_is_down(nxgep); 4443a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 444444961713Sgirish } 444544961713Sgirish } 444644961713Sgirish 44472d17280bSsbehera start_link_check: 444844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 444944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 445098ecde52Stm portn)); 445144961713Sgirish return (NXGE_OK); 445244961713Sgirish 445344961713Sgirish fail: 445498ecde52Stm (void) nxge_check_link_stop(nxgep); 445598ecde52Stm 445644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 445798ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 445898ecde52Stm portn)); 445944961713Sgirish return (status); 446044961713Sgirish } 446144961713Sgirish 446244961713Sgirish 446344961713Sgirish /* Declare link down */ 446444961713Sgirish 446544961713Sgirish void 446644961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 446744961713Sgirish { 446859ac0c16Sdavemq p_nxge_stats_t statsp; 446959ac0c16Sdavemq char link_stat_msg[64]; 447059ac0c16Sdavemq 447144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 447244961713Sgirish 447359ac0c16Sdavemq statsp = nxgep->statsp; 447459ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 447559ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 447659ac0c16Sdavemq 447759ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 447859ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 447959ac0c16Sdavemq } 448059ac0c16Sdavemq 448144961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 448244961713Sgirish 448344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 448444961713Sgirish } 448544961713Sgirish 448644961713Sgirish /* Declare link up */ 448744961713Sgirish 448844961713Sgirish void 448944961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 449044961713Sgirish { 449159ac0c16Sdavemq p_nxge_stats_t statsp; 449259ac0c16Sdavemq char link_stat_msg[64]; 449344961713Sgirish uint32_t val; 449444961713Sgirish 449544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 449644961713Sgirish 449759ac0c16Sdavemq statsp = nxgep->statsp; 449859ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 449959ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 450059ac0c16Sdavemq statsp->mac_stats.link_speed); 450159ac0c16Sdavemq 450259ac0c16Sdavemq if (statsp->mac_stats.link_T4) 450359ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 450459ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 450559ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 450659ac0c16Sdavemq else 450759ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 450859ac0c16Sdavemq 450944961713Sgirish (void) nxge_xif_init(nxgep); 451044961713Sgirish 451144961713Sgirish /* Clean up symbol errors incurred during link transition */ 45122e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 45132e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 451444961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 451544961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 451644961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 451744961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 451844961713Sgirish } 451944961713Sgirish 452059ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 452159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 452259ac0c16Sdavemq } 452359ac0c16Sdavemq 452444961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 452544961713Sgirish 452644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 452744961713Sgirish } 452844961713Sgirish 452944961713Sgirish /* 453044961713Sgirish * Calculate the bit in the multicast address filter 453144961713Sgirish * that selects the given * address. 453244961713Sgirish * Note: For GEM, the last 8-bits are used. 453344961713Sgirish */ 453444961713Sgirish uint32_t 453544961713Sgirish crc32_mchash(p_ether_addr_t addr) 453644961713Sgirish { 453744961713Sgirish uint8_t *cp; 453844961713Sgirish uint32_t crc; 453944961713Sgirish uint32_t c; 454044961713Sgirish int byte; 454144961713Sgirish int bit; 454244961713Sgirish 454344961713Sgirish cp = (uint8_t *)addr; 454444961713Sgirish crc = (uint32_t)0xffffffff; 454544961713Sgirish for (byte = 0; byte < 6; byte++) { 454644961713Sgirish c = (uint32_t)cp[byte]; 454744961713Sgirish for (bit = 0; bit < 8; bit++) { 454844961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 454944961713Sgirish crc = (crc >> 1)^0xedb88320; 455044961713Sgirish else 455144961713Sgirish crc = (crc >> 1); 455244961713Sgirish c >>= 1; 455344961713Sgirish } 455444961713Sgirish } 455544961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 455644961713Sgirish } 455744961713Sgirish 455844961713Sgirish /* Reset serdes */ 455944961713Sgirish 456044961713Sgirish nxge_status_t 456144961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 456244961713Sgirish { 456344961713Sgirish npi_handle_t handle; 456444961713Sgirish 456544961713Sgirish handle = nxgep->npi_handle; 456644961713Sgirish 456744961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 456844961713Sgirish drv_usecwait(500); 456944961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 457044961713Sgirish 457144961713Sgirish return (NXGE_OK); 457244961713Sgirish } 457344961713Sgirish 457444961713Sgirish /* Monitor link status using interrupt or polling */ 457544961713Sgirish 457644961713Sgirish nxge_status_t 457744961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 457844961713Sgirish { 457944961713Sgirish nxge_status_t status = NXGE_OK; 458044961713Sgirish 458144961713Sgirish /* 458298ecde52Stm * Return immediately if this is an imaginary XMAC port. 458398ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 458444961713Sgirish */ 45852e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 45862e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 45872e59129aSraghus (nxgep->mac.portnum > 1)) 458844961713Sgirish return (NXGE_OK); 458944961713Sgirish 459044961713Sgirish if (nxgep->statsp == NULL) { 459144961713Sgirish /* stats has not been allocated. */ 459244961713Sgirish return (NXGE_OK); 459344961713Sgirish } 4594*321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 4595*321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 459644961713Sgirish return (NXGE_OK); 459744961713Sgirish 459844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 459998ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 460098ecde52Stm nxgep->mac.portnum, enable)); 460144961713Sgirish if (enable == LINK_MONITOR_START) { 460244961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 460344961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 460498ecde52Stm != NXGE_OK) 460544961713Sgirish goto fail; 460644961713Sgirish } else { 460798ecde52Stm timeout_id_t timerid; 460898ecde52Stm 460998ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 461098ecde52Stm return (NXGE_OK); 461198ecde52Stm 461259ac0c16Sdavemq if (nxgep->xcvr.check_link) { 461359ac0c16Sdavemq timerid = timeout( 461459ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 461598ecde52Stm nxgep, 461698ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 461759ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 461859ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 461959ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 462059ac0c16Sdavemq } else { 462198ecde52Stm return (NXGE_ERROR); 462244961713Sgirish } 462344961713Sgirish } 462444961713Sgirish } else { 462544961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 462644961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 462798ecde52Stm != NXGE_OK) 462844961713Sgirish goto fail; 462944961713Sgirish } else { 463098ecde52Stm clock_t rv; 463198ecde52Stm 463298ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 463398ecde52Stm 463498ecde52Stm /* If <timerid> == 0, the link monitor has */ 463598ecde52Stm /* never been started, or just now stopped. */ 463698ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 463798ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 463898ecde52Stm return (NXGE_OK); 463998ecde52Stm } 464098ecde52Stm 464198ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 464298ecde52Stm rv = cv_timedwait(&nxgep->poll_cv, 464398ecde52Stm &nxgep->poll_lock, 464498ecde52Stm ddi_get_lbolt() + 464598ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 464698ecde52Stm LINK_MONITOR_PERIOD)); 464798ecde52Stm if (rv == -1) { 464898ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 464998ecde52Stm "==> stopping port %d: " 465098ecde52Stm "cv_timedwait(%d) timed out", 465198ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 465298ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 465344961713Sgirish nxgep->nxge_link_poll_timerid = 0; 465444961713Sgirish } 465598ecde52Stm 465698ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 465744961713Sgirish } 465844961713Sgirish } 465944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 466098ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 466198ecde52Stm nxgep->mac.portnum, enable)); 466244961713Sgirish return (NXGE_OK); 466344961713Sgirish fail: 466444961713Sgirish return (status); 466544961713Sgirish } 466644961713Sgirish 466744961713Sgirish /* Set promiscous mode */ 466844961713Sgirish 466944961713Sgirish nxge_status_t 467044961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 467144961713Sgirish { 467244961713Sgirish nxge_status_t status = NXGE_OK; 467344961713Sgirish 467459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 467544961713Sgirish 467644961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 467744961713Sgirish 467844961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 467944961713Sgirish 468044961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 468144961713Sgirish goto fail; 468244961713Sgirish } 468344961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 468444961713Sgirish goto fail; 468544961713Sgirish } 468644961713Sgirish 468744961713Sgirish RW_EXIT(&nxgep->filter_lock); 468844961713Sgirish 468944961713Sgirish if (on) 469044961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 469144961713Sgirish else 469244961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 469344961713Sgirish 469444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 469544961713Sgirish 469644961713Sgirish return (NXGE_OK); 469744961713Sgirish fail: 469844961713Sgirish RW_EXIT(&nxgep->filter_lock); 469944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 470059ac0c16Sdavemq "Unable to set promisc (%d)", on)); 470144961713Sgirish 470244961713Sgirish return (status); 470344961713Sgirish } 470444961713Sgirish 470544961713Sgirish /*ARGSUSED*/ 470644961713Sgirish uint_t 470744961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 470844961713Sgirish { 470944961713Sgirish #ifdef NXGE_DEBUG 471044961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 471144961713Sgirish #endif 471244961713Sgirish #if NXGE_MIF 471344961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 471444961713Sgirish uint32_t status; 471544961713Sgirish npi_handle_t handle; 471644961713Sgirish uint8_t portn; 471744961713Sgirish p_nxge_stats_t statsp; 471844961713Sgirish #endif 471944961713Sgirish 472044961713Sgirish #ifdef NXGE_MIF 472144961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 472244961713Sgirish nxgep = ldvp->nxgep; 472344961713Sgirish } 472444961713Sgirish nxgep = ldvp->nxgep; 472544961713Sgirish #endif 472644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 472744961713Sgirish 472844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 472944961713Sgirish return (DDI_INTR_CLAIMED); 473044961713Sgirish 473144961713Sgirish mif_intr_fail: 473244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 473344961713Sgirish return (DDI_INTR_UNCLAIMED); 473444961713Sgirish } 473544961713Sgirish 473644961713Sgirish /*ARGSUSED*/ 473744961713Sgirish uint_t 473844961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 473944961713Sgirish { 474044961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 474144961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 474244961713Sgirish p_nxge_ldg_t ldgp; 474344961713Sgirish uint32_t status; 474444961713Sgirish npi_handle_t handle; 474544961713Sgirish uint8_t portn; 474644961713Sgirish p_nxge_stats_t statsp; 474744961713Sgirish npi_status_t rs = NPI_SUCCESS; 474844961713Sgirish 474944961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 475044961713Sgirish nxgep = ldvp->nxgep; 475144961713Sgirish } 475244961713Sgirish 475344961713Sgirish ldgp = ldvp->ldgp; 475444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 475559ac0c16Sdavemq "group %d", ldgp->ldg)); 475644961713Sgirish 475744961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 475844961713Sgirish /* 475944961713Sgirish * This interrupt handler is for a specific 476044961713Sgirish * mac port. 476144961713Sgirish */ 476244961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 476344961713Sgirish portn = nxgep->mac.portnum; 476444961713Sgirish 476544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 476659ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 476744961713Sgirish 476844961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 476944961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 477044961713Sgirish (xmac_tx_iconfig_t *)&status); 477144961713Sgirish if (rs != NPI_SUCCESS) 477244961713Sgirish goto npi_fail; 477344961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 477444961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 477544961713Sgirish statsp->xmac_stats.tx_underflow_err++; 477644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 477744961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 477844961713Sgirish } 477944961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 478044961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 4781f6485eecSyc /* 4782f6485eecSyc * Do not send FMA ereport because this 4783f6485eecSyc * error does not indicate HW failure. 4784f6485eecSyc */ 478544961713Sgirish } 478644961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 478744961713Sgirish statsp->xmac_stats.tx_overflow_err++; 478844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 478944961713Sgirish NXGE_FM_EREPORT_TXMAC_OVERFLOW); 479044961713Sgirish } 479144961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 479244961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 479344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 479444961713Sgirish NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 479544961713Sgirish } 479644961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 479744961713Sgirish statsp->xmac_stats.tx_byte_cnt += 479844961713Sgirish XTXMAC_BYTE_CNT_MASK; 479944961713Sgirish } 480044961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 480144961713Sgirish statsp->xmac_stats.tx_frame_cnt += 480244961713Sgirish XTXMAC_FRM_CNT_MASK; 480344961713Sgirish } 480444961713Sgirish } 480544961713Sgirish 480644961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 480744961713Sgirish (xmac_rx_iconfig_t *)&status); 480844961713Sgirish if (rs != NPI_SUCCESS) 480944961713Sgirish goto npi_fail; 481044961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 481144961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 481244961713Sgirish statsp->xmac_stats.rx_overflow_err++; 481344961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 481444961713Sgirish statsp->xmac_stats.rx_underflow_err++; 481544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 481644961713Sgirish NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 481744961713Sgirish } 4818f6485eecSyc /* 4819f6485eecSyc * Do not send FMA ereport for the following 3 errors 4820f6485eecSyc * because they do not indicate HW failures. 4821f6485eecSyc */ 482244961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 482344961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 482444961713Sgirish XRXMAC_CRC_ER_CNT_MASK; 482544961713Sgirish } 482644961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 482744961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 482844961713Sgirish MAC_LEN_ER_CNT_MASK; 482944961713Sgirish } 483044961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 483144961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 483244961713Sgirish XRXMAC_CD_VIO_CNT_MASK; 483344961713Sgirish } 483444961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 483544961713Sgirish statsp->xmac_stats.rx_byte_cnt += 483644961713Sgirish XRXMAC_BT_CNT_MASK; 483744961713Sgirish } 483844961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 483944961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 484044961713Sgirish XRXMAC_HIST_CNT1_MASK; 484144961713Sgirish } 484244961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 484344961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 484444961713Sgirish XRXMAC_HIST_CNT2_MASK; 484544961713Sgirish } 484644961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 484744961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 484844961713Sgirish XRXMAC_HIST_CNT3_MASK; 484944961713Sgirish } 485044961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 485144961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 485244961713Sgirish XRXMAC_HIST_CNT4_MASK; 485344961713Sgirish } 485444961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 485544961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 485644961713Sgirish XRXMAC_HIST_CNT5_MASK; 485744961713Sgirish } 485844961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 485944961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 486044961713Sgirish XRXMAC_HIST_CNT6_MASK; 486144961713Sgirish } 486244961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 486344961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 486444961713Sgirish XRXMAC_BC_FRM_CNT_MASK; 486544961713Sgirish } 486644961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 486744961713Sgirish statsp->xmac_stats.rx_mult_cnt += 486844961713Sgirish XRXMAC_MC_FRM_CNT_MASK; 486944961713Sgirish } 4870f6485eecSyc /* 4871f6485eecSyc * Do not send FMA ereport for the following 3 errors 4872f6485eecSyc * because they do not indicate HW failures. 4873f6485eecSyc */ 487444961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 487544961713Sgirish statsp->xmac_stats.rx_frag_cnt += 487644961713Sgirish XRXMAC_FRAG_CNT_MASK; 487744961713Sgirish } 487844961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 487944961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 488044961713Sgirish XRXMAC_AL_ER_CNT_MASK; 488144961713Sgirish } 488244961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 488344961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 488444961713Sgirish XMAC_LINK_FLT_CNT_MASK; 488544961713Sgirish } 488644961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 488744961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 488844961713Sgirish } 488944961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 489044961713Sgirish statsp->xmac_stats.rx_localfault_err++; 489144961713Sgirish } 489244961713Sgirish } 489344961713Sgirish 489444961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 489544961713Sgirish (xmac_ctl_iconfig_t *)&status); 489644961713Sgirish if (rs != NPI_SUCCESS) 489744961713Sgirish goto npi_fail; 489844961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 489944961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 490044961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 490144961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 490244961713Sgirish statsp->xmac_stats.tx_pause_state++; 490344961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 490444961713Sgirish statsp->xmac_stats.tx_nopause_state++; 490544961713Sgirish } 490644961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 490744961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 490844961713Sgirish (bmac_tx_iconfig_t *)&status); 490944961713Sgirish if (rs != NPI_SUCCESS) 491044961713Sgirish goto npi_fail; 491144961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 491244961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 491344961713Sgirish statsp->bmac_stats.tx_underrun_err++; 491444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 491544961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 491644961713Sgirish } 491744961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 491844961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 491944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 492044961713Sgirish NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 492144961713Sgirish } 492244961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 492344961713Sgirish statsp->bmac_stats.tx_byte_cnt += 492444961713Sgirish BTXMAC_BYTE_CNT_MASK; 492544961713Sgirish } 492644961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 492744961713Sgirish statsp->bmac_stats.tx_frame_cnt += 492844961713Sgirish BTXMAC_FRM_CNT_MASK; 492944961713Sgirish } 493044961713Sgirish } 493144961713Sgirish 493244961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 493344961713Sgirish (bmac_rx_iconfig_t *)&status); 493444961713Sgirish if (rs != NPI_SUCCESS) 493544961713Sgirish goto npi_fail; 493644961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 493744961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 493844961713Sgirish statsp->bmac_stats.rx_overflow_err++; 493944961713Sgirish } 494044961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 494144961713Sgirish statsp->bmac_stats.rx_frame_cnt += 494244961713Sgirish RXMAC_FRM_CNT_MASK; 494344961713Sgirish } 494444961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 494544961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 494644961713Sgirish BMAC_CRC_ER_CNT_MASK; 494744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 494844961713Sgirish NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 494944961713Sgirish } 495044961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 495144961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 495244961713Sgirish MAC_LEN_ER_CNT_MASK; 495344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 495444961713Sgirish NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 495544961713Sgirish } 495644961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 495744961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 495844961713Sgirish BMAC_CD_VIO_CNT_MASK; 495944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 496044961713Sgirish NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 496144961713Sgirish } 496244961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 496344961713Sgirish statsp->bmac_stats.rx_byte_cnt += 496444961713Sgirish BRXMAC_BYTE_CNT_MASK; 496544961713Sgirish } 496644961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 496744961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 496844961713Sgirish BMAC_AL_ER_CNT_MASK; 496944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 497044961713Sgirish NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 497144961713Sgirish } 497244961713Sgirish 497344961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 497444961713Sgirish (bmac_ctl_iconfig_t *)&status); 497544961713Sgirish if (rs != NPI_SUCCESS) 497644961713Sgirish goto npi_fail; 497744961713Sgirish 497844961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 497944961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 498044961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 498144961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 498244961713Sgirish statsp->bmac_stats.tx_pause_state++; 498344961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 498444961713Sgirish statsp->bmac_stats.tx_nopause_state++; 498544961713Sgirish } 498644961713Sgirish } 498744961713Sgirish 498844961713Sgirish if (ldgp->nldvs == 1) { 498944961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 499044961713Sgirish B_TRUE, ldgp->ldg_timer); 499144961713Sgirish } 499244961713Sgirish 499344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 499444961713Sgirish return (DDI_INTR_CLAIMED); 499544961713Sgirish 499644961713Sgirish npi_fail: 499744961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 499844961713Sgirish return (DDI_INTR_UNCLAIMED); 499944961713Sgirish } 500044961713Sgirish 500144961713Sgirish nxge_status_t 500244961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 500344961713Sgirish { 500444961713Sgirish uint8_t phy_port_addr; 500544961713Sgirish nxge_status_t status = NXGE_OK; 500644961713Sgirish boolean_t rx_sig_ok; 500744961713Sgirish boolean_t pcs_blk_lock; 500844961713Sgirish boolean_t link_align; 500944961713Sgirish uint16_t val1, val2, val3; 501044961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 501144961713Sgirish uint16_t val_debug; 501244961713Sgirish uint16_t val; 501344961713Sgirish #endif 501444961713Sgirish 501544961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 501644961713Sgirish 501744961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 501844961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 501944961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 502044961713Sgirish if ((val_debug & ~0x200) != 0) { 502144961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 502244961713Sgirish nxgep->mac.portnum, val_debug); 502344961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 502444961713Sgirish &val_debug); 502544961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 502644961713Sgirish nxgep->mac.portnum, val_debug); 502744961713Sgirish } 502844961713Sgirish 502944961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 503044961713Sgirish XPCS_REG_DESCWERR_COUNTER, &val); 503144961713Sgirish if (val != 0) 503244961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 503344961713Sgirish 503444961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 503544961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 503644961713Sgirish if (val != 0) 503744961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 503844961713Sgirish 503944961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 504044961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 504144961713Sgirish if (val != 0) 504244961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 504344961713Sgirish #endif 504444961713Sgirish 504544961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 504644961713Sgirish 504744961713Sgirish /* Check Device 1 Register 0xA bit0 */ 504844961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 504944961713Sgirish BCM8704_PMA_PMD_DEV_ADDR, 505044961713Sgirish BCM8704_PMD_RECEIVE_SIG_DETECT, 505144961713Sgirish &val1); 505244961713Sgirish if (status != NXGE_OK) 505344961713Sgirish goto fail; 505444961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 505544961713Sgirish 505644961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 505744961713Sgirish if ((status = nxge_mdio_read(nxgep, phy_port_addr, 505844961713Sgirish BCM8704_PCS_DEV_ADDR, 505944961713Sgirish BCM8704_10GBASE_R_PCS_STATUS_REG, 506044961713Sgirish &val2)) != NPI_SUCCESS) 506144961713Sgirish goto fail; 506244961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 506344961713Sgirish 506444961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 506544961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 506644961713Sgirish BCM8704_PHYXS_ADDR, 506744961713Sgirish BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 506844961713Sgirish &val3); 506944961713Sgirish if (status != NXGE_OK) 507044961713Sgirish goto fail; 50712d17280bSsbehera 50722d17280bSsbehera switch (nxgep->chip_id) { 50732d17280bSsbehera case BCM8704_CHIP_ID: 50742d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 50752d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 50762d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 50772d17280bSsbehera break; 50782d17280bSsbehera case BCM8706_CHIP_ID: 50792d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 50802d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 50812d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 50822d17280bSsbehera B_TRUE : B_FALSE; 50832d17280bSsbehera break; 50842d17280bSsbehera default: 50852d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 50862d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 50872d17280bSsbehera goto fail; 50882d17280bSsbehera } 50892d17280bSsbehera 509044961713Sgirish 509144961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 509244961713Sgirish /* Temp workaround for link down issue */ 509344961713Sgirish if (pcs_blk_lock == B_FALSE) { 509444961713Sgirish if (val2 != 0x4) { 509544961713Sgirish pcs_blk_lock = B_TRUE; 509644961713Sgirish cmn_err(CE_NOTE, 509744961713Sgirish "!LINK DEBUG: port%d PHY Dev3 " 509844961713Sgirish "Reg 0x20 = 0x%x\n", 509944961713Sgirish nxgep->mac.portnum, val2); 510044961713Sgirish } 510144961713Sgirish } 510244961713Sgirish 510344961713Sgirish if (link_align == B_FALSE) { 510444961713Sgirish if (val3 != 0x140f) { 510544961713Sgirish link_align = B_TRUE; 510644961713Sgirish cmn_err(CE_NOTE, 510744961713Sgirish "!LINK DEBUG: port%d PHY Dev4 " 510844961713Sgirish "Reg 0x18 = 0x%x\n", 510944961713Sgirish nxgep->mac.portnum, val3); 511044961713Sgirish } 511144961713Sgirish } 511244961713Sgirish 511344961713Sgirish if (rx_sig_ok == B_FALSE) { 511444961713Sgirish if ((val2 == 0) || (val3 == 0)) { 511544961713Sgirish rx_sig_ok = B_TRUE; 511644961713Sgirish cmn_err(CE_NOTE, 511744961713Sgirish "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 511844961713Sgirish nxgep->mac.portnum); 511944961713Sgirish } 512044961713Sgirish } 512144961713Sgirish #endif 512244961713Sgirish 512344961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 512444961713Sgirish (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 512544961713Sgirish 512644961713Sgirish return (NXGE_OK); 512744961713Sgirish fail: 512844961713Sgirish return (status); 512944961713Sgirish } 513044961713Sgirish 513159ac0c16Sdavemq nxge_status_t 513259ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 513359ac0c16Sdavemq { 513459ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 513559ac0c16Sdavemq != NPI_SUCCESS) 513659ac0c16Sdavemq return (NXGE_ERROR); 513759ac0c16Sdavemq else 513859ac0c16Sdavemq return (NXGE_OK); 513959ac0c16Sdavemq } 514044961713Sgirish 514144961713Sgirish nxge_status_t 514259ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 514344961713Sgirish { 514459ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 514559ac0c16Sdavemq != NPI_SUCCESS) 514659ac0c16Sdavemq return (NXGE_ERROR); 514759ac0c16Sdavemq else 514859ac0c16Sdavemq return (NXGE_OK); 514959ac0c16Sdavemq } 515044961713Sgirish 51512d17280bSsbehera static boolean_t 51522d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 51532d17280bSsbehera { 51542d17280bSsbehera uint32_t pma_pmd_id = 0; 51552d17280bSsbehera uint32_t pcs_id = 0; 51562d17280bSsbehera uint32_t phy_id = 0; 51572d17280bSsbehera 51582d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 51592d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51602d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 51612d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 51622d17280bSsbehera goto found_phy; 51632d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 51642d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51652d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 51662d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 51672d17280bSsbehera goto found_phy; 51682d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 51692d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51702d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 51712d17280bSsbehera if ((phy_id & mask) == (id & mask)) 51722d17280bSsbehera goto found_phy; 51732d17280bSsbehera 51742d17280bSsbehera return (B_FALSE); 51752d17280bSsbehera 51762d17280bSsbehera found_phy: 51772d17280bSsbehera return (B_TRUE); 51782d17280bSsbehera } 51792d17280bSsbehera 518059ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 518159ac0c16Sdavemq 518259ac0c16Sdavemq static boolean_t 518359ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 518459ac0c16Sdavemq { 518559ac0c16Sdavemq int i; 518659ac0c16Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 518759ac0c16Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 518859ac0c16Sdavemq boolean_t found = B_FALSE; 518959ac0c16Sdavemq 519059ac0c16Sdavemq switch (type) { 519159ac0c16Sdavemq case CLAUSE_45_TYPE: 519259ac0c16Sdavemq for (i = 0; i < cl45_arr_len; i++) { 519330505775Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 519430505775Ssbehera (id & BCM_PHY_ID_MASK)) { 519559ac0c16Sdavemq found = B_TRUE; 519659ac0c16Sdavemq break; 519759ac0c16Sdavemq } 519859ac0c16Sdavemq } 519959ac0c16Sdavemq break; 520059ac0c16Sdavemq case CLAUSE_22_TYPE: 520159ac0c16Sdavemq for (i = 0; i < cl22_arr_len; i++) { 520230505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 520330505775Ssbehera (id & BCM_PHY_ID_MASK)) { 520459ac0c16Sdavemq found = B_TRUE; 520559ac0c16Sdavemq break; 520656d930aeSspeer } 520744961713Sgirish } 520859ac0c16Sdavemq break; 520959ac0c16Sdavemq default: 521059ac0c16Sdavemq break; 521156d930aeSspeer } 521256d930aeSspeer 521359ac0c16Sdavemq return (found); 521459ac0c16Sdavemq } 521559ac0c16Sdavemq 52162e59129aSraghus static uint32_t 52172e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 52182e59129aSraghus { 52192e59129aSraghus uint16_t val1 = 0; 52202e59129aSraghus uint16_t val2 = 0; 52212e59129aSraghus uint32_t pma_pmd_dev_id = 0; 52222e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 52232e59129aSraghus 522453560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 52252e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 52262e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 52272e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 52282e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 522953560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 52302e59129aSraghus 52312e59129aSraghus pma_pmd_dev_id = val1; 52322e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 52332e59129aSraghus pma_pmd_dev_id |= val2; 52342e59129aSraghus 52352e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 52362e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 52372e59129aSraghus 52382e59129aSraghus return (pma_pmd_dev_id); 52392e59129aSraghus } 52402e59129aSraghus 52412e59129aSraghus static uint32_t 52422e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 52432e59129aSraghus { 52442e59129aSraghus uint16_t val1 = 0; 52452e59129aSraghus uint16_t val2 = 0; 52462e59129aSraghus uint32_t pcs_dev_id = 0; 52472e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 52482e59129aSraghus 524953560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 52502e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 52512e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 52522e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 52532e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 525453560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 52552e59129aSraghus 52562e59129aSraghus pcs_dev_id = val1; 52572e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 52582e59129aSraghus pcs_dev_id |= val2; 52592e59129aSraghus 52602e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 52612e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 52622e59129aSraghus 52632e59129aSraghus return (pcs_dev_id); 52642e59129aSraghus } 52652e59129aSraghus 52662e59129aSraghus static uint32_t 52672e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 52682e59129aSraghus { 52692e59129aSraghus uint16_t val1 = 0; 52702e59129aSraghus uint16_t val2 = 0; 52712e59129aSraghus uint32_t phy_id = 0; 52722e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 52732e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 52742e59129aSraghus 5275*321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 52762e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 52772e59129aSraghus &val1); 52782e59129aSraghus if (npi_status != NPI_SUCCESS) { 52792e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 52802e59129aSraghus "clause 22 read to reg 2 failed!!!")); 52812e59129aSraghus goto exit; 52822e59129aSraghus } 52832e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 52842e59129aSraghus &val2); 52852e59129aSraghus if (npi_status != 0) { 52862e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 52872e59129aSraghus "clause 22 read to reg 3 failed!!!")); 52882e59129aSraghus goto exit; 52892e59129aSraghus } 52902e59129aSraghus phy_id = val1; 52912e59129aSraghus phy_id = (phy_id << 16); 52922e59129aSraghus phy_id |= val2; 52932e59129aSraghus 52942e59129aSraghus exit: 5295*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 52962e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 52972e59129aSraghus phy_port, phy_id)); 52982e59129aSraghus 52992e59129aSraghus return (phy_id); 53002e59129aSraghus } 53012e59129aSraghus 530259ac0c16Sdavemq /* 530359ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 530459ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 530559ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 530659ac0c16Sdavemq * and the Neptune type. 530759ac0c16Sdavemq */ 530859ac0c16Sdavemq 530959ac0c16Sdavemq nxge_status_t 531059ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 531159ac0c16Sdavemq { 531259ac0c16Sdavemq int i, j, k, l; 531359ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 531459ac0c16Sdavemq uint32_t pcs_dev_id = 0; 531559ac0c16Sdavemq uint32_t phy_id = 0; 531630505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 531730505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 531830505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 531959ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 532059ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 53212d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 53222d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 532359ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 532459ac0c16Sdavemq nxge_status_t status = NXGE_OK; 532556d930aeSspeer 532659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 532756d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 532859ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 532959ac0c16Sdavemq nxgep->niu_type)); 533059ac0c16Sdavemq 533159ac0c16Sdavemq j = k = l = 0; 533259ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 533356d930aeSspeer /* 533459ac0c16Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 533559ac0c16Sdavemq * for on chip serdes usages. 533656d930aeSspeer */ 533759ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 53382e59129aSraghus 53392e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 534059ac0c16Sdavemq 534159ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 534259ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 534359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 534459ac0c16Sdavemq "PMA/PMD dev found", i)); 534530505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 534630505775Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 534730505775Ssbehera BCM_PHY_ID_MASK; 53482d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 534959ac0c16Sdavemq j++; 535059ac0c16Sdavemq } 535159ac0c16Sdavemq } else { 535259ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 535359ac0c16Sdavemq } 535459ac0c16Sdavemq 53552e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 535659ac0c16Sdavemq 535759ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 535859ac0c16Sdavemq pcs_dev_fd[i] = 1; 535959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 536059ac0c16Sdavemq "dev found", i)); 536130505775Ssbehera if (k < NXGE_PORTS_NEPTUNE) { 536230505775Ssbehera port_pcs_dev_id[k] = pcs_dev_id & 536330505775Ssbehera BCM_PHY_ID_MASK; 53642d17280bSsbehera port_fd_arr[k] = (uint8_t)i; 536559ac0c16Sdavemq k++; 536659ac0c16Sdavemq } 536759ac0c16Sdavemq } else { 536859ac0c16Sdavemq pcs_dev_fd[i] = 0; 536959ac0c16Sdavemq } 537059ac0c16Sdavemq 53712d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 53722d17280bSsbehera total_port_fd ++; 53732d17280bSsbehera } 537459ac0c16Sdavemq 53752e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 537659ac0c16Sdavemq 537759ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 53782d17280bSsbehera total_phy_fd ++; 537959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 538059ac0c16Sdavemq "found", i)); 538130505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 538230505775Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 53832d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 538459ac0c16Sdavemq l++; 538559ac0c16Sdavemq } 538659ac0c16Sdavemq } 538759ac0c16Sdavemq } 538859ac0c16Sdavemq 538959ac0c16Sdavemq switch (total_port_fd) { 539059ac0c16Sdavemq case 2: 539159ac0c16Sdavemq switch (total_phy_fd) { 539259ac0c16Sdavemq case 2: 53932e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53942e59129aSraghus "Unsupported neptune type 1")); 53952e59129aSraghus goto error_exit; 539659ac0c16Sdavemq case 1: 539759ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 539859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 539959ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 540059ac0c16Sdavemq goto error_exit; 540159ac0c16Sdavemq case 0: 540259ac0c16Sdavemq /* 2 10G */ 540330505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 540430505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 540530505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 540630505775Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 54072e59129aSraghus 54082e59129aSraghus /* 54092e59129aSraghus * Check the first phy port address against 54102e59129aSraghus * the known phy start addresses to determine 54112e59129aSraghus * the platform type. 54122e59129aSraghus */ 54132d17280bSsbehera 54142d17280bSsbehera switch (port_fd_arr[0]) { 54152d17280bSsbehera case BCM8704_NEPTUNE_PORT_ADDR_BASE: 54162e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 54172e59129aSraghus hw_p->platform_type = 54182e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 54192d17280bSsbehera break; 54202d17280bSsbehera case BCM8706_GOA_PORT_ADDR_BASE: 54212d17280bSsbehera if (hw_p->platform_type != 54222d17280bSsbehera P_NEPTUNE_NIU) { 54232d17280bSsbehera hw_p->platform_type = 54242d17280bSsbehera P_NEPTUNE_GENERIC; 54252d17280bSsbehera hw_p->niu_type = 54262d17280bSsbehera NEPTUNE_2_10GF; 54272d17280bSsbehera } 54282d17280bSsbehera break; 54292d17280bSsbehera default: 54302d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 54312e59129aSraghus "Unsupported neptune type 2 - 1")); 54322e59129aSraghus goto error_exit; 54332e59129aSraghus } 54342d17280bSsbehera 54352d17280bSsbehera for (i = 0; i < 2; i++) { 54362d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 54372d17280bSsbehera } 543859ac0c16Sdavemq } else { 543959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 544059ac0c16Sdavemq "Unsupported neptune type 2")); 544159ac0c16Sdavemq goto error_exit; 544259ac0c16Sdavemq } 544359ac0c16Sdavemq break; 544459ac0c16Sdavemq case 4: 544559ac0c16Sdavemq /* Maramba with 2 XAUI */ 544630505775Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 544730505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 544830505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 544930505775Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 545030505775Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 545130505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 545230505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 545330505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 545459ac0c16Sdavemq 545559ac0c16Sdavemq /* 545659ac0c16Sdavemq * Check the first phy port address against 545759ac0c16Sdavemq * the known phy start addresses to determine 545859ac0c16Sdavemq * the platform type. 545959ac0c16Sdavemq */ 54602d17280bSsbehera switch (phy_fd_arr[0]) { 54612d17280bSsbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 546259ac0c16Sdavemq hw_p->platform_type = 546359ac0c16Sdavemq P_NEPTUNE_MARAMBA_P0; 54642d17280bSsbehera break; 54652d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 546659ac0c16Sdavemq hw_p->platform_type = 546759ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 54682d17280bSsbehera break; 54692d17280bSsbehera default: 547059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 547159ac0c16Sdavemq "Unknown port %d...Cannot " 547259ac0c16Sdavemq "determine platform type", i)); 54732e59129aSraghus goto error_exit; 547459ac0c16Sdavemq } 54752d17280bSsbehera 54762e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 54772e59129aSraghus 54782d17280bSsbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 54792d17280bSsbehera hw_p->xcvr_addr[1] = port_fd_arr[1]; 54802d17280bSsbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 54812d17280bSsbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 54822d17280bSsbehera 548359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 548459ac0c16Sdavemq "Maramba with 2 XAUI")); 548559ac0c16Sdavemq } else { 548659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 548759ac0c16Sdavemq "Unsupported neptune type 3")); 548859ac0c16Sdavemq goto error_exit; 548959ac0c16Sdavemq } 549059ac0c16Sdavemq break; 549159ac0c16Sdavemq default: 549259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 549359ac0c16Sdavemq "Unsupported neptune type 5")); 549459ac0c16Sdavemq goto error_exit; 549559ac0c16Sdavemq } 549630505775Ssbehera break; 549759ac0c16Sdavemq case 1: 549859ac0c16Sdavemq switch (total_phy_fd) { 549959ac0c16Sdavemq case 3: 55002e59129aSraghus /* 55012e59129aSraghus * TODO 3 1G, 1 10G mode. 55022e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 55032e59129aSraghus * 1_10G_3_1G 55042e59129aSraghus */ 55052e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55062e59129aSraghus "Unsupported neptune type 7")); 55072e59129aSraghus goto error_exit; 550859ac0c16Sdavemq case 2: 550959ac0c16Sdavemq /* 551059ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 551159ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 551259ac0c16Sdavemq * 1_10G_2_1G 551359ac0c16Sdavemq */ 551459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 551559ac0c16Sdavemq "Unsupported neptune type 8")); 551659ac0c16Sdavemq goto error_exit; 551759ac0c16Sdavemq case 1: 551859ac0c16Sdavemq /* 551959ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 552059ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 552159ac0c16Sdavemq * 1_10G_1_1G 552259ac0c16Sdavemq */ 552359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 552459ac0c16Sdavemq "Unsupported neptune type 9")); 552559ac0c16Sdavemq goto error_exit; 552659ac0c16Sdavemq case 0: 55272d17280bSsbehera /* 1 10G mode, N2 with 1 XAUI */ 55282d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 55292d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 55302d17280bSsbehera 55312d17280bSsbehera /* 55322d17280bSsbehera * Check the first phy port address against 55332d17280bSsbehera * the known phy start addresses to determine 55342d17280bSsbehera * the platform type. 55352d17280bSsbehera */ 55362d17280bSsbehera 55372d17280bSsbehera switch (port_fd_arr[0]) { 55382d17280bSsbehera case BCM8704_N2_PORT_ADDR_BASE: 55392d17280bSsbehera case (BCM8704_N2_PORT_ADDR_BASE + 1): 55402d17280bSsbehera case BCM8706_ALT_GOA_PORT1_ADDR: 55412d17280bSsbehera if (hw_p->platform_type != 55422d17280bSsbehera P_NEPTUNE_NIU) { 55432d17280bSsbehera hw_p->platform_type = 55442d17280bSsbehera P_NEPTUNE_GENERIC; 55452d17280bSsbehera hw_p->niu_type = 55462d17280bSsbehera NEPTUNE_2_10GF; 55472d17280bSsbehera } 55482d17280bSsbehera break; 55492d17280bSsbehera default: 55502d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 55512d17280bSsbehera "Unsupported neptune type 10")); 55522d17280bSsbehera goto error_exit; 55532d17280bSsbehera } 5554*321febdeSsbehera /* 5555*321febdeSsbehera * For GOA, which is a hot swappable PHY, the 5556*321febdeSsbehera * phy address to function number mapping 5557*321febdeSsbehera * should be preserved, i.e., addr 16 is 5558*321febdeSsbehera * assigned to function 0 and 20 to function 1 5559*321febdeSsbehera * But for Huron XAUI, the assignment should 5560*321febdeSsbehera * be by function number, i.e., whichever 5561*321febdeSsbehera * function number attaches should be 5562*321febdeSsbehera * assigned the available PHY (this is required 5563*321febdeSsbehera * primarily to support pre-production Huron 5564*321febdeSsbehera * boards where function 0 is mapped to addr 17 5565*321febdeSsbehera */ 5566*321febdeSsbehera if (port_fd_arr[0] == 5567*321febdeSsbehera BCM8706_ALT_GOA_PORT1_ADDR) { 5568*321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 5569*321febdeSsbehera } else { 5570*321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 5571*321febdeSsbehera port_fd_arr[0]; 5572*321febdeSsbehera } 55732d17280bSsbehera } else { 55742d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 55752d17280bSsbehera "Unsupported neptune type 10 - 1")); 55762d17280bSsbehera goto error_exit; 55772d17280bSsbehera } 55782d17280bSsbehera break; 557959ac0c16Sdavemq case 4: 558059ac0c16Sdavemq /* Maramba with 1 XAUI */ 558130505775Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 558230505775Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 558359ac0c16Sdavemq 558459ac0c16Sdavemq /* 558559ac0c16Sdavemq * Check the first phy port address against 558659ac0c16Sdavemq * the known phy start addresses to determine 558759ac0c16Sdavemq * the platform type. 558859ac0c16Sdavemq */ 55892d17280bSsbehera switch (phy_fd_arr[0]) { 55902d17280bSsbehera case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 559159ac0c16Sdavemq hw_p->platform_type = 559259ac0c16Sdavemq P_NEPTUNE_MARAMBA_P0; 55932d17280bSsbehera break; 55942d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 559559ac0c16Sdavemq hw_p->platform_type = 559659ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 55972d17280bSsbehera break; 55982d17280bSsbehera default: 559959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 560059ac0c16Sdavemq "Unknown port %d...Cannot " 56012d17280bSsbehera "determine platform type 10 - 2", 56022d17280bSsbehera i)); 56032e59129aSraghus goto error_exit; 56042e59129aSraghus } 56052e59129aSraghus 56062d17280bSsbehera /* 56072d17280bSsbehera * Check the BCM8704 address to determine 56082d17280bSsbehera * if XAUI is in port 0 or port 1. 56092d17280bSsbehera */ 56102d17280bSsbehera switch (port_fd_arr[0]) { 56112d17280bSsbehera case BCM8704_MARAMBA_PORT_ADDR_BASE: 56122e59129aSraghus hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 56132d17280bSsbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 56142d17280bSsbehera for (i = 1; i < NXGE_MAX_PORTS; i++) { 56152d17280bSsbehera hw_p->xcvr_addr[i] = 56162d17280bSsbehera phy_fd_arr[i]; 56172d17280bSsbehera } 56182d17280bSsbehera break; 56192d17280bSsbehera case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1): 56202e59129aSraghus hw_p->niu_type = 56212e59129aSraghus NEPTUNE_1_1GC_1_10GF_2_1GC; 56222d17280bSsbehera hw_p->xcvr_addr[0] = phy_fd_arr[0]; 56232d17280bSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 56242d17280bSsbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 56252d17280bSsbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 56262d17280bSsbehera break; 56272d17280bSsbehera default: 56282e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 56292e59129aSraghus "Unsupported neptune type 11")); 56302e59129aSraghus goto error_exit; 563159ac0c16Sdavemq } 563259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 563359ac0c16Sdavemq "Maramba with 1 XAUI")); 563459ac0c16Sdavemq } else { 563559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 563659ac0c16Sdavemq "Unsupported neptune type 12")); 563759ac0c16Sdavemq goto error_exit; 563859ac0c16Sdavemq } 563959ac0c16Sdavemq break; 564059ac0c16Sdavemq default: 564159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 564259ac0c16Sdavemq "Unsupported neptune type 13")); 564359ac0c16Sdavemq goto error_exit; 564459ac0c16Sdavemq } 564559ac0c16Sdavemq break; 564659ac0c16Sdavemq case 0: 564759ac0c16Sdavemq switch (total_phy_fd) { 564859ac0c16Sdavemq case 4: 564930505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 565030505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 565130505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 565230505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 565359ac0c16Sdavemq 565459ac0c16Sdavemq /* 565559ac0c16Sdavemq * Check the first phy port address against 565659ac0c16Sdavemq * the known phy start addresses to determine 565759ac0c16Sdavemq * the platform type. 565859ac0c16Sdavemq */ 56592d17280bSsbehera switch (phy_fd_arr[0]) { 56602d17280bSsbehera case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 566159ac0c16Sdavemq hw_p->platform_type = 566259ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 56632d17280bSsbehera break; 56642d17280bSsbehera case BCM5464_NEPTUNE_PORT_ADDR_BASE: 56652e59129aSraghus hw_p->platform_type = 56662e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 56672d17280bSsbehera break; 56682d17280bSsbehera default: 56692e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 56702e59129aSraghus "Unknown port %d...Cannot " 56712e59129aSraghus "determine platform type", i)); 56722e59129aSraghus goto error_exit; 567359ac0c16Sdavemq } 56742e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 56752d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 56762d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 56772d17280bSsbehera } 567859ac0c16Sdavemq } else { 567959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 568059ac0c16Sdavemq "Unsupported neptune type 14")); 568159ac0c16Sdavemq goto error_exit; 568259ac0c16Sdavemq } 568359ac0c16Sdavemq break; 568459ac0c16Sdavemq case 3: 568559ac0c16Sdavemq /* TODO 3 1G mode */ 568659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 568759ac0c16Sdavemq "Unsupported neptune type 15")); 568859ac0c16Sdavemq goto error_exit; 568959ac0c16Sdavemq case 2: 569059ac0c16Sdavemq /* TODO 2 1G mode */ 569159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 569259ac0c16Sdavemq "Unsupported neptune type 16")); 569359ac0c16Sdavemq goto error_exit; 569459ac0c16Sdavemq case 1: 569559ac0c16Sdavemq /* TODO 1 1G mode */ 569659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 569759ac0c16Sdavemq "Unsupported neptune type 17")); 569859ac0c16Sdavemq goto error_exit; 569959ac0c16Sdavemq default: 570059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 570159ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 570259ac0c16Sdavemq total_phy_fd)); 570359ac0c16Sdavemq goto error_exit; 570459ac0c16Sdavemq } 570559ac0c16Sdavemq break; 570659ac0c16Sdavemq default: 570756d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 570859ac0c16Sdavemq "Unsupported neptune type 19")); 570959ac0c16Sdavemq goto error_exit; 571044961713Sgirish } 571144961713Sgirish 571259ac0c16Sdavemq scan_exit: 571344961713Sgirish 571459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 571559ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 571659ac0c16Sdavemq return (status); 571744961713Sgirish 571859ac0c16Sdavemq error_exit: 571959ac0c16Sdavemq return (NXGE_ERROR); 572044961713Sgirish } 572156d930aeSspeer 572256d930aeSspeer boolean_t 572356d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 572456d930aeSspeer { 572556d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 572656d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 572756d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 572856d930aeSspeer return (B_FALSE); 572956d930aeSspeer else 573056d930aeSspeer return (B_TRUE); 573156d930aeSspeer } 573259ac0c16Sdavemq 573359ac0c16Sdavemq static void 573459ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 573559ac0c16Sdavemq 573659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 573759ac0c16Sdavemq uint8_t xcvr_portn; 573859ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 573959ac0c16Sdavemq 574059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 574159ac0c16Sdavemq 574259ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 574359ac0c16Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 574459ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 574559ac0c16Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 574659ac0c16Sdavemq } 574759ac0c16Sdavemq /* 574859ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 574959ac0c16Sdavemq * swapped with ethernet port number. This is 575059ac0c16Sdavemq * designed for better signal integrity in routing. 575159ac0c16Sdavemq */ 575259ac0c16Sdavemq switch (portn) { 575359ac0c16Sdavemq case 0: 575459ac0c16Sdavemq xcvr_portn += 3; 575559ac0c16Sdavemq break; 575659ac0c16Sdavemq case 1: 575759ac0c16Sdavemq xcvr_portn += 2; 575859ac0c16Sdavemq break; 575959ac0c16Sdavemq case 2: 576059ac0c16Sdavemq xcvr_portn += 1; 576159ac0c16Sdavemq break; 576259ac0c16Sdavemq case 3: 576359ac0c16Sdavemq default: 576459ac0c16Sdavemq break; 576559ac0c16Sdavemq } 576659ac0c16Sdavemq 5767*321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 576859ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 576959ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 577059ac0c16Sdavemq if (rs != NPI_SUCCESS) { 577159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 577259ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 577359ac0c16Sdavemq "returned error 0x[%x]", rs)); 5774*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 577559ac0c16Sdavemq return; 577659ac0c16Sdavemq } 577759ac0c16Sdavemq 577859ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 577959ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 578059ac0c16Sdavemq if (rs != NPI_SUCCESS) { 578159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 578259ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 578359ac0c16Sdavemq "returned error 0x[%x]", rs)); 578459ac0c16Sdavemq } 578559ac0c16Sdavemq 5786*321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 578759ac0c16Sdavemq } 5788d81011f0Ssbehera 5789d81011f0Ssbehera static nxge_status_t 5790d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 5791d81011f0Ssbehera { 5792d81011f0Ssbehera p_nxge_stats_t statsp; 5793d81011f0Ssbehera uint8_t xcvr_portn; 5794d81011f0Ssbehera p_mii_regs_t mii_regs; 5795d81011f0Ssbehera mii_mode_control_stat_t mode; 5796d81011f0Ssbehera int status = NXGE_OK; 5797d81011f0Ssbehera 5798d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 5799d81011f0Ssbehera 5800d81011f0Ssbehera statsp = nxgep->statsp; 5801d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 5802d81011f0Ssbehera mii_regs = NULL; 5803d81011f0Ssbehera mode.value = 0; 58046b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 5805d81011f0Ssbehera #if defined(__i386) 5806d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5807d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 5808d81011f0Ssbehera mode.value)) != NXGE_OK) { 5809d81011f0Ssbehera goto fail; 5810d81011f0Ssbehera #else 5811d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 5812d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 5813d81011f0Ssbehera mode.value)) != NXGE_OK) { 5814d81011f0Ssbehera goto fail; 5815d81011f0Ssbehera #endif 5816d81011f0Ssbehera } 5817d81011f0Ssbehera #if defined(__i386) 5818d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5819d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 5820d81011f0Ssbehera &mode.value)) != NXGE_OK) { 5821d81011f0Ssbehera goto fail; 5822d81011f0Ssbehera } 5823d81011f0Ssbehera #else 5824d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 5825d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 5826d81011f0Ssbehera &mode.value)) != NXGE_OK) { 5827d81011f0Ssbehera goto fail; 5828d81011f0Ssbehera } 5829d81011f0Ssbehera #endif 5830d81011f0Ssbehera 5831d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 5832d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 5833d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5834d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 5835d81011f0Ssbehera } 5836d81011f0Ssbehera 5837d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5838d81011f0Ssbehera "nxge_mii_get_link_mode: " 5839d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 58406b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 5841d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 5842d81011f0Ssbehera 5843d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5844d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 5845d81011f0Ssbehera return (status); 5846d81011f0Ssbehera fail: 5847d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5848d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 5849d81011f0Ssbehera return (NXGE_ERROR); 5850d81011f0Ssbehera } 5851d81011f0Ssbehera 5852d81011f0Ssbehera #ifdef NXGE_DEBUG 5853d81011f0Ssbehera static void 5854d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 5855d81011f0Ssbehera { 5856d81011f0Ssbehera p_nxge_stats_t statsp; 5857d81011f0Ssbehera uint8_t xcvr_portn; 5858d81011f0Ssbehera p_mii_regs_t mii_regs; 5859d81011f0Ssbehera mii_bmcr_t bmcr; 5860d81011f0Ssbehera mii_bmsr_t bmsr; 5861d81011f0Ssbehera mii_idr1_t idr1; 5862d81011f0Ssbehera mii_idr2_t idr2; 5863d81011f0Ssbehera mii_mode_control_stat_t mode; 5864d81011f0Ssbehera 5865d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 5866d81011f0Ssbehera 5867d81011f0Ssbehera statsp = nxgep->statsp; 5868d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 5869d81011f0Ssbehera 5870d81011f0Ssbehera mii_regs = NULL; 5871d81011f0Ssbehera 5872d81011f0Ssbehera #if defined(__i386) 5873d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 5874d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 5875d81011f0Ssbehera #else 5876d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 5877d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 5878d81011f0Ssbehera #endif 5879d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5880d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 5881d81011f0Ssbehera xcvr_portn, bmcr.value)); 5882d81011f0Ssbehera 5883d81011f0Ssbehera #if defined(__i386) 5884d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5885d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5886d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 5887d81011f0Ssbehera #else 5888d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5889d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5890d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 5891d81011f0Ssbehera #endif 5892d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5893d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 5894d81011f0Ssbehera xcvr_portn, bmsr.value)); 5895d81011f0Ssbehera 5896d81011f0Ssbehera #if defined(__i386) 5897d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5898d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5899d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 5900d81011f0Ssbehera #else 5901d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5902d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5903d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 5904d81011f0Ssbehera #endif 5905d81011f0Ssbehera 5906d81011f0Ssbehera 5907d81011f0Ssbehera #if defined(__i386) 5908d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5909d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5910d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 5911d81011f0Ssbehera #else 5912d81011f0Ssbehera (void) nxge_mii_read(nxgep, 5913d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 5914d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 5915d81011f0Ssbehera #endif 5916d81011f0Ssbehera 5917d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5918d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 5919d81011f0Ssbehera xcvr_portn, idr1.value)); 5920d81011f0Ssbehera 5921d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5922d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 5923d81011f0Ssbehera xcvr_portn, idr2.value)); 5924d81011f0Ssbehera 5925d81011f0Ssbehera mode.value = 0; 59266b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 5927d81011f0Ssbehera 5928d81011f0Ssbehera #if defined(__i386) 5929d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 5930d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 5931d81011f0Ssbehera 5932d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 5933d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 5934d81011f0Ssbehera #else 5935d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 5936d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 5937d81011f0Ssbehera 5938d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 5939d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 5940d81011f0Ssbehera #endif 5941d81011f0Ssbehera 5942d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5943d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 5944d81011f0Ssbehera xcvr_portn, mode.value)); 5945d81011f0Ssbehera } 5946d81011f0Ssbehera #endif 5947