13859Sml29623 /* 23859Sml29623 * CDDL HEADER START 33859Sml29623 * 43859Sml29623 * The contents of this file are subject to the terms of the 53859Sml29623 * Common Development and Distribution License (the "License"). 63859Sml29623 * You may not use this file except in compliance with the License. 73859Sml29623 * 83859Sml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93859Sml29623 * or http://www.opensolaris.org/os/licensing. 103859Sml29623 * See the License for the specific language governing permissions 113859Sml29623 * and limitations under the License. 123859Sml29623 * 133859Sml29623 * When distributing Covered Code, include this CDDL HEADER in each 143859Sml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153859Sml29623 * If applicable, add the following below this CDDL HEADER, with the 163859Sml29623 * fields enclosed by brackets "[]" replaced with your own identifying 173859Sml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 183859Sml29623 * 193859Sml29623 * CDDL HEADER END 203859Sml29623 */ 213859Sml29623 /* 223859Sml29623 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233859Sml29623 * Use is subject to license terms. 243859Sml29623 */ 253859Sml29623 263859Sml29623 #pragma ident "%Z%%M% %I% %E% SMI" 273859Sml29623 283859Sml29623 #include <sys/nxge/nxge_impl.h> 293859Sml29623 #include <sys/nxge/nxge_mac.h> 303859Sml29623 314693Stm144005 #define LINK_MONITOR_PERIOD (1000 * 1000) 324693Stm144005 #define LM_WAIT_MULTIPLIER 8 334693Stm144005 343859Sml29623 extern uint32_t nxge_no_link_notify; 35*4732Sdavemq extern boolean_t nxge_no_msg; 363859Sml29623 extern uint32_t nxge_lb_dbg; 373859Sml29623 extern nxge_os_mutex_t nxge_mdio_lock; 383859Sml29623 extern nxge_os_mutex_t nxge_mii_lock; 393859Sml29623 extern boolean_t nxge_jumbo_enable; 403859Sml29623 414693Stm144005 typedef enum { 424693Stm144005 CHECK_LINK_RESCHEDULE, 434693Stm144005 CHECK_LINK_STOP 444693Stm144005 } check_link_state_t; 454693Stm144005 464693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *); 474693Stm144005 483859Sml29623 /* 493859Sml29623 * Ethernet broadcast address definition. 503859Sml29623 */ 513859Sml29623 static ether_addr_st etherbroadcastaddr = 523859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 53*4732Sdavemq /* 54*4732Sdavemq * Ethernet zero address definition. 55*4732Sdavemq */ 564185Sspeer static ether_addr_st etherzeroaddr = 574185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 58*4732Sdavemq /* 59*4732Sdavemq * Supported chip types 60*4732Sdavemq */ 61*4732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID}; 62*4732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 63*4732Sdavemq 64*4732Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 65*4732Sdavemq sizeof (uint32_t)) 66*4732Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 67*4732Sdavemq sizeof (uint32_t)) 68*4732Sdavemq /* 69*4732Sdavemq * static functions 70*4732Sdavemq */ 71*4732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 72*4732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 73*4732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 74*4732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 75*4732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 76*4732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 77*4732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 78*4732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 79*4732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 80*4732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 81*4732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 82*4732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 83*4732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 84*4732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 85*4732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 86*4732Sdavemq 87*4732Sdavemq /* 88*4732Sdavemq * xcvr tables for supported transceivers 89*4732Sdavemq */ 90*4732Sdavemq 91*4732Sdavemq static nxge_xcvr_table_t nxge_n2_table = { 92*4732Sdavemq nxge_n2_serdes_init, 93*4732Sdavemq nxge_10G_xcvr_init, 94*4732Sdavemq nxge_10G_link_intr_stop, 95*4732Sdavemq nxge_10G_link_intr_start, 96*4732Sdavemq nxge_check_10g_link, 97*4732Sdavemq BCM8704_DEV_ID, 98*4732Sdavemq PCS_XCVR, 99*4732Sdavemq BCM8704_N2_PORT_ADDR_BASE 100*4732Sdavemq }; 101*4732Sdavemq 102*4732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 103*4732Sdavemq nxge_neptune_10G_serdes_init, 104*4732Sdavemq nxge_10G_xcvr_init, 105*4732Sdavemq nxge_10G_link_intr_stop, 106*4732Sdavemq nxge_10G_link_intr_start, 107*4732Sdavemq nxge_check_10g_link, 108*4732Sdavemq BCM8704_DEV_ID, 109*4732Sdavemq PCS_XCVR, 110*4732Sdavemq BCM8704_NEPTUNE_PORT_ADDR_BASE 111*4732Sdavemq }; 112*4732Sdavemq 113*4732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 114*4732Sdavemq NULL, 115*4732Sdavemq nxge_1G_xcvr_init, 116*4732Sdavemq nxge_1G_copper_link_intr_stop, 117*4732Sdavemq nxge_1G_copper_link_intr_start, 118*4732Sdavemq nxge_check_mii_link, 119*4732Sdavemq BCM5464R_PHY_ID, 120*4732Sdavemq INT_MII_XCVR, 121*4732Sdavemq BCM5464_NEPTUNE_PORT_ADDR_BASE 122*4732Sdavemq }; 123*4732Sdavemq 124*4732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 125*4732Sdavemq nxge_1G_serdes_init, 126*4732Sdavemq nxge_1G_xcvr_init, 127*4732Sdavemq nxge_1G_fiber_link_intr_stop, 128*4732Sdavemq nxge_1G_fiber_link_intr_start, 129*4732Sdavemq nxge_check_mii_link, 130*4732Sdavemq 0, 131*4732Sdavemq PCS_XCVR, 132*4732Sdavemq 0 133*4732Sdavemq }; 134*4732Sdavemq 135*4732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 136*4732Sdavemq nxge_neptune_10G_serdes_init, 137*4732Sdavemq NULL, 138*4732Sdavemq NULL, 139*4732Sdavemq NULL, 140*4732Sdavemq 0, 141*4732Sdavemq PCS_XCVR, 142*4732Sdavemq 0 143*4732Sdavemq }; 1443859Sml29623 1453859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 1463859Sml29623 147*4732Sdavemq /* Set up the PHY specific values. */ 148*4732Sdavemq 149*4732Sdavemq nxge_status_t 150*4732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 151*4732Sdavemq { 152*4732Sdavemq nxge_status_t status = NXGE_OK; 153*4732Sdavemq uint32_t port_type; 154*4732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 155*4732Sdavemq 156*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 157*4732Sdavemq portn)); 158*4732Sdavemq 159*4732Sdavemq if (nxgep->niu_type == N2_NIU) { 160*4732Sdavemq nxgep->mac.portmode = PORT_10G_FIBER; 161*4732Sdavemq nxgep->xcvr = nxge_n2_table; 162*4732Sdavemq nxgep->xcvr.xcvr_addr += portn; 163*4732Sdavemq } else { 164*4732Sdavemq port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn); 165*4732Sdavemq port_type = port_type & (NXGE_PORT_TYPE_MASK); 166*4732Sdavemq switch (port_type) { 167*4732Sdavemq case NXGE_PORT_1G_COPPER: 168*4732Sdavemq nxgep->mac.portmode = PORT_1G_COPPER; 169*4732Sdavemq nxgep->xcvr = nxge_1G_copper_table; 170*4732Sdavemq if (nxgep->nxge_hw_p->platform_type == 171*4732Sdavemq P_NEPTUNE_MARAMBA_P1) { 172*4732Sdavemq nxgep->xcvr.xcvr_addr = 173*4732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 174*4732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == 175*4732Sdavemq P_NEPTUNE_MARAMBA_P0) { 176*4732Sdavemq nxgep->xcvr.xcvr_addr = 177*4732Sdavemq BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 178*4732Sdavemq } 179*4732Sdavemq /* 180*4732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 181*4732Sdavemq * swapped with ethernet port number. This is 182*4732Sdavemq * designed for better signal integrity in routing. 183*4732Sdavemq */ 184*4732Sdavemq switch (portn) { 185*4732Sdavemq case 0: 186*4732Sdavemq nxgep->xcvr.xcvr_addr += 3; 187*4732Sdavemq break; 188*4732Sdavemq case 1: 189*4732Sdavemq nxgep->xcvr.xcvr_addr += 2; 190*4732Sdavemq break; 191*4732Sdavemq case 2: 192*4732Sdavemq nxgep->xcvr.xcvr_addr += 1; 193*4732Sdavemq break; 194*4732Sdavemq case 3: 195*4732Sdavemq break; 196*4732Sdavemq default: 197*4732Sdavemq return (NXGE_ERROR); 198*4732Sdavemq } 199*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 200*4732Sdavemq break; 201*4732Sdavemq case NXGE_PORT_10G_COPPER: 202*4732Sdavemq nxgep->mac.portmode = PORT_10G_COPPER; 203*4732Sdavemq nxgep->xcvr = nxge_10G_copper_table; 204*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 205*4732Sdavemq break; 206*4732Sdavemq case NXGE_PORT_1G_FIBRE: 207*4732Sdavemq nxgep->mac.portmode = PORT_1G_FIBER; 208*4732Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 209*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr")); 210*4732Sdavemq break; 211*4732Sdavemq case NXGE_PORT_10G_FIBRE: 212*4732Sdavemq nxgep->mac.portmode = PORT_10G_FIBER; 213*4732Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 214*4732Sdavemq if ((nxgep->nxge_hw_p->platform_type == 215*4732Sdavemq P_NEPTUNE_MARAMBA_P0) || 216*4732Sdavemq (nxgep->nxge_hw_p->platform_type == 217*4732Sdavemq P_NEPTUNE_MARAMBA_P1)) { 218*4732Sdavemq nxgep->xcvr.xcvr_addr = 219*4732Sdavemq BCM8704_MARAMBA_PORT_ADDR_BASE; 220*4732Sdavemq /* 221*4732Sdavemq * Switch off LED for corresponding copper 222*4732Sdavemq * port 223*4732Sdavemq */ 224*4732Sdavemq nxge_bcm5464_link_led_off(nxgep); 225*4732Sdavemq } 226*4732Sdavemq nxgep->xcvr.xcvr_addr += portn; 227*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr")); 228*4732Sdavemq break; 229*4732Sdavemq default: 230*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 231*4732Sdavemq "Unknown port-type: 0x%x", port_type)); 232*4732Sdavemq return (NXGE_ERROR); 233*4732Sdavemq } 234*4732Sdavemq } 235*4732Sdavemq 236*4732Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 237*4732Sdavemq nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr; 238*4732Sdavemq nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id; 239*4732Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 240*4732Sdavemq 241*4732Sdavemq return (status); 242*4732Sdavemq } 243*4732Sdavemq 2443859Sml29623 /* Initialize the entire MAC and physical layer */ 2453859Sml29623 2463859Sml29623 nxge_status_t 2473859Sml29623 nxge_mac_init(p_nxge_t nxgep) 2483859Sml29623 { 2493859Sml29623 uint8_t portn; 2503859Sml29623 nxge_status_t status = NXGE_OK; 2513859Sml29623 2523859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2533859Sml29623 2543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 2553859Sml29623 2563859Sml29623 nxgep->mac.portnum = portn; 2573859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 2583859Sml29623 2593859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 2603859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 2613859Sml29623 2623859Sml29623 /* Initialize XIF to configure a network mode */ 2633859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 2643859Sml29623 goto fail; 2653859Sml29623 } 2663859Sml29623 2673859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 2683859Sml29623 goto fail; 2693859Sml29623 } 2703859Sml29623 2713859Sml29623 /* Initialize TX and RX MACs */ 2723859Sml29623 /* 2733859Sml29623 * Always perform XIF init first, before TX and RX MAC init 2743859Sml29623 */ 2753859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 2763859Sml29623 goto fail; 2773859Sml29623 2783859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 2793859Sml29623 goto fail; 2803859Sml29623 2813859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 2823859Sml29623 goto fail; 2833859Sml29623 2843859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 2853859Sml29623 goto fail; 2863859Sml29623 2873859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 2883859Sml29623 goto fail; 2893859Sml29623 2903859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 2913859Sml29623 goto fail; 2923859Sml29623 2933859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 2943859Sml29623 2953859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 2963859Sml29623 2973859Sml29623 return (NXGE_OK); 2983859Sml29623 fail: 2993859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3003859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 3013859Sml29623 portn)); 3023859Sml29623 return (status); 3033859Sml29623 } 3043859Sml29623 3053859Sml29623 /* Initialize the Ethernet Link */ 3063859Sml29623 3073859Sml29623 nxge_status_t 3083859Sml29623 nxge_link_init(p_nxge_t nxgep) 3093859Sml29623 { 3103859Sml29623 nxge_status_t status = NXGE_OK; 3113859Sml29623 #ifdef NXGE_DEBUG 3123859Sml29623 uint8_t portn; 3133859Sml29623 3143859Sml29623 portn = nxgep->mac.portnum; 3153859Sml29623 3163859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 3173859Sml29623 #endif 3183859Sml29623 3193859Sml29623 if (nxgep->niu_type == N2_NIU) { 3203859Sml29623 /* Workaround to get link up in both NIU ports */ 3213859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 3223859Sml29623 goto fail; 3233859Sml29623 } 3243859Sml29623 NXGE_DELAY(200000); 3253859Sml29623 /* Initialize internal serdes */ 3263859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 3273859Sml29623 goto fail; 3283859Sml29623 NXGE_DELAY(200000); 3293859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 3303859Sml29623 goto fail; 3313859Sml29623 3323859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 3333859Sml29623 3343859Sml29623 return (NXGE_OK); 3353859Sml29623 3363859Sml29623 fail: 3373859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3383859Sml29623 "nxge_link_init: ", 3393859Sml29623 "failed to initialize Ethernet link on port<%d>", 3403859Sml29623 portn)); 3413859Sml29623 3423859Sml29623 return (status); 3433859Sml29623 } 3443859Sml29623 3453859Sml29623 3463859Sml29623 /* Initialize the XIF sub-block within the MAC */ 3473859Sml29623 3483859Sml29623 nxge_status_t 3493859Sml29623 nxge_xif_init(p_nxge_t nxgep) 3503859Sml29623 { 3513859Sml29623 uint32_t xif_cfg = 0; 3523859Sml29623 npi_attr_t ap; 3533859Sml29623 uint8_t portn; 3543859Sml29623 nxge_port_t portt; 3553859Sml29623 nxge_port_mode_t portmode; 3563859Sml29623 p_nxge_stats_t statsp; 3573859Sml29623 npi_status_t rs = NPI_SUCCESS; 3583859Sml29623 npi_handle_t handle; 3593859Sml29623 3603859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3613859Sml29623 3623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 3633859Sml29623 3643859Sml29623 handle = nxgep->npi_handle; 3653859Sml29623 portmode = nxgep->mac.portmode; 3663859Sml29623 portt = nxgep->mac.porttype; 3673859Sml29623 statsp = nxgep->statsp; 3683859Sml29623 3693859Sml29623 if (portt == PORT_TYPE_XMAC) { 3703859Sml29623 3713859Sml29623 /* Setup XIF Configuration for XMAC */ 3723859Sml29623 3733859Sml29623 if ((portmode == PORT_10G_FIBER) || 3743859Sml29623 (portmode == PORT_10G_COPPER)) 3753859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 3763859Sml29623 3773859Sml29623 if (portmode == PORT_1G_COPPER) { 3783859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 3793859Sml29623 } 3803859Sml29623 3813859Sml29623 /* Set MAC Internal Loopback if necessary */ 3823859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 3833859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 3843859Sml29623 3853859Sml29623 if (statsp->mac_stats.link_speed == 100) 3863859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 3873859Sml29623 3883859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 3893859Sml29623 3903859Sml29623 if (portmode == PORT_10G_FIBER) { 3913859Sml29623 if (statsp->mac_stats.link_up) { 3923859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 3933859Sml29623 } else { 3943859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 3953859Sml29623 } 3963859Sml29623 } 3973859Sml29623 3983859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 3993859Sml29623 if (rs != NPI_SUCCESS) 4003859Sml29623 goto fail; 4013859Sml29623 4023859Sml29623 nxgep->mac.xif_config = xif_cfg; 4033859Sml29623 4043859Sml29623 /* Set Port Mode */ 4053859Sml29623 if ((portmode == PORT_10G_FIBER) || 4063859Sml29623 (portmode == PORT_10G_COPPER)) { 4073859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4083859Sml29623 MAC_XGMII_MODE, rs); 4093859Sml29623 if (rs != NPI_SUCCESS) 4103859Sml29623 goto fail; 4113859Sml29623 if (statsp->mac_stats.link_up) { 4123859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 4133859Sml29623 goto fail; 4143859Sml29623 } else { 4153859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 4163859Sml29623 goto fail; 4173859Sml29623 } 4183859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 4193859Sml29623 (portmode == PORT_1G_COPPER)) { 4203859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 4213859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4223859Sml29623 MAC_GMII_MODE, rs); 4233859Sml29623 } else { 4243859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4253859Sml29623 MAC_MII_MODE, rs); 4263859Sml29623 } 4273859Sml29623 if (rs != NPI_SUCCESS) 4283859Sml29623 goto fail; 4293859Sml29623 } else { 4303859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4313859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 4323859Sml29623 " for port<%d>", portmode, portn)); 4333859Sml29623 goto fail; 4343859Sml29623 } 4353859Sml29623 4363859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 4373859Sml29623 4383859Sml29623 /* Setup XIF Configuration for BMAC */ 4393859Sml29623 4403859Sml29623 if (portmode == PORT_1G_COPPER) { 4413859Sml29623 if (statsp->mac_stats.link_speed == 100) 4423859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 4433859Sml29623 } 4443859Sml29623 4453859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 4463859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 4473859Sml29623 4483859Sml29623 if (statsp->mac_stats.link_speed == 1000) 4493859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 4503859Sml29623 4513859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 4523859Sml29623 4533859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 4543859Sml29623 if (rs != NPI_SUCCESS) 4553859Sml29623 goto fail; 4563859Sml29623 nxgep->mac.xif_config = xif_cfg; 4573859Sml29623 } 4583859Sml29623 4593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 4603859Sml29623 return (NXGE_OK); 4613859Sml29623 fail: 4623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4633859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 4643859Sml29623 portn)); 4653859Sml29623 return (NXGE_ERROR | rs); 4663859Sml29623 } 4673859Sml29623 4683859Sml29623 /* Initialize the PCS sub-block in the MAC */ 4693859Sml29623 4703859Sml29623 nxge_status_t 4713859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 4723859Sml29623 { 4733859Sml29623 pcs_cfg_t pcs_cfg; 4743859Sml29623 uint32_t val; 4753859Sml29623 uint8_t portn; 4763859Sml29623 nxge_port_mode_t portmode; 4773859Sml29623 npi_handle_t handle; 4783859Sml29623 p_nxge_stats_t statsp; 4793859Sml29623 npi_status_t rs = NPI_SUCCESS; 4803859Sml29623 4813859Sml29623 handle = nxgep->npi_handle; 4823859Sml29623 portmode = nxgep->mac.portmode; 4833859Sml29623 portn = nxgep->mac.portnum; 4843859Sml29623 statsp = nxgep->statsp; 4853859Sml29623 4863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 4873859Sml29623 4883859Sml29623 if (portmode == PORT_1G_FIBER) { 4893859Sml29623 /* Initialize port's PCS */ 4903859Sml29623 pcs_cfg.value = 0; 4913859Sml29623 pcs_cfg.bits.w0.enable = 1; 4923859Sml29623 pcs_cfg.bits.w0.mask = 1; 4933859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 4943859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 4953859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 4963859Sml29623 goto fail; 4973859Sml29623 4983859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 4993859Sml29623 (portmode == PORT_10G_COPPER)) { 5003859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 5013859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 5023859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 5033859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 5043859Sml29623 5053859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 5063859Sml29623 goto fail; 5073859Sml29623 5083859Sml29623 /* Set XPCS Internal Loopback if necessary */ 5093859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5103859Sml29623 XPCS_REG_CONTROL1, &val)) 5113859Sml29623 != NPI_SUCCESS) 5123859Sml29623 goto fail; 5133859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 5143859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 5153859Sml29623 val |= XPCS_CTRL1_LOOPBK; 5163859Sml29623 else 5173859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 5183859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 5193859Sml29623 XPCS_REG_CONTROL1, val)) 5203859Sml29623 != NPI_SUCCESS) 5213859Sml29623 goto fail; 5223859Sml29623 5233859Sml29623 /* Clear descw errors */ 5243859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 5253859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 5263859Sml29623 != NPI_SUCCESS) 5273859Sml29623 goto fail; 5283859Sml29623 /* Clear symbol errors */ 5293859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5303859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 5313859Sml29623 != NPI_SUCCESS) 5323859Sml29623 goto fail; 5333859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5343859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 5353859Sml29623 != NPI_SUCCESS) 5363859Sml29623 goto fail; 5373859Sml29623 5383859Sml29623 } else if (portmode == PORT_1G_COPPER) { 5393859Sml29623 if (portn < 4) { 5403859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 5413859Sml29623 PCS_DATAPATH_MODE_MII); 5423859Sml29623 } 5433859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 5443859Sml29623 goto fail; 5453859Sml29623 5463859Sml29623 } else { 5473859Sml29623 goto fail; 5483859Sml29623 } 5493859Sml29623 pass: 5503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 5513859Sml29623 return (NXGE_OK); 5523859Sml29623 fail: 5533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5543859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 5553859Sml29623 portn)); 5563859Sml29623 return (NXGE_ERROR | rs); 5573859Sml29623 } 5583859Sml29623 5593859Sml29623 /* Initialize the Internal Serdes */ 5603859Sml29623 5613859Sml29623 nxge_status_t 5623859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 5633859Sml29623 { 5643859Sml29623 p_nxge_stats_t statsp; 5653859Sml29623 #ifdef NXGE_DEBUG 5663859Sml29623 uint8_t portn; 5673859Sml29623 #endif 5683859Sml29623 nxge_status_t status = NXGE_OK; 5693859Sml29623 5703859Sml29623 #ifdef NXGE_DEBUG 5713859Sml29623 portn = nxgep->mac.portnum; 5723859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 573*4732Sdavemq "==> nxge_serdes_init port<%d>", portn)); 5743859Sml29623 #endif 5753859Sml29623 576*4732Sdavemq if (nxgep->xcvr.serdes_init) { 577*4732Sdavemq statsp = nxgep->statsp; 578*4732Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 579*4732Sdavemq if (status != NXGE_OK) 5803859Sml29623 goto fail; 581*4732Sdavemq statsp->mac_stats.serdes_inits++; 5823859Sml29623 } 5833859Sml29623 5843859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 585*4732Sdavemq portn)); 5863859Sml29623 5873859Sml29623 return (NXGE_OK); 5883859Sml29623 5893859Sml29623 fail: 5903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 591*4732Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 592*4732Sdavemq portn)); 5933859Sml29623 5943859Sml29623 return (status); 5953859Sml29623 } 5963859Sml29623 5973859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 5983859Sml29623 599*4732Sdavemq static nxge_status_t 6003859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 6013859Sml29623 { 6023859Sml29623 uint8_t portn; 6033859Sml29623 int chan; 6043859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 6053859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 6063859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 6073859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 6083859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 6093859Sml29623 esr_ti_testcfg_t test_cfg; 6103859Sml29623 nxge_status_t status = NXGE_OK; 6113859Sml29623 6123859Sml29623 portn = nxgep->mac.portnum; 6133859Sml29623 6143859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 6153859Sml29623 portn)); 6163859Sml29623 6173859Sml29623 tx_cfg_l.value = 0; 6183859Sml29623 tx_cfg_h.value = 0; 6193859Sml29623 rx_cfg_l.value = 0; 6203859Sml29623 rx_cfg_h.value = 0; 6213859Sml29623 pll_cfg_l.value = 0; 6223859Sml29623 test_cfg.value = 0; 6233859Sml29623 6243859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 6253859Sml29623 /* 0x0E01 */ 6263859Sml29623 tx_cfg_l.bits.entx = 1; 6273859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 6283859Sml29623 6293859Sml29623 /* 0x9101 */ 6303859Sml29623 rx_cfg_l.bits.enrx = 1; 6313859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 6323859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 6333859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 6343859Sml29623 6353859Sml29623 /* 0x0008 */ 6363859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 6373859Sml29623 6383859Sml29623 /* Set loopback mode if necessary */ 6393859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 6403859Sml29623 tx_cfg_l.bits.entest = 1; 6413859Sml29623 rx_cfg_l.bits.entest = 1; 6423859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 6433859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6443859Sml29623 ESR_N2_DEV_ADDR, 6453859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 6463859Sml29623 != NXGE_OK) 6473859Sml29623 goto fail; 6483859Sml29623 } 6493859Sml29623 6503859Sml29623 /* Use default PLL value */ 6513859Sml29623 6523859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 6533859Sml29623 6543859Sml29623 /* 0x0E21 */ 6553859Sml29623 tx_cfg_l.bits.entx = 1; 6563859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 6573859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 6583859Sml29623 6593859Sml29623 /* 0x9121 */ 6603859Sml29623 rx_cfg_l.bits.enrx = 1; 6613859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 6623859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 6633859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 6643859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 6653859Sml29623 6663859Sml29623 /* 0x8 */ 6673859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 6683859Sml29623 6693859Sml29623 /* MPY = 0x100 */ 6703859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 6713859Sml29623 6723859Sml29623 /* Set PLL */ 6733859Sml29623 pll_cfg_l.bits.enpll = 1; 6743859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6753859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 6763859Sml29623 != NXGE_OK) 6773859Sml29623 goto fail; 6783859Sml29623 } else { 6793859Sml29623 goto fail; 6803859Sml29623 } 6813859Sml29623 6823859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 6833859Sml29623 6843859Sml29623 NXGE_DELAY(20); 6853859Sml29623 6863859Sml29623 /* init TX channels */ 6873859Sml29623 for (chan = 0; chan < 4; chan++) { 6883859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6893859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 6903859Sml29623 != NXGE_OK) 6913859Sml29623 goto fail; 6923859Sml29623 6933859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6943859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 6953859Sml29623 != NXGE_OK) 6963859Sml29623 goto fail; 6973859Sml29623 } 6983859Sml29623 6993859Sml29623 /* init RX channels */ 7003859Sml29623 for (chan = 0; chan < 4; chan++) { 7013859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 7023859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 7033859Sml29623 != NXGE_OK) 7043859Sml29623 goto fail; 7053859Sml29623 7063859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 7073859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 7083859Sml29623 != NXGE_OK) 7093859Sml29623 goto fail; 7103859Sml29623 } 7113859Sml29623 7123859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 7133859Sml29623 portn)); 7143859Sml29623 7153859Sml29623 return (NXGE_OK); 7163859Sml29623 fail: 7173859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7183859Sml29623 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 7193859Sml29623 portn)); 7203859Sml29623 7213859Sml29623 return (status); 7223859Sml29623 } 7233859Sml29623 724*4732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 725*4732Sdavemq 726*4732Sdavemq static nxge_status_t 727*4732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 7283859Sml29623 { 7293859Sml29623 npi_handle_t handle; 7303859Sml29623 uint8_t portn; 7313859Sml29623 int chan; 7323859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 7333859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 7343859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 7353859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 7363859Sml29623 uint64_t val; 7373859Sml29623 uint16_t val16l; 7383859Sml29623 uint16_t val16h; 7393859Sml29623 nxge_status_t status = NXGE_OK; 7403859Sml29623 7413859Sml29623 portn = nxgep->mac.portnum; 7423859Sml29623 7433859Sml29623 if ((portn != 0) && (portn != 1)) 7443859Sml29623 return (NXGE_OK); 7453859Sml29623 746*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 747*4732Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 7483859Sml29623 7493859Sml29623 handle = nxgep->npi_handle; 750*4732Sdavemq switch (portn) { 751*4732Sdavemq case 0: 752*4732Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 753*4732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 754*4732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 755*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 756*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 757*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 758*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 759*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 760*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 761*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 762*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 763*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 764*4732Sdavemq 765*4732Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 766*4732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 767*4732Sdavemq ESR_REG_WR(handle, 768*4732Sdavemq ESR_0_TEST_CONFIG_REG, 769*4732Sdavemq ESR_PAD_LOOPBACK_CH3 | 770*4732Sdavemq ESR_PAD_LOOPBACK_CH2 | 771*4732Sdavemq ESR_PAD_LOOPBACK_CH1 | 772*4732Sdavemq ESR_PAD_LOOPBACK_CH0); 773*4732Sdavemq } else { 774*4732Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 7753859Sml29623 } 776*4732Sdavemq break; 777*4732Sdavemq case 1: 778*4732Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 779*4732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 780*4732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 781*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 782*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 783*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 784*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 785*4732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 786*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 787*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 788*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 789*4732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 790*4732Sdavemq 791*4732Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 792*4732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 793*4732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 794*4732Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 795*4732Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 796*4732Sdavemq } else { 797*4732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 7983859Sml29623 } 799*4732Sdavemq break; 800*4732Sdavemq default: 801*4732Sdavemq /* Nothing to do here */ 802*4732Sdavemq goto done; 803*4732Sdavemq } 804*4732Sdavemq 805*4732Sdavemq /* init TX RX channels */ 806*4732Sdavemq for (chan = 0; chan < 4; chan++) { 807*4732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 808*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 809*4732Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 8103859Sml29623 goto fail; 811*4732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 812*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 813*4732Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 8143859Sml29623 goto fail; 8153859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 816*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 817*4732Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 8183859Sml29623 goto fail; 8193859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 820*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 821*4732Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 822*4732Sdavemq goto fail; 823*4732Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 824*4732Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 825*4732Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 826*4732Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 827*4732Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 828*4732Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 829*4732Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 830*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 831*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 832*4732Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 833*4732Sdavemq goto fail; 834*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 835*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 836*4732Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 837*4732Sdavemq goto fail; 838*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 839*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 840*4732Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 841*4732Sdavemq goto fail; 842*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 843*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 844*4732Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 8453859Sml29623 goto fail; 8463859Sml29623 } 8473859Sml29623 848*4732Sdavemq /* Apply Tx core reset */ 849*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 850*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 851*4732Sdavemq (uint16_t)0)) != NXGE_OK) 852*4732Sdavemq goto fail; 853*4732Sdavemq 854*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 855*4732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 856*4732Sdavemq NXGE_OK) 857*4732Sdavemq goto fail; 858*4732Sdavemq 859*4732Sdavemq NXGE_DELAY(200); 860*4732Sdavemq 861*4732Sdavemq /* Apply Rx core reset */ 862*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 863*4732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 864*4732Sdavemq NXGE_OK) 865*4732Sdavemq goto fail; 866*4732Sdavemq 867*4732Sdavemq NXGE_DELAY(200); 868*4732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 869*4732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 870*4732Sdavemq goto fail; 871*4732Sdavemq 872*4732Sdavemq NXGE_DELAY(200); 873*4732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 874*4732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 875*4732Sdavemq &val16l)) != NXGE_OK) 876*4732Sdavemq goto fail; 877*4732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 878*4732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 879*4732Sdavemq goto fail; 880*4732Sdavemq if ((val16l != 0) || (val16h != 0)) { 881*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 882*4732Sdavemq "Failed to reset port<%d> XAUI Serdes", portn)); 883*4732Sdavemq } 884*4732Sdavemq 885*4732Sdavemq ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 886*4732Sdavemq 887*4732Sdavemq if (portn == 0) { 888*4732Sdavemq if ((val & ESR_SIG_P0_BITS_MASK) != 8893859Sml29623 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 8903859Sml29623 ESR_SIG_XSERDES_RDY_P0 | 8913859Sml29623 ESR_SIG_XDETECT_P0_CH3 | 8923859Sml29623 ESR_SIG_XDETECT_P0_CH2 | 8933859Sml29623 ESR_SIG_XDETECT_P0_CH1 | 8943859Sml29623 ESR_SIG_XDETECT_P0_CH0)) { 895*4732Sdavemq goto fail; 896*4732Sdavemq } 897*4732Sdavemq } else if (portn == 1) { 898*4732Sdavemq if ((val & ESR_SIG_P1_BITS_MASK) != 8993859Sml29623 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 9003859Sml29623 ESR_SIG_XSERDES_RDY_P1 | 9013859Sml29623 ESR_SIG_XDETECT_P1_CH3 | 9023859Sml29623 ESR_SIG_XDETECT_P1_CH2 | 9033859Sml29623 ESR_SIG_XDETECT_P1_CH1 | 9043859Sml29623 ESR_SIG_XDETECT_P1_CH0)) { 9053859Sml29623 goto fail; 9063859Sml29623 } 9073859Sml29623 } 9083859Sml29623 9093859Sml29623 done: 910*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 911*4732Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 912*4732Sdavemq 9133859Sml29623 return (NXGE_OK); 9143859Sml29623 fail: 915*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 916*4732Sdavemq "nxge_neptune_10G_serdes_init: " 917*4732Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 9183859Sml29623 9193859Sml29623 return (status); 9203859Sml29623 } 9213859Sml29623 922*4732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 923*4732Sdavemq 924*4732Sdavemq static nxge_status_t 925*4732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 9263859Sml29623 { 927*4732Sdavemq npi_handle_t handle; 928*4732Sdavemq uint8_t portn; 929*4732Sdavemq uint64_t val; 9303859Sml29623 9313859Sml29623 portn = nxgep->mac.portnum; 932*4732Sdavemq 933*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 934*4732Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 935*4732Sdavemq 936*4732Sdavemq handle = nxgep->npi_handle; 937*4732Sdavemq 938*4732Sdavemq ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val); 939*4732Sdavemq val &= ~ESR_PLL_CFG_FBDIV_2; 940*4732Sdavemq switch (portn) { 941*4732Sdavemq case 0: 942*4732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_0; 943*4732Sdavemq break; 944*4732Sdavemq case 1: 945*4732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_1; 946*4732Sdavemq break; 947*4732Sdavemq case 2: 948*4732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_2; 949*4732Sdavemq break; 950*4732Sdavemq case 3: 951*4732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_3; 952*4732Sdavemq break; 953*4732Sdavemq default: 954*4732Sdavemq goto fail; 9553859Sml29623 } 9563859Sml29623 957*4732Sdavemq ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 958*4732Sdavemq 959*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 960*4732Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 9613859Sml29623 return (NXGE_OK); 962*4732Sdavemq fail: 963*4732Sdavemq NXGE_DEBUG_MSG((nxgep, TX_CTL, 964*4732Sdavemq "nxge_1G_serdes_init: " 965*4732Sdavemq "Failed to initialize Neptune serdes for port<%d>", 966*4732Sdavemq portn)); 967*4732Sdavemq 968*4732Sdavemq return (NXGE_ERROR); 9693859Sml29623 } 9703859Sml29623 971*4732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */ 972*4732Sdavemq 973*4732Sdavemq static nxge_status_t 974*4732Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep) 9753859Sml29623 { 9763859Sml29623 p_nxge_stats_t statsp; 9773859Sml29623 uint16_t val; 9783859Sml29623 #ifdef NXGE_DEBUG 9793859Sml29623 uint8_t portn; 9803859Sml29623 uint16_t val1; 9813859Sml29623 #endif 9823859Sml29623 uint8_t phy_port_addr; 9833859Sml29623 pmd_tx_control_t tx_ctl; 9843859Sml29623 control_t ctl; 9853859Sml29623 phyxs_control_t phyxs_ctl; 9863859Sml29623 pcs_control_t pcs_ctl; 9873859Sml29623 uint32_t delay = 0; 9883859Sml29623 optics_dcntr_t op_ctr; 9893859Sml29623 nxge_status_t status = NXGE_OK; 9903859Sml29623 #ifdef NXGE_DEBUG 9913859Sml29623 portn = nxgep->mac.portnum; 9923859Sml29623 #endif 993*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 994*4732Sdavemq portn)); 995*4732Sdavemq 996*4732Sdavemq statsp = nxgep->statsp; 997*4732Sdavemq 998*4732Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 999*4732Sdavemq 1000*4732Sdavemq /* Disable Link LEDs */ 1001*4732Sdavemq if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 1002*4732Sdavemq goto fail; 1003*4732Sdavemq 1004*4732Sdavemq /* Set Clause 45 */ 1005*4732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 1006*4732Sdavemq 1007*4732Sdavemq /* Reset the transceiver */ 1008*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1009*4732Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 1010*4732Sdavemq goto fail; 1011*4732Sdavemq 1012*4732Sdavemq phyxs_ctl.bits.reset = 1; 1013*4732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1014*4732Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 1015*4732Sdavemq goto fail; 1016*4732Sdavemq 1017*4732Sdavemq do { 1018*4732Sdavemq drv_usecwait(500); 1019*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1020*4732Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 1021*4732Sdavemq &phyxs_ctl.value)) != NXGE_OK) 1022*4732Sdavemq goto fail; 1023*4732Sdavemq delay++; 1024*4732Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 1025*4732Sdavemq if (delay == 100) { 1026*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 1027*4732Sdavemq "failed to reset Transceiver on port<%d>", portn)); 1028*4732Sdavemq status = NXGE_ERROR; 1029*4732Sdavemq goto fail; 1030*4732Sdavemq } 1031*4732Sdavemq 1032*4732Sdavemq /* Set to 0x7FBF */ 1033*4732Sdavemq ctl.value = 0; 1034*4732Sdavemq ctl.bits.res1 = 0x3F; 1035*4732Sdavemq ctl.bits.optxon_lvl = 1; 1036*4732Sdavemq ctl.bits.oprxflt_lvl = 1; 1037*4732Sdavemq ctl.bits.optrxlos_lvl = 1; 1038*4732Sdavemq ctl.bits.optxflt_lvl = 1; 1039*4732Sdavemq ctl.bits.opprflt_lvl = 1; 1040*4732Sdavemq ctl.bits.obtmpflt_lvl = 1; 1041*4732Sdavemq ctl.bits.opbiasflt_lvl = 1; 1042*4732Sdavemq ctl.bits.optxrst_lvl = 1; 1043*4732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1044*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 1045*4732Sdavemq != NXGE_OK) 1046*4732Sdavemq goto fail; 1047*4732Sdavemq 1048*4732Sdavemq /* Set to 0x164 */ 1049*4732Sdavemq tx_ctl.value = 0; 1050*4732Sdavemq tx_ctl.bits.tsck_lpwren = 1; 1051*4732Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 1052*4732Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 1053*4732Sdavemq tx_ctl.bits.xfp_clken = 1; 1054*4732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1055*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 1056*4732Sdavemq tx_ctl.value)) != NXGE_OK) 1057*4732Sdavemq goto fail; 1058*4732Sdavemq /* 1059*4732Sdavemq * According to Broadcom's instruction, SW needs to read 1060*4732Sdavemq * back these registers twice after written. 1061*4732Sdavemq */ 1062*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1063*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1064*4732Sdavemq != NXGE_OK) 1065*4732Sdavemq goto fail; 1066*4732Sdavemq 1067*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1068*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1069*4732Sdavemq != NXGE_OK) 1070*4732Sdavemq goto fail; 1071*4732Sdavemq 1072*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1073*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1074*4732Sdavemq != NXGE_OK) 1075*4732Sdavemq goto fail; 1076*4732Sdavemq 1077*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1078*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1079*4732Sdavemq != NXGE_OK) 1080*4732Sdavemq goto fail; 1081*4732Sdavemq 1082*4732Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 1083*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1084*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1085*4732Sdavemq &op_ctr.value)) != NXGE_OK) 1086*4732Sdavemq goto fail; 1087*4732Sdavemq op_ctr.bits.gpio_sel = 0x3; 1088*4732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1089*4732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1090*4732Sdavemq op_ctr.value)) != NXGE_OK) 1091*4732Sdavemq goto fail; 1092*4732Sdavemq 1093*4732Sdavemq NXGE_DELAY(1000000); 1094*4732Sdavemq 1095*4732Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 1096*4732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1097*4732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 1098*4732Sdavemq != NXGE_OK) 1099*4732Sdavemq goto fail; 1100*4732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 1101*4732Sdavemq pcs_ctl.bits.loopback = 1; 1102*4732Sdavemq else 1103*4732Sdavemq pcs_ctl.bits.loopback = 0; 1104*4732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1105*4732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 1106*4732Sdavemq != NXGE_OK) 1107*4732Sdavemq goto fail; 1108*4732Sdavemq 1109*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 1110*4732Sdavemq if (status != NXGE_OK) 1111*4732Sdavemq goto fail; 1112*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1113*4732Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 1114*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 1115*4732Sdavemq if (status != NXGE_OK) 1116*4732Sdavemq goto fail; 1117*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1118*4732Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 1119*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 1120*4732Sdavemq if (status != NXGE_OK) 1121*4732Sdavemq goto fail; 1122*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1123*4732Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 1124*4732Sdavemq 1125*4732Sdavemq #ifdef NXGE_DEBUG 1126*4732Sdavemq /* Diagnose link issue if link is not up */ 1127*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 1128*4732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 1129*4732Sdavemq &val); 1130*4732Sdavemq if (status != NXGE_OK) 1131*4732Sdavemq goto fail; 1132*4732Sdavemq 1133*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 1134*4732Sdavemq BCM8704_USER_DEV3_ADDR, 1135*4732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 1136*4732Sdavemq &val); 1137*4732Sdavemq if (status != NXGE_OK) 1138*4732Sdavemq goto fail; 1139*4732Sdavemq 1140*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 1141*4732Sdavemq BCM8704_USER_DEV3_ADDR, 1142*4732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 1143*4732Sdavemq &val1); 1144*4732Sdavemq if (status != NXGE_OK) 1145*4732Sdavemq goto fail; 1146*4732Sdavemq 1147*4732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 1148*4732Sdavemq BCM8704_USER_DEV3_ADDR, 1149*4732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 1150*4732Sdavemq &val1); 1151*4732Sdavemq if (status != NXGE_OK) 1152*4732Sdavemq goto fail; 1153*4732Sdavemq 1154*4732Sdavemq if (val != 0x3FC) { 1155*4732Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 1156*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1157*4732Sdavemq "Cable not connected to peer or bad" 1158*4732Sdavemq " cable on port<%d>\n", portn)); 1159*4732Sdavemq } else if (val == 0x639C) { 1160*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1161*4732Sdavemq "Optical module (XFP) is bad or absent" 1162*4732Sdavemq " on port<%d>\n", portn)); 1163*4732Sdavemq } 1164*4732Sdavemq } 1165*4732Sdavemq #endif 1166*4732Sdavemq 1167*4732Sdavemq statsp->mac_stats.cap_10gfdx = 1; 1168*4732Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 1169*4732Sdavemq 1170*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 1171*4732Sdavemq portn)); 1172*4732Sdavemq return (NXGE_OK); 1173*4732Sdavemq 1174*4732Sdavemq fail: 1175*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1176*4732Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 1177*4732Sdavemq "port<%d>", portn)); 1178*4732Sdavemq return (status); 1179*4732Sdavemq } 1180*4732Sdavemq 1181*4732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 1182*4732Sdavemq 1183*4732Sdavemq static nxge_status_t 1184*4732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 1185*4732Sdavemq { 1186*4732Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 1187*4732Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 1188*4732Sdavemq nxge_status_t status = NXGE_OK; 1189*4732Sdavemq 1190*4732Sdavemq /* Set Clause 22 */ 1191*4732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 1192*4732Sdavemq 1193*4732Sdavemq /* Set capability flags */ 1194*4732Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 1195*4732Sdavemq statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value; 1196*4732Sdavemq statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value; 1197*4732Sdavemq 1198*4732Sdavemq status = nxge_mii_xcvr_init(nxgep); 1199*4732Sdavemq 1200*4732Sdavemq return (status); 1201*4732Sdavemq } 1202*4732Sdavemq 1203*4732Sdavemq /* Initialize transceiver */ 1204*4732Sdavemq 1205*4732Sdavemq nxge_status_t 1206*4732Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 1207*4732Sdavemq { 1208*4732Sdavemq p_nxge_stats_t statsp; 1209*4732Sdavemq #ifdef NXGE_DEBUG 1210*4732Sdavemq uint8_t portn; 1211*4732Sdavemq #endif 1212*4732Sdavemq 1213*4732Sdavemq nxge_status_t status = NXGE_OK; 1214*4732Sdavemq #ifdef NXGE_DEBUG 1215*4732Sdavemq portn = nxgep->mac.portnum; 1216*4732Sdavemq #endif 12173859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 12183859Sml29623 statsp = nxgep->statsp; 12193859Sml29623 12203859Sml29623 /* 12213859Sml29623 * Initialize the xcvr statistics. 12223859Sml29623 */ 12233859Sml29623 statsp->mac_stats.cap_autoneg = 0; 12243859Sml29623 statsp->mac_stats.cap_100T4 = 0; 12253859Sml29623 statsp->mac_stats.cap_100fdx = 0; 12263859Sml29623 statsp->mac_stats.cap_100hdx = 0; 12273859Sml29623 statsp->mac_stats.cap_10fdx = 0; 12283859Sml29623 statsp->mac_stats.cap_10hdx = 0; 12293859Sml29623 statsp->mac_stats.cap_asmpause = 0; 12303859Sml29623 statsp->mac_stats.cap_pause = 0; 12313859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 12323859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 12333859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 12343859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 12353859Sml29623 12363859Sml29623 /* 12373859Sml29623 * Initialize the link statistics. 12383859Sml29623 */ 12393859Sml29623 statsp->mac_stats.link_T4 = 0; 12403859Sml29623 statsp->mac_stats.link_asmpause = 0; 12413859Sml29623 statsp->mac_stats.link_pause = 0; 12423859Sml29623 1243*4732Sdavemq if (nxgep->xcvr.xcvr_init) { 1244*4732Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 12453859Sml29623 if (status != NXGE_OK) 12463859Sml29623 goto fail; 1247*4732Sdavemq statsp->mac_stats.xcvr_inits++; 12483859Sml29623 } 12493859Sml29623 1250*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 1251*4732Sdavemq portn)); 12523859Sml29623 return (NXGE_OK); 12533859Sml29623 12543859Sml29623 fail: 12553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1256*4732Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 1257*4732Sdavemq portn)); 12583859Sml29623 return (status); 12593859Sml29623 } 12603859Sml29623 12613859Sml29623 12623859Sml29623 /* Initialize the TxMAC sub-block */ 12633859Sml29623 12643859Sml29623 nxge_status_t 12653859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 12663859Sml29623 { 12673859Sml29623 npi_attr_t ap; 12683859Sml29623 uint8_t portn; 12693859Sml29623 nxge_port_mode_t portmode; 12703859Sml29623 nxge_port_t portt; 12713859Sml29623 npi_handle_t handle; 12723859Sml29623 npi_status_t rs = NPI_SUCCESS; 12733859Sml29623 12743859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 12753859Sml29623 portt = nxgep->mac.porttype; 12763859Sml29623 handle = nxgep->npi_handle; 12773859Sml29623 portmode = nxgep->mac.portmode; 12783859Sml29623 12793859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 12803859Sml29623 portn)); 12813859Sml29623 12823859Sml29623 /* Set Max and Min Frame Size */ 12833859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 12843859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 12853859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 12863859Sml29623 } else { 12873859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 12883859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 12893859Sml29623 } 12903859Sml29623 12913859Sml29623 if (rs != NPI_SUCCESS) 12923859Sml29623 goto fail; 12933859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || 12943859Sml29623 nxgep->mac.is_jumbo == B_TRUE) 12953859Sml29623 nxgep->mac.maxframesize = 0x2400; 12963859Sml29623 else 12973859Sml29623 nxgep->mac.maxframesize = 0x5EE + 4; 12983859Sml29623 nxgep->mac.minframesize = 64; 12993859Sml29623 13003859Sml29623 if (portt == PORT_TYPE_XMAC) { 13013859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 13023859Sml29623 0)) != NPI_SUCCESS) 13033859Sml29623 goto fail; 13043859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 13053859Sml29623 if ((portmode == PORT_10G_FIBER) || 13063859Sml29623 (portmode == PORT_10G_COPPER)) { 13073859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 13083859Sml29623 XGMII_IPG_12_15, rs); 13093859Sml29623 if (rs != NPI_SUCCESS) 13103859Sml29623 goto fail; 13113859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 13123859Sml29623 } else { 13133859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 13143859Sml29623 MII_GMII_IPG_12, rs); 13153859Sml29623 if (rs != NPI_SUCCESS) 13163859Sml29623 goto fail; 13173859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 13183859Sml29623 } 13193859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 13203859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 13213859Sml29623 goto fail; 13223859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 13233859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 13243859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 13253859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 13263859Sml29623 13273859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 13283859Sml29623 != NPI_SUCCESS) 13293859Sml29623 goto fail; 13303859Sml29623 13313859Sml29623 } else { 13323859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 13333859Sml29623 0)) != NPI_SUCCESS) 13343859Sml29623 goto fail; 13353859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 13363859Sml29623 13373859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 13383859Sml29623 rs); 13393859Sml29623 if (rs != NPI_SUCCESS) 13403859Sml29623 goto fail; 13413859Sml29623 nxgep->mac.ctrltype = 0x8808; 13423859Sml29623 13433859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 13443859Sml29623 if (rs != NPI_SUCCESS) 13453859Sml29623 goto fail; 13463859Sml29623 nxgep->mac.pa_size = 0x7; 13473859Sml29623 13483859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 13493859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 13503859Sml29623 goto fail; 13513859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 13523859Sml29623 } 13533859Sml29623 13543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 13553859Sml29623 portn)); 13563859Sml29623 13573859Sml29623 return (NXGE_OK); 13583859Sml29623 fail: 13593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13603859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 13613859Sml29623 portn)); 13623859Sml29623 13633859Sml29623 return (NXGE_ERROR | rs); 13643859Sml29623 } 13653859Sml29623 13663859Sml29623 /* Initialize the RxMAC sub-block */ 13673859Sml29623 13683859Sml29623 nxge_status_t 13693859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 13703859Sml29623 { 13713859Sml29623 npi_attr_t ap; 13723859Sml29623 uint32_t i; 13733859Sml29623 uint16_t hashtab_e; 13743859Sml29623 p_hash_filter_t hash_filter; 13753859Sml29623 nxge_port_t portt; 13763859Sml29623 uint8_t portn; 13773859Sml29623 npi_handle_t handle; 13783859Sml29623 npi_status_t rs = NPI_SUCCESS; 13793859Sml29623 uint16_t *addr16p; 13803859Sml29623 uint16_t addr0, addr1, addr2; 13813859Sml29623 xmac_rx_config_t xconfig; 13823859Sml29623 bmac_rx_config_t bconfig; 13833859Sml29623 13843859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 13853859Sml29623 13863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 13873859Sml29623 portn)); 13883859Sml29623 handle = nxgep->npi_handle; 13893859Sml29623 portt = nxgep->mac.porttype; 13903859Sml29623 13913859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 13923859Sml29623 addr0 = ntohs(addr16p[2]); 13933859Sml29623 addr1 = ntohs(addr16p[1]); 13943859Sml29623 addr2 = ntohs(addr16p[0]); 13953859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 13963859Sml29623 rs); 13973859Sml29623 13983859Sml29623 if (rs != NPI_SUCCESS) 13993859Sml29623 goto fail; 14003859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 14013859Sml29623 if (rs != NPI_SUCCESS) 14023859Sml29623 goto fail; 14033859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 14043859Sml29623 if (rs != NPI_SUCCESS) 14053859Sml29623 goto fail; 14063859Sml29623 14073859Sml29623 /* 14083859Sml29623 * Load the multicast hash filter bits. 14093859Sml29623 */ 14103859Sml29623 hash_filter = nxgep->hash_filter; 14113859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 14123859Sml29623 if (hash_filter != NULL) { 14133859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 14143859Sml29623 (NMCFILTER_REGS - 1) - i]; 14153859Sml29623 } else { 14163859Sml29623 hashtab_e = 0; 14173859Sml29623 } 14183859Sml29623 14193859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 14203859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 14213859Sml29623 goto fail; 14223859Sml29623 } 14233859Sml29623 14243859Sml29623 if (portt == PORT_TYPE_XMAC) { 14253859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 14263859Sml29623 0)) != NPI_SUCCESS) 14273859Sml29623 goto fail; 14283859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 14293859Sml29623 14303859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 14313859Sml29623 14323859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 14333859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 14343859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 14353859Sml29623 14363859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 14373859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 14383859Sml29623 14393859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 14403859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 14413859Sml29623 14423859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 14433859Sml29623 14443859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 14453859Sml29623 xconfig)) != NPI_SUCCESS) 14463859Sml29623 goto fail; 14473859Sml29623 nxgep->mac.rx_config = xconfig; 14483859Sml29623 14493859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 14503859Sml29623 14513859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 14523859Sml29623 != NPI_SUCCESS) 14533859Sml29623 goto fail; 14543859Sml29623 } else { 14553859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 14563859Sml29623 14573859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 14583859Sml29623 0) != NPI_SUCCESS) 14593859Sml29623 goto fail; 14603859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 14613859Sml29623 14623859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 14633859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 14643859Sml29623 14653859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 14663859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 14673859Sml29623 14683859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 14693859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 14703859Sml29623 14713859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 14723859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 14733859Sml29623 bconfig)) != NPI_SUCCESS) 14743859Sml29623 goto fail; 14753859Sml29623 nxgep->mac.rx_config = bconfig; 14763859Sml29623 14773859Sml29623 /* Always enable comparison of mac unique address */ 14783859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 14793859Sml29623 != NPI_SUCCESS) 14803859Sml29623 goto fail; 14813859Sml29623 } 14823859Sml29623 14833859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 14843859Sml29623 portn)); 14853859Sml29623 14863859Sml29623 return (NXGE_OK); 14873859Sml29623 14883859Sml29623 fail: 14893859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14903859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 14913859Sml29623 portn)); 14923859Sml29623 14933859Sml29623 return (NXGE_ERROR | rs); 14943859Sml29623 } 14953859Sml29623 14963859Sml29623 /* Enable TXMAC */ 14973859Sml29623 14983859Sml29623 nxge_status_t 14993859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 15003859Sml29623 { 15013859Sml29623 npi_handle_t handle; 15023859Sml29623 npi_status_t rs = NPI_SUCCESS; 15033859Sml29623 nxge_status_t status = NXGE_OK; 15043859Sml29623 15053859Sml29623 handle = nxgep->npi_handle; 15063859Sml29623 15073859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 15083859Sml29623 nxgep->mac.portnum)); 15093859Sml29623 15103859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 15113859Sml29623 goto fail; 15123859Sml29623 15133859Sml29623 /* based on speed */ 15143859Sml29623 nxgep->msg_min = ETHERMIN; 15153859Sml29623 15163859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15173859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 15183859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 15193859Sml29623 goto fail; 15203859Sml29623 } else { 15213859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 15223859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 15233859Sml29623 goto fail; 15243859Sml29623 } 15253859Sml29623 15263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 15273859Sml29623 nxgep->mac.portnum)); 15283859Sml29623 15293859Sml29623 return (NXGE_OK); 15303859Sml29623 fail: 15313859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15323859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 15333859Sml29623 nxgep->mac.portnum)); 15343859Sml29623 if (rs != NPI_SUCCESS) 15353859Sml29623 return (NXGE_ERROR | rs); 15363859Sml29623 else 15373859Sml29623 return (status); 15383859Sml29623 } 15393859Sml29623 15403859Sml29623 /* Disable TXMAC */ 15413859Sml29623 15423859Sml29623 nxge_status_t 15433859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 15443859Sml29623 { 15453859Sml29623 npi_handle_t handle; 15463859Sml29623 npi_status_t rs = NPI_SUCCESS; 15473859Sml29623 15483859Sml29623 handle = nxgep->npi_handle; 15493859Sml29623 15503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 15513859Sml29623 nxgep->mac.portnum)); 15523859Sml29623 15533859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15543859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 15553859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 15563859Sml29623 goto fail; 15573859Sml29623 } else { 15583859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 15593859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 15603859Sml29623 goto fail; 15613859Sml29623 } 15623859Sml29623 15633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 15643859Sml29623 nxgep->mac.portnum)); 15653859Sml29623 return (NXGE_OK); 15663859Sml29623 fail: 15673859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15683859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 15693859Sml29623 nxgep->mac.portnum)); 15703859Sml29623 return (NXGE_ERROR | rs); 15713859Sml29623 } 15723859Sml29623 15733859Sml29623 /* Enable RXMAC */ 15743859Sml29623 15753859Sml29623 nxge_status_t 15763859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 15773859Sml29623 { 15783859Sml29623 npi_handle_t handle; 15793859Sml29623 uint8_t portn; 15803859Sml29623 npi_status_t rs = NPI_SUCCESS; 15813859Sml29623 nxge_status_t status = NXGE_OK; 15823859Sml29623 15833859Sml29623 handle = nxgep->npi_handle; 15843859Sml29623 portn = nxgep->mac.portnum; 15853859Sml29623 15863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 15873859Sml29623 portn)); 15883859Sml29623 15893859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 15903859Sml29623 goto fail; 15913859Sml29623 15923859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15933859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 15943859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 15953859Sml29623 goto fail; 15963859Sml29623 } else { 15973859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 15983859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 15993859Sml29623 goto fail; 16003859Sml29623 } 16013859Sml29623 16023859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 16033859Sml29623 portn)); 16043859Sml29623 16053859Sml29623 return (NXGE_OK); 16063859Sml29623 fail: 16073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16083859Sml29623 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 16093859Sml29623 portn)); 16103859Sml29623 16113859Sml29623 if (rs != NPI_SUCCESS) 16123859Sml29623 return (NXGE_ERROR | rs); 16133859Sml29623 else 16143859Sml29623 return (status); 16153859Sml29623 } 16163859Sml29623 16173859Sml29623 /* Disable RXMAC */ 16183859Sml29623 16193859Sml29623 nxge_status_t 16203859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 16213859Sml29623 { 16223859Sml29623 npi_handle_t handle; 16233859Sml29623 uint8_t portn; 16243859Sml29623 npi_status_t rs = NPI_SUCCESS; 16253859Sml29623 16263859Sml29623 handle = nxgep->npi_handle; 16273859Sml29623 portn = nxgep->mac.portnum; 16283859Sml29623 16293859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 16303859Sml29623 portn)); 16313859Sml29623 16323859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 16333859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 16343859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 16353859Sml29623 goto fail; 16363859Sml29623 } else { 16373859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 16383859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 16393859Sml29623 goto fail; 16403859Sml29623 } 16413859Sml29623 16423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 16433859Sml29623 portn)); 16443859Sml29623 return (NXGE_OK); 16453859Sml29623 fail: 16463859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16473859Sml29623 "nxgep_rx_mac_disable: ", 16483859Sml29623 "Failed to disable port<%d> RxMAC", 16493859Sml29623 portn)); 16503859Sml29623 16513859Sml29623 return (NXGE_ERROR | rs); 16523859Sml29623 } 16533859Sml29623 16543859Sml29623 /* Reset TXMAC */ 16553859Sml29623 16563859Sml29623 nxge_status_t 16573859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 16583859Sml29623 { 16593859Sml29623 npi_handle_t handle; 16603859Sml29623 uint8_t portn; 16613859Sml29623 npi_status_t rs = NPI_SUCCESS; 16623859Sml29623 16633859Sml29623 handle = nxgep->npi_handle; 16643859Sml29623 portn = nxgep->mac.portnum; 16653859Sml29623 16663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 16673859Sml29623 portn)); 16683859Sml29623 16693859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 16703859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 16713859Sml29623 != NPI_SUCCESS) 16723859Sml29623 goto fail; 16733859Sml29623 } else { 16743859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 16753859Sml29623 != NPI_SUCCESS) 16763859Sml29623 goto fail; 16773859Sml29623 } 16783859Sml29623 16793859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 16803859Sml29623 portn)); 16813859Sml29623 16823859Sml29623 return (NXGE_OK); 16833859Sml29623 fail: 16843859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16853859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 16863859Sml29623 portn)); 16873859Sml29623 16883859Sml29623 return (NXGE_ERROR | rs); 16893859Sml29623 } 16903859Sml29623 16913859Sml29623 /* Reset RXMAC */ 16923859Sml29623 16933859Sml29623 nxge_status_t 16943859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 16953859Sml29623 { 16963859Sml29623 npi_handle_t handle; 16973859Sml29623 uint8_t portn; 16983859Sml29623 npi_status_t rs = NPI_SUCCESS; 16993859Sml29623 17003859Sml29623 handle = nxgep->npi_handle; 17013859Sml29623 portn = nxgep->mac.portnum; 17023859Sml29623 17033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 17043859Sml29623 portn)); 17053859Sml29623 17063859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 17073859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 17083859Sml29623 != NPI_SUCCESS) 17093859Sml29623 goto fail; 17103859Sml29623 } else { 17113859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 17123859Sml29623 != NPI_SUCCESS) 17133859Sml29623 goto fail; 17143859Sml29623 } 17153859Sml29623 17163859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 17173859Sml29623 portn)); 17183859Sml29623 17193859Sml29623 return (NXGE_OK); 17203859Sml29623 fail: 17213859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17223859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 17233859Sml29623 portn)); 17243859Sml29623 return (NXGE_ERROR | rs); 17253859Sml29623 } 17263859Sml29623 1727*4732Sdavemq /* 10G fiber link interrupt start routine */ 1728*4732Sdavemq 1729*4732Sdavemq static nxge_status_t 1730*4732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 1731*4732Sdavemq { 1732*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1733*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1734*4732Sdavemq 1735*4732Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 1736*4732Sdavemq 1737*4732Sdavemq if (rs != NPI_SUCCESS) 1738*4732Sdavemq return (NXGE_ERROR | rs); 1739*4732Sdavemq else 1740*4732Sdavemq return (NXGE_OK); 1741*4732Sdavemq } 1742*4732Sdavemq 1743*4732Sdavemq /* 10G fiber link interrupt stop routine */ 1744*4732Sdavemq 1745*4732Sdavemq static nxge_status_t 1746*4732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 1747*4732Sdavemq { 1748*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1749*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1750*4732Sdavemq 1751*4732Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 1752*4732Sdavemq 1753*4732Sdavemq if (rs != NPI_SUCCESS) 1754*4732Sdavemq return (NXGE_ERROR | rs); 1755*4732Sdavemq else 1756*4732Sdavemq return (NXGE_OK); 1757*4732Sdavemq } 1758*4732Sdavemq 1759*4732Sdavemq /* 1G fiber link interrupt start routine */ 1760*4732Sdavemq 1761*4732Sdavemq static nxge_status_t 1762*4732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 1763*4732Sdavemq { 1764*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1765*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1766*4732Sdavemq 1767*4732Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 1768*4732Sdavemq if (rs != NPI_SUCCESS) 1769*4732Sdavemq return (NXGE_ERROR | rs); 1770*4732Sdavemq else 1771*4732Sdavemq return (NXGE_OK); 1772*4732Sdavemq } 1773*4732Sdavemq 1774*4732Sdavemq /* 1G fiber link interrupt stop routine */ 1775*4732Sdavemq 1776*4732Sdavemq static nxge_status_t 1777*4732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 1778*4732Sdavemq { 1779*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1780*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1781*4732Sdavemq 1782*4732Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 1783*4732Sdavemq 1784*4732Sdavemq if (rs != NPI_SUCCESS) 1785*4732Sdavemq return (NXGE_ERROR | rs); 1786*4732Sdavemq else 1787*4732Sdavemq return (NXGE_OK); 1788*4732Sdavemq } 1789*4732Sdavemq 1790*4732Sdavemq /* 1G copper link interrupt start routine */ 1791*4732Sdavemq 1792*4732Sdavemq static nxge_status_t 1793*4732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 1794*4732Sdavemq { 1795*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1796*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1797*4732Sdavemq 1798*4732Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 1799*4732Sdavemq MII_BMSR, BMSR_LSTATUS); 1800*4732Sdavemq 1801*4732Sdavemq if (rs != NPI_SUCCESS) 1802*4732Sdavemq return (NXGE_ERROR | rs); 1803*4732Sdavemq else 1804*4732Sdavemq return (NXGE_OK); 1805*4732Sdavemq } 1806*4732Sdavemq 1807*4732Sdavemq /* 1G copper link interrupt stop routine */ 1808*4732Sdavemq 1809*4732Sdavemq static nxge_status_t 1810*4732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 1811*4732Sdavemq { 1812*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 1813*4732Sdavemq uint8_t portn = nxgep->mac.portnum; 1814*4732Sdavemq 1815*4732Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 1816*4732Sdavemq 1817*4732Sdavemq if (rs != NPI_SUCCESS) 1818*4732Sdavemq return (NXGE_ERROR | rs); 1819*4732Sdavemq else 1820*4732Sdavemq return (NXGE_OK); 1821*4732Sdavemq } 1822*4732Sdavemq 1823*4732Sdavemq /* Enable/Disable Link Status change interrupt */ 18243859Sml29623 18253859Sml29623 nxge_status_t 18263859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 18273859Sml29623 { 1828*4732Sdavemq uint8_t portn; 1829*4732Sdavemq nxge_status_t status = NXGE_OK; 18303859Sml29623 18313859Sml29623 portn = nxgep->mac.portnum; 18323859Sml29623 18333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 1834*4732Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 1835*4732Sdavemq return (NXGE_OK); 1836*4732Sdavemq 1837*4732Sdavemq if (enable == LINK_INTR_START) 1838*4732Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 1839*4732Sdavemq else if (enable == LINK_INTR_STOP) 1840*4732Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 1841*4732Sdavemq if (status != NXGE_OK) 1842*4732Sdavemq goto fail; 18433859Sml29623 18443859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 18453859Sml29623 18463859Sml29623 return (NXGE_OK); 18473859Sml29623 fail: 18483859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18493859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 18503859Sml29623 portn)); 18513859Sml29623 1852*4732Sdavemq return (status); 18533859Sml29623 } 18543859Sml29623 18553859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 18563859Sml29623 18573859Sml29623 nxge_status_t 18583859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 18593859Sml29623 { 18603859Sml29623 p_nxge_param_t param_arr; 18613859Sml29623 p_nxge_stats_t statsp; 18623859Sml29623 uint8_t xcvr_portn; 18633859Sml29623 p_mii_regs_t mii_regs; 18643859Sml29623 mii_bmcr_t bmcr; 18653859Sml29623 mii_bmsr_t bmsr; 18663859Sml29623 mii_anar_t anar; 18673859Sml29623 mii_gcr_t gcr; 18683859Sml29623 mii_esr_t esr; 18693859Sml29623 mii_aux_ctl_t bcm5464r_aux; 18703859Sml29623 int status = NXGE_OK; 18713859Sml29623 18723859Sml29623 uint_t delay; 18733859Sml29623 18743859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 18753859Sml29623 18763859Sml29623 param_arr = nxgep->param_arr; 18773859Sml29623 statsp = nxgep->statsp; 18783859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 18793859Sml29623 18803859Sml29623 mii_regs = NULL; 18813859Sml29623 18823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18833859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 18843859Sml29623 18853859Sml29623 /* 18863859Sml29623 * Reset the transceiver. 18873859Sml29623 */ 18883859Sml29623 delay = 0; 18893859Sml29623 bmcr.value = 0; 18903859Sml29623 bmcr.bits.reset = 1; 18913859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18923859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 18933859Sml29623 goto fail; 18943859Sml29623 do { 18953859Sml29623 drv_usecwait(500); 18963859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 18973859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 18983859Sml29623 != NXGE_OK) 18993859Sml29623 goto fail; 19003859Sml29623 delay++; 19013859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 19023859Sml29623 if (delay == 1000) { 19033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 19043859Sml29623 goto fail; 19053859Sml29623 } 19063859Sml29623 19073859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19083859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 19093859Sml29623 &bmsr.value)) != NXGE_OK) 19103859Sml29623 goto fail; 19113859Sml29623 19123859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 19133859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 19143859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 19153859Sml29623 param_arr[param_anar_100hdx].value = 0; 19163859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 19173859Sml29623 param_arr[param_anar_10hdx].value = 0; 19183859Sml29623 19193859Sml29623 /* 19203859Sml29623 * Initialize the xcvr statistics. 19213859Sml29623 */ 19223859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 19233859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 19243859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 19253859Sml29623 statsp->mac_stats.cap_100hdx = 0; 19263859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 19273859Sml29623 statsp->mac_stats.cap_10hdx = 0; 19283859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 19293859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 19303859Sml29623 19313859Sml29623 /* 19323859Sml29623 * Initialise the xcvr advertised capability statistics. 19333859Sml29623 */ 19343859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 19353859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 19363859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 19373859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 19383859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 19393859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 19403859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 19413859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 19423859Sml29623 statsp->mac_stats.adv_cap_asmpause = 19433859Sml29623 param_arr[param_anar_asmpause].value; 19443859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 19453859Sml29623 19463859Sml29623 19473859Sml29623 /* 19483859Sml29623 * Check for extended status just in case we're 19493859Sml29623 * running a Gigibit phy. 19503859Sml29623 */ 19513859Sml29623 if (bmsr.bits.extend_status) { 19523859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19533859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 19543859Sml29623 != NXGE_OK) 19553859Sml29623 goto fail; 19563859Sml29623 param_arr[param_anar_1000fdx].value &= 19573859Sml29623 esr.bits.link_1000fdx; 19583859Sml29623 param_arr[param_anar_1000hdx].value = 0; 19593859Sml29623 19603859Sml29623 statsp->mac_stats.cap_1000fdx = 19613859Sml29623 (esr.bits.link_1000Xfdx || 19623859Sml29623 esr.bits.link_1000fdx); 19633859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 19643859Sml29623 } else { 19653859Sml29623 param_arr[param_anar_1000fdx].value = 0; 19663859Sml29623 param_arr[param_anar_1000hdx].value = 0; 19673859Sml29623 } 19683859Sml29623 19693859Sml29623 /* 19703859Sml29623 * Initialize 1G Statistics once the capability is established. 19713859Sml29623 */ 19723859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 19733859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 19743859Sml29623 19753859Sml29623 /* 19763859Sml29623 * Initialise the link statistics. 19773859Sml29623 */ 19783859Sml29623 statsp->mac_stats.link_T4 = 0; 19793859Sml29623 statsp->mac_stats.link_asmpause = 0; 19803859Sml29623 statsp->mac_stats.link_pause = 0; 19813859Sml29623 statsp->mac_stats.link_speed = 0; 19823859Sml29623 statsp->mac_stats.link_duplex = 0; 19833859Sml29623 statsp->mac_stats.link_up = 0; 19843859Sml29623 19853859Sml29623 /* 19863859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 19873859Sml29623 */ 19883859Sml29623 bmcr.value = 0; 19893859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 19903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 19913859Sml29623 goto fail; 19923859Sml29623 19933859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 19943859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 19953859Sml29623 bmcr.bits.loopback = 1; 19963859Sml29623 bmcr.bits.enable_autoneg = 0; 19973859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 19983859Sml29623 bmcr.bits.speed_1000_sel = 1; 19993859Sml29623 bmcr.bits.duplex_mode = 1; 20003859Sml29623 param_arr[param_autoneg].value = 0; 20013859Sml29623 } else { 20023859Sml29623 bmcr.bits.loopback = 0; 20033859Sml29623 } 20043859Sml29623 20053859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 20063859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 20073859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 20083859Sml29623 param_arr[param_autoneg].value = 0; 20093859Sml29623 bcm5464r_aux.value = 0; 20103859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 20113859Sml29623 bcm5464r_aux.bits.write_1 = 1; 20123859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20133859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 20143859Sml29623 != NXGE_OK) 20153859Sml29623 goto fail; 20163859Sml29623 } 20173859Sml29623 20183859Sml29623 if (param_arr[param_autoneg].value) { 20193859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20203859Sml29623 "Restarting Auto-negotiation.")); 20213859Sml29623 /* 20223859Sml29623 * Setup our Auto-negotiation advertisement register. 20233859Sml29623 */ 20243859Sml29623 anar.value = 0; 20253859Sml29623 anar.bits.selector = 1; 20263859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 20273859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 20283859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 20293859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 20303859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 20313859Sml29623 anar.bits.cap_asmpause = 0; 20323859Sml29623 anar.bits.cap_pause = 0; 20333859Sml29623 if (param_arr[param_anar_1000fdx].value || 20343859Sml29623 param_arr[param_anar_100fdx].value || 20353859Sml29623 param_arr[param_anar_10fdx].value) { 20363859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 20373859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 20383859Sml29623 } 20393859Sml29623 20403859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20413859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 20423859Sml29623 != NXGE_OK) 20433859Sml29623 goto fail; 20443859Sml29623 if (bmsr.bits.extend_status) { 20453859Sml29623 gcr.value = 0; 20463859Sml29623 gcr.bits.ms_mode_en = 20473859Sml29623 param_arr[param_master_cfg_enable].value; 20483859Sml29623 gcr.bits.master = 20493859Sml29623 param_arr[param_master_cfg_value].value; 20503859Sml29623 gcr.bits.link_1000fdx = 20513859Sml29623 param_arr[param_anar_1000fdx].value; 20523859Sml29623 gcr.bits.link_1000hdx = 20533859Sml29623 param_arr[param_anar_1000hdx].value; 20543859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20553859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 20563859Sml29623 != NXGE_OK) 20573859Sml29623 goto fail; 20583859Sml29623 } 20593859Sml29623 20603859Sml29623 bmcr.bits.enable_autoneg = 1; 20613859Sml29623 bmcr.bits.restart_autoneg = 1; 20623859Sml29623 20633859Sml29623 } else { 20643859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 20653859Sml29623 bmcr.bits.speed_1000_sel = 20663859Sml29623 param_arr[param_anar_1000fdx].value | 20673859Sml29623 param_arr[param_anar_1000hdx].value; 20683859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 20693859Sml29623 (param_arr[param_anar_100fdx].value | 20703859Sml29623 param_arr[param_anar_100hdx].value); 20713859Sml29623 if (bmcr.bits.speed_1000_sel) { 20723859Sml29623 statsp->mac_stats.link_speed = 1000; 20733859Sml29623 gcr.value = 0; 20743859Sml29623 gcr.bits.ms_mode_en = 20753859Sml29623 param_arr[param_master_cfg_enable].value; 20763859Sml29623 gcr.bits.master = 20773859Sml29623 param_arr[param_master_cfg_value].value; 20783859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20793859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 20803859Sml29623 gcr.value)) 20813859Sml29623 != NXGE_OK) 20823859Sml29623 goto fail; 20833859Sml29623 if (param_arr[param_anar_1000fdx].value) { 20843859Sml29623 bmcr.bits.duplex_mode = 1; 20853859Sml29623 statsp->mac_stats.link_duplex = 2; 20863859Sml29623 } else 20873859Sml29623 statsp->mac_stats.link_duplex = 1; 20883859Sml29623 } else if (bmcr.bits.speed_sel) { 20893859Sml29623 statsp->mac_stats.link_speed = 100; 20903859Sml29623 if (param_arr[param_anar_100fdx].value) { 20913859Sml29623 bmcr.bits.duplex_mode = 1; 20923859Sml29623 statsp->mac_stats.link_duplex = 2; 20933859Sml29623 } else 20943859Sml29623 statsp->mac_stats.link_duplex = 1; 20953859Sml29623 } else { 20963859Sml29623 statsp->mac_stats.link_speed = 10; 20973859Sml29623 if (param_arr[param_anar_10fdx].value) { 20983859Sml29623 bmcr.bits.duplex_mode = 1; 20993859Sml29623 statsp->mac_stats.link_duplex = 2; 21003859Sml29623 } else 21013859Sml29623 statsp->mac_stats.link_duplex = 1; 21023859Sml29623 } 21033859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 21043859Sml29623 statsp->mac_stats.link_asmpause = 21053859Sml29623 statsp->mac_stats.cap_asmpause; 21063859Sml29623 statsp->mac_stats.link_pause = 21073859Sml29623 statsp->mac_stats.cap_pause; 21083859Sml29623 } 21093859Sml29623 21103859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 21113859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 21123859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 21133859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 21143859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 21153859Sml29623 gcr.value = 0; 21163859Sml29623 gcr.bits.ms_mode_en = 1; 21173859Sml29623 gcr.bits.master = 1; 21183859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 21193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 21203859Sml29623 gcr.value)) 21213859Sml29623 != NXGE_OK) 21223859Sml29623 goto fail; 21233859Sml29623 bmcr.value = 0; 21243859Sml29623 bmcr.bits.speed_1000_sel = 1; 21253859Sml29623 statsp->mac_stats.link_speed = 1000; 21263859Sml29623 } else if (statsp->port_stats.lb_mode 21273859Sml29623 == nxge_lb_ext100) { 21283859Sml29623 /* BCM5464R 100mbps external loopback mode */ 21293859Sml29623 bmcr.value = 0; 21303859Sml29623 bmcr.bits.speed_sel = 1; 21313859Sml29623 bmcr.bits.duplex_mode = 1; 21323859Sml29623 statsp->mac_stats.link_speed = 100; 21333859Sml29623 } else if (statsp->port_stats.lb_mode 21343859Sml29623 == nxge_lb_ext10) { 21353859Sml29623 /* BCM5464R 10mbps external loopback mode */ 21363859Sml29623 bmcr.value = 0; 21373859Sml29623 bmcr.bits.duplex_mode = 1; 21383859Sml29623 statsp->mac_stats.link_speed = 10; 21393859Sml29623 } 21403859Sml29623 } 21413859Sml29623 } 21423859Sml29623 21433859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 21443859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 21453859Sml29623 bmcr.value)) != NXGE_OK) 21463859Sml29623 goto fail; 21473859Sml29623 21483859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 21493859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 21503859Sml29623 goto fail; 21513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 21523859Sml29623 21533859Sml29623 /* 21543859Sml29623 * Initialize the xcvr status kept in the context structure. 21553859Sml29623 */ 21563859Sml29623 nxgep->soft_bmsr.value = 0; 21573859Sml29623 21583859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 21593859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 21603859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 21613859Sml29623 goto fail; 21623859Sml29623 21633859Sml29623 statsp->mac_stats.xcvr_inits++; 21643859Sml29623 nxgep->bmsr.value = 0; 21653859Sml29623 21663859Sml29623 fail: 21673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 21683859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 21693859Sml29623 return (status); 21703859Sml29623 } 21713859Sml29623 21723859Sml29623 /* Read from a MII compliant register */ 21733859Sml29623 21743859Sml29623 nxge_status_t 21753859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 21763859Sml29623 uint16_t *value) 21773859Sml29623 { 21783859Sml29623 npi_status_t rs = NPI_SUCCESS; 21793859Sml29623 21803859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 21813859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 21823859Sml29623 21833859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 21843859Sml29623 21853859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 21863859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 21873859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 21883859Sml29623 goto fail; 21893859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 21903859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 21913859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 21923859Sml29623 goto fail; 21933859Sml29623 } else 21943859Sml29623 goto fail; 21953859Sml29623 21963859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 21973859Sml29623 21983859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 21993859Sml29623 "xcvr_reg<%d> value=0x%x", 22003859Sml29623 xcvr_portn, xcvr_reg, *value)); 22013859Sml29623 return (NXGE_OK); 22023859Sml29623 fail: 22033859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22043859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22053859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 22063859Sml29623 xcvr_portn)); 22073859Sml29623 22083859Sml29623 return (NXGE_ERROR | rs); 22093859Sml29623 } 22103859Sml29623 22113859Sml29623 /* Write to a MII compliant Register */ 22123859Sml29623 22133859Sml29623 nxge_status_t 22143859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 22153859Sml29623 uint16_t value) 22163859Sml29623 { 22173859Sml29623 npi_status_t rs = NPI_SUCCESS; 22183859Sml29623 22193859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 22203859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 22213859Sml29623 value)); 22223859Sml29623 22233859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 22243859Sml29623 22253859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 22263859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 22273859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 22283859Sml29623 goto fail; 22293859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 22303859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 22313859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 22323859Sml29623 goto fail; 22333859Sml29623 } else 22343859Sml29623 goto fail; 22353859Sml29623 22363859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22373859Sml29623 22383859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 22393859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 22403859Sml29623 return (NXGE_OK); 22413859Sml29623 fail: 22423859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22433859Sml29623 22443859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22453859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 22463859Sml29623 xcvr_portn)); 22473859Sml29623 22483859Sml29623 return (NXGE_ERROR | rs); 22493859Sml29623 } 22503859Sml29623 22513859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 22523859Sml29623 22533859Sml29623 nxge_status_t 22543859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 22553859Sml29623 uint16_t xcvr_reg, uint16_t *value) 22563859Sml29623 { 22573859Sml29623 npi_status_t rs = NPI_SUCCESS; 22583859Sml29623 22593859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 22603859Sml29623 xcvr_portn)); 22613859Sml29623 22623859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 22633859Sml29623 22643859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 22653859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 22663859Sml29623 goto fail; 22673859Sml29623 22683859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 22693859Sml29623 22703859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 22713859Sml29623 xcvr_portn)); 22723859Sml29623 return (NXGE_OK); 22733859Sml29623 fail: 22743859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 22753859Sml29623 22763859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22773859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 22783859Sml29623 xcvr_portn)); 22793859Sml29623 22803859Sml29623 return (NXGE_ERROR | rs); 22813859Sml29623 } 22823859Sml29623 22833859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 22843859Sml29623 22853859Sml29623 nxge_status_t 22863859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 22873859Sml29623 uint16_t xcvr_reg, uint16_t value) 22883859Sml29623 { 22893859Sml29623 npi_status_t rs = NPI_SUCCESS; 22903859Sml29623 22913859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 22923859Sml29623 xcvr_portn)); 22933859Sml29623 22943859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 22953859Sml29623 22963859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 22973859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 22983859Sml29623 goto fail; 22993859Sml29623 23003859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 23013859Sml29623 23023859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 23033859Sml29623 xcvr_portn)); 23043859Sml29623 return (NXGE_OK); 23053859Sml29623 fail: 23063859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 23073859Sml29623 23083859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23093859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 23103859Sml29623 xcvr_portn)); 23113859Sml29623 23123859Sml29623 return (NXGE_ERROR | rs); 23133859Sml29623 } 23143859Sml29623 23153859Sml29623 23163859Sml29623 /* Check MII to see if there is any link status change */ 23173859Sml29623 23183859Sml29623 nxge_status_t 23193859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 23203859Sml29623 nxge_link_state_t *link_up) 23213859Sml29623 { 23223859Sml29623 p_nxge_param_t param_arr; 23233859Sml29623 p_nxge_stats_t statsp; 23243859Sml29623 p_mii_regs_t mii_regs; 23253859Sml29623 p_mii_bmsr_t soft_bmsr; 23263859Sml29623 mii_anar_t anar; 23273859Sml29623 mii_anlpar_t anlpar; 23283859Sml29623 mii_anar_t an_common; 23293859Sml29623 mii_aner_t aner; 23303859Sml29623 mii_gsr_t gsr; 23313859Sml29623 nxge_status_t status = NXGE_OK; 23323859Sml29623 23333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 23343859Sml29623 23353859Sml29623 mii_regs = NULL; 23363859Sml29623 param_arr = nxgep->param_arr; 23373859Sml29623 statsp = nxgep->statsp; 23383859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 23393859Sml29623 *link_up = LINK_NO_CHANGE; 23403859Sml29623 23413859Sml29623 if (bmsr_ints.bits.link_status) { 23423859Sml29623 if (bmsr.bits.link_status) { 23433859Sml29623 soft_bmsr->bits.link_status = 1; 23443859Sml29623 } else { 23453859Sml29623 statsp->mac_stats.link_up = 0; 23463859Sml29623 soft_bmsr->bits.link_status = 0; 23473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 23483859Sml29623 "Link down cable problem")); 23493859Sml29623 *link_up = LINK_IS_DOWN; 23503859Sml29623 } 23513859Sml29623 } 23523859Sml29623 23533859Sml29623 if (param_arr[param_autoneg].value) { 23543859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 23553859Sml29623 if (bmsr.bits.auto_neg_complete) 23563859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 23573859Sml29623 else 23583859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 23593859Sml29623 } 23603859Sml29623 if (soft_bmsr->bits.link_status == 0) { 23613859Sml29623 statsp->mac_stats.link_T4 = 0; 23623859Sml29623 statsp->mac_stats.link_speed = 0; 23633859Sml29623 statsp->mac_stats.link_duplex = 0; 23643859Sml29623 statsp->mac_stats.link_asmpause = 0; 23653859Sml29623 statsp->mac_stats.link_pause = 0; 23663859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 23673859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 23683859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 23693859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 23703859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 23713859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 23723859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 23733859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 23743859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 23753859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 23763859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 23773859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 23783859Sml29623 } 23793859Sml29623 } else 23803859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 23813859Sml29623 23823859Sml29623 if ((bmsr_ints.bits.link_status || 23833859Sml29623 bmsr_ints.bits.auto_neg_complete) && 23843859Sml29623 soft_bmsr->bits.link_status && 23853859Sml29623 soft_bmsr->bits.auto_neg_complete) { 23863859Sml29623 statsp->mac_stats.link_up = 1; 23873859Sml29623 if (param_arr[param_autoneg].value) { 23883859Sml29623 if ((status = nxge_mii_read(nxgep, 23893859Sml29623 statsp->mac_stats.xcvr_portn, 23903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 23913859Sml29623 &anar.value)) != NXGE_OK) 23923859Sml29623 goto fail; 23933859Sml29623 if ((status = nxge_mii_read(nxgep, 23943859Sml29623 statsp->mac_stats.xcvr_portn, 23953859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 23963859Sml29623 &anlpar.value)) != NXGE_OK) 23973859Sml29623 goto fail; 23983859Sml29623 if ((status = nxge_mii_read(nxgep, 23993859Sml29623 statsp->mac_stats.xcvr_portn, 24003859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 24013859Sml29623 &aner.value)) != NXGE_OK) 24023859Sml29623 goto fail; 24033859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 24043859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 24053859Sml29623 statsp->mac_stats.lp_cap_100fdx = 24063859Sml29623 anlpar.bits.cap_100fdx; 24073859Sml29623 statsp->mac_stats.lp_cap_100hdx = 24083859Sml29623 anlpar.bits.cap_100hdx; 24093859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 24103859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 24113859Sml29623 statsp->mac_stats.lp_cap_asmpause = 24123859Sml29623 anlpar.bits.cap_asmpause; 24133859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 24143859Sml29623 an_common.value = anar.value & anlpar.value; 24153859Sml29623 if (param_arr[param_anar_1000fdx].value || 24163859Sml29623 param_arr[param_anar_1000hdx].value) { 24173859Sml29623 if ((status = nxge_mii_read(nxgep, 24183859Sml29623 statsp->mac_stats.xcvr_portn, 24193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 24203859Sml29623 &gsr.value)) 24213859Sml29623 != NXGE_OK) 24223859Sml29623 goto fail; 24233859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 24243859Sml29623 gsr.bits.link_1000fdx; 24253859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 24263859Sml29623 gsr.bits.link_1000hdx; 24273859Sml29623 if (param_arr[param_anar_1000fdx].value && 24283859Sml29623 gsr.bits.link_1000fdx) { 24293859Sml29623 statsp->mac_stats.link_speed = 1000; 24303859Sml29623 statsp->mac_stats.link_duplex = 2; 24313859Sml29623 } else if ( 24323859Sml29623 param_arr[param_anar_1000hdx].value && 24333859Sml29623 gsr.bits.link_1000hdx) { 24343859Sml29623 statsp->mac_stats.link_speed = 1000; 24353859Sml29623 statsp->mac_stats.link_duplex = 1; 24363859Sml29623 } 24373859Sml29623 } 24383859Sml29623 if ((an_common.value != 0) && 24393859Sml29623 !(statsp->mac_stats.link_speed)) { 24403859Sml29623 if (an_common.bits.cap_100T4) { 24413859Sml29623 statsp->mac_stats.link_T4 = 1; 24423859Sml29623 statsp->mac_stats.link_speed = 100; 24433859Sml29623 statsp->mac_stats.link_duplex = 1; 24443859Sml29623 } else if (an_common.bits.cap_100fdx) { 24453859Sml29623 statsp->mac_stats.link_speed = 100; 24463859Sml29623 statsp->mac_stats.link_duplex = 2; 24473859Sml29623 } else if (an_common.bits.cap_100hdx) { 24483859Sml29623 statsp->mac_stats.link_speed = 100; 24493859Sml29623 statsp->mac_stats.link_duplex = 1; 24503859Sml29623 } else if (an_common.bits.cap_10fdx) { 24513859Sml29623 statsp->mac_stats.link_speed = 10; 24523859Sml29623 statsp->mac_stats.link_duplex = 2; 24533859Sml29623 } else if (an_common.bits.cap_10hdx) { 24543859Sml29623 statsp->mac_stats.link_speed = 10; 24553859Sml29623 statsp->mac_stats.link_duplex = 1; 24563859Sml29623 } else { 24573859Sml29623 goto fail; 24583859Sml29623 } 24593859Sml29623 } 24603859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 24613859Sml29623 statsp->mac_stats.link_asmpause = 24623859Sml29623 an_common.bits.cap_asmpause; 24633859Sml29623 if (statsp->mac_stats.link_asmpause) 24643859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 24653859Sml29623 (statsp->mac_stats.lp_cap_pause 24663859Sml29623 == 1)) 24673859Sml29623 statsp->mac_stats.link_pause 24683859Sml29623 = 0; 24693859Sml29623 else 24703859Sml29623 statsp->mac_stats.link_pause 24713859Sml29623 = 1; 24723859Sml29623 else 24733859Sml29623 statsp->mac_stats.link_pause = 24743859Sml29623 an_common.bits.cap_pause; 24753859Sml29623 } 24763859Sml29623 } 24773859Sml29623 *link_up = LINK_IS_UP; 24783859Sml29623 } 24793859Sml29623 24803859Sml29623 if (nxgep->link_notify) { 24813859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 24823859Sml29623 LINK_IS_DOWN); 24833859Sml29623 nxgep->link_notify = B_FALSE; 24843859Sml29623 } 24853859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 24863859Sml29623 return (NXGE_OK); 24873859Sml29623 fail: 24883859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 24893859Sml29623 "nxge_mii_check: Unable to check MII")); 24903859Sml29623 return (status); 24913859Sml29623 } 24923859Sml29623 24933859Sml29623 /* Add a multicast address entry into the HW hash table */ 24943859Sml29623 24953859Sml29623 nxge_status_t 24963859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 24973859Sml29623 { 24983859Sml29623 uint32_t mchash; 24993859Sml29623 p_hash_filter_t hash_filter; 25003859Sml29623 uint16_t hash_bit; 25013859Sml29623 boolean_t rx_init = B_FALSE; 25023859Sml29623 uint_t j; 25033859Sml29623 nxge_status_t status = NXGE_OK; 25043859Sml29623 25053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 25063859Sml29623 25073859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 25083859Sml29623 mchash = crc32_mchash(addrp); 25093859Sml29623 if (nxgep->hash_filter == NULL) { 25103859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25113859Sml29623 "Allocating hash filter storage.")); 25123859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 25133859Sml29623 KM_SLEEP); 25143859Sml29623 } 25153859Sml29623 hash_filter = nxgep->hash_filter; 25163859Sml29623 j = mchash / HASH_REG_WIDTH; 25173859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 25183859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 25193859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 25203859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 25213859Sml29623 hash_filter->hash_ref_cnt++; 25223859Sml29623 rx_init = B_TRUE; 25233859Sml29623 } 25243859Sml29623 if (rx_init) { 25253859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 25263859Sml29623 goto fail; 25273859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 25283859Sml29623 goto fail; 25293859Sml29623 } 25303859Sml29623 25313859Sml29623 RW_EXIT(&nxgep->filter_lock); 25323859Sml29623 25333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 25343859Sml29623 25353859Sml29623 return (NXGE_OK); 25363859Sml29623 fail: 25373859Sml29623 RW_EXIT(&nxgep->filter_lock); 25383859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 25393859Sml29623 "Unable to add multicast address")); 25403859Sml29623 return (status); 25413859Sml29623 } 25423859Sml29623 25433859Sml29623 /* Remove a multicast address entry from the HW hash table */ 25443859Sml29623 25453859Sml29623 nxge_status_t 25463859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 25473859Sml29623 { 25483859Sml29623 uint32_t mchash; 25493859Sml29623 p_hash_filter_t hash_filter; 25503859Sml29623 uint16_t hash_bit; 25513859Sml29623 boolean_t rx_init = B_FALSE; 25523859Sml29623 uint_t j; 25533859Sml29623 nxge_status_t status = NXGE_OK; 25543859Sml29623 25553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 25563859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 25573859Sml29623 mchash = crc32_mchash(addrp); 25583859Sml29623 if (nxgep->hash_filter == NULL) { 25593859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25603859Sml29623 "Hash filter already de_allocated.")); 25613859Sml29623 RW_EXIT(&nxgep->filter_lock); 25623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 25633859Sml29623 return (NXGE_OK); 25643859Sml29623 } 25653859Sml29623 hash_filter = nxgep->hash_filter; 25663859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 25673859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 25683859Sml29623 j = mchash / HASH_REG_WIDTH; 25693859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 25703859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 25713859Sml29623 hash_filter->hash_ref_cnt--; 25723859Sml29623 rx_init = B_TRUE; 25733859Sml29623 } 25743859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 25753859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25763859Sml29623 "De-allocating hash filter storage.")); 25773859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 25783859Sml29623 nxgep->hash_filter = NULL; 25793859Sml29623 } 25803859Sml29623 25813859Sml29623 if (rx_init) { 25823859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 25833859Sml29623 goto fail; 25843859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 25853859Sml29623 goto fail; 25863859Sml29623 } 25873859Sml29623 RW_EXIT(&nxgep->filter_lock); 25883859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 25893859Sml29623 25903859Sml29623 return (NXGE_OK); 25913859Sml29623 fail: 25923859Sml29623 RW_EXIT(&nxgep->filter_lock); 25933859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 25943859Sml29623 "Unable to remove multicast address")); 25953859Sml29623 25963859Sml29623 return (status); 25973859Sml29623 } 25983859Sml29623 25993859Sml29623 /* Set MAC address into MAC address HW registers */ 26003859Sml29623 26013859Sml29623 nxge_status_t 26023859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 26033859Sml29623 { 26043859Sml29623 nxge_status_t status = NXGE_OK; 26053859Sml29623 26063859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 26073859Sml29623 26083859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 26093859Sml29623 /* 26103859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 26113859Sml29623 */ 26123859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 26133859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 26143859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 26153859Sml29623 goto nxge_set_mac_addr_exit; 26163859Sml29623 } 26173859Sml29623 nxgep->ouraddr = *addrp; 26183859Sml29623 /* 26193859Sml29623 * Set new interface local address and re-init device. 26203859Sml29623 * This is destructive to any other streams attached 26213859Sml29623 * to this device. 26223859Sml29623 */ 26233859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 26243859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 26253859Sml29623 goto fail; 26263859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 26273859Sml29623 goto fail; 26283859Sml29623 26293859Sml29623 RW_EXIT(&nxgep->filter_lock); 26303859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26313859Sml29623 goto nxge_set_mac_addr_end; 26323859Sml29623 nxge_set_mac_addr_exit: 26333859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26343859Sml29623 nxge_set_mac_addr_end: 26353859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 26363859Sml29623 26373859Sml29623 return (NXGE_OK); 26383859Sml29623 fail: 26393859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26403859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 26413859Sml29623 "Unable to set mac address")); 26423859Sml29623 return (status); 26433859Sml29623 } 26443859Sml29623 26454693Stm144005 static 26464693Stm144005 check_link_state_t 26474693Stm144005 nxge_check_link_stop( 26484693Stm144005 nxge_t *nxge) 26494693Stm144005 { 26504693Stm144005 /* If the poll has been cancelled, return STOP. */ 26514693Stm144005 MUTEX_ENTER(&nxge->poll_lock); 26524693Stm144005 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 26534693Stm144005 nxge->poll_state = LINK_MONITOR_STOP; 26544693Stm144005 nxge->nxge_link_poll_timerid = 0; 26554693Stm144005 cv_broadcast(&nxge->poll_cv); 26564693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 26574693Stm144005 26584693Stm144005 NXGE_DEBUG_MSG((nxge, MAC_CTL, 26594693Stm144005 "nxge_check_%s_link(port<%d>) stopped.", 26604693Stm144005 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 26614693Stm144005 nxge->mac.portnum)); 26624693Stm144005 return (CHECK_LINK_STOP); 26634693Stm144005 } 26644693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 26654693Stm144005 26664693Stm144005 return (CHECK_LINK_RESCHEDULE); 26674693Stm144005 } 26684693Stm144005 26693859Sml29623 /* Check status of MII (MIF or PCS) link */ 26703859Sml29623 2671*4732Sdavemq static nxge_status_t 26723859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 26733859Sml29623 { 26743859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 26753859Sml29623 mii_anlpar_t anlpar; 26763859Sml29623 mii_gsr_t gsr; 26773859Sml29623 p_mii_regs_t mii_regs; 26783859Sml29623 nxge_status_t status = NXGE_OK; 26793859Sml29623 uint8_t portn; 26803859Sml29623 nxge_link_state_t link_up; 26813859Sml29623 26824693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 26834693Stm144005 return (NXGE_ERROR); 26844693Stm144005 26854693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 26864693Stm144005 return (NXGE_OK); 26874693Stm144005 26883859Sml29623 portn = nxgep->mac.portnum; 26893859Sml29623 26903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 26914693Stm144005 portn)); 26923859Sml29623 26933859Sml29623 mii_regs = NULL; 26943859Sml29623 26953859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 26963859Sml29623 26973859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 26983859Sml29623 goto nxge_check_mii_link_exit; 26993859Sml29623 27003859Sml29623 if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 27013859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 27023859Sml29623 &bmsr_data.value)) != NXGE_OK) 27033859Sml29623 goto fail; 27043859Sml29623 27053859Sml29623 if (nxgep->param_arr[param_autoneg].value) { 27063859Sml29623 if ((status = nxge_mii_read(nxgep, 27073859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 27083859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 27093859Sml29623 &gsr.value)) != NXGE_OK) 27103859Sml29623 goto fail; 27113859Sml29623 if ((status = nxge_mii_read(nxgep, 27123859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 27133859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 27143859Sml29623 &anlpar.value)) != NXGE_OK) 27153859Sml29623 goto fail; 27163859Sml29623 if (nxgep->statsp->mac_stats.link_up && 27173859Sml29623 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 27183859Sml29623 gsr.bits.link_1000fdx) || 27193859Sml29623 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 27203859Sml29623 gsr.bits.link_1000hdx) || 27213859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 27223859Sml29623 anlpar.bits.cap_100T4) || 27233859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 27243859Sml29623 anlpar.bits.cap_100fdx) || 27253859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 27263859Sml29623 anlpar.bits.cap_100hdx) || 27273859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 27283859Sml29623 anlpar.bits.cap_10fdx) || 27293859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 27303859Sml29623 anlpar.bits.cap_10hdx))) { 27313859Sml29623 bmsr_data.bits.link_status = 0; 27323859Sml29623 } 27333859Sml29623 } 27343859Sml29623 27353859Sml29623 /* Workaround for link down issue */ 27363859Sml29623 if (bmsr_data.value == 0) { 2737*4732Sdavemq cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n", 2738*4732Sdavemq nxgep->instance); 27393859Sml29623 goto nxge_check_mii_link_exit; 27403859Sml29623 } 27413859Sml29623 27423859Sml29623 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 27433859Sml29623 nxgep->bmsr.value = bmsr_data.value; 27443859Sml29623 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up)) 27454693Stm144005 != NXGE_OK) 27463859Sml29623 goto fail; 27473859Sml29623 27483859Sml29623 nxge_check_mii_link_exit: 27493859Sml29623 RW_EXIT(&nxgep->filter_lock); 27503859Sml29623 if (link_up == LINK_IS_UP) { 27513859Sml29623 nxge_link_is_up(nxgep); 27523859Sml29623 } else if (link_up == LINK_IS_DOWN) { 27533859Sml29623 nxge_link_is_down(nxgep); 27543859Sml29623 } 27553859Sml29623 27563859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 27573859Sml29623 27583859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 27594693Stm144005 portn)); 27603859Sml29623 return (NXGE_OK); 27613859Sml29623 27623859Sml29623 fail: 27633859Sml29623 RW_EXIT(&nxgep->filter_lock); 27643859Sml29623 27653859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 27663859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27674693Stm144005 "nxge_check_mii_link: Failed to check link port<%d>", 27684693Stm144005 portn)); 27693859Sml29623 return (status); 27703859Sml29623 } 27713859Sml29623 27723859Sml29623 27733859Sml29623 /*ARGSUSED*/ 2774*4732Sdavemq static nxge_status_t 27753859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 27763859Sml29623 { 27773859Sml29623 uint8_t portn; 27783859Sml29623 27793859Sml29623 nxge_status_t status = NXGE_OK; 27803859Sml29623 boolean_t link_up; 27813859Sml29623 27824693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 27834693Stm144005 return (NXGE_ERROR); 27844693Stm144005 27854693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 27864693Stm144005 return (NXGE_OK); 27874693Stm144005 27883859Sml29623 portn = nxgep->mac.portnum; 27893859Sml29623 27903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 27914693Stm144005 portn)); 27923859Sml29623 27933859Sml29623 status = nxge_check_bcm8704_link(nxgep, &link_up); 27943859Sml29623 27953859Sml29623 if (status != NXGE_OK) 27963859Sml29623 goto fail; 27973859Sml29623 27983859Sml29623 if (link_up) { 27993859Sml29623 if (nxgep->link_notify || 28003859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 28013859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 28023859Sml29623 goto fail; 28033859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 28043859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 28053859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 28063859Sml29623 28073859Sml29623 nxge_link_is_up(nxgep); 28083859Sml29623 nxgep->link_notify = B_FALSE; 28093859Sml29623 } 28103859Sml29623 } else { 28113859Sml29623 if (nxgep->link_notify || 28123859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 28133859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 28143859Sml29623 goto fail; 28153859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2816*4732Sdavemq "Link down cable problem")); 28173859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 28183859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 28193859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 28203859Sml29623 28213859Sml29623 nxge_link_is_down(nxgep); 28223859Sml29623 nxgep->link_notify = B_FALSE; 28233859Sml29623 } 28243859Sml29623 } 28253859Sml29623 28263859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 28273859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 28284693Stm144005 portn)); 28293859Sml29623 return (NXGE_OK); 28303859Sml29623 28313859Sml29623 fail: 28324693Stm144005 (void) nxge_check_link_stop(nxgep); 28334693Stm144005 28343859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28354693Stm144005 "nxge_check_10g_link: Failed to check link port<%d>", 28364693Stm144005 portn)); 28373859Sml29623 return (status); 28383859Sml29623 } 28393859Sml29623 28403859Sml29623 28413859Sml29623 /* Declare link down */ 28423859Sml29623 28433859Sml29623 void 28443859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 28453859Sml29623 { 2846*4732Sdavemq p_nxge_stats_t statsp; 2847*4732Sdavemq char link_stat_msg[64]; 2848*4732Sdavemq 28493859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 28503859Sml29623 2851*4732Sdavemq statsp = nxgep->statsp; 2852*4732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 2853*4732Sdavemq statsp->mac_stats.xcvr_portn); 2854*4732Sdavemq 2855*4732Sdavemq if (nxge_no_msg == B_FALSE) { 2856*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 2857*4732Sdavemq } 2858*4732Sdavemq 28593859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 28603859Sml29623 28613859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 28623859Sml29623 } 28633859Sml29623 28643859Sml29623 /* Declare link up */ 28653859Sml29623 28663859Sml29623 void 28673859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 28683859Sml29623 { 2869*4732Sdavemq p_nxge_stats_t statsp; 2870*4732Sdavemq char link_stat_msg[64]; 28713859Sml29623 uint32_t val; 28723859Sml29623 28733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 28743859Sml29623 2875*4732Sdavemq statsp = nxgep->statsp; 2876*4732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 2877*4732Sdavemq statsp->mac_stats.xcvr_portn, 2878*4732Sdavemq statsp->mac_stats.link_speed); 2879*4732Sdavemq 2880*4732Sdavemq if (statsp->mac_stats.link_T4) 2881*4732Sdavemq (void) strcat(link_stat_msg, "T4"); 2882*4732Sdavemq else if (statsp->mac_stats.link_duplex == 2) 2883*4732Sdavemq (void) strcat(link_stat_msg, "full duplex"); 2884*4732Sdavemq else 2885*4732Sdavemq (void) strcat(link_stat_msg, "half duplex"); 2886*4732Sdavemq 28873859Sml29623 (void) nxge_xif_init(nxgep); 28883859Sml29623 28893859Sml29623 /* Clean up symbol errors incurred during link transition */ 28903859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 28913859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 28923859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 28933859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 28943859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 28953859Sml29623 } 28963859Sml29623 2897*4732Sdavemq if (nxge_no_msg == B_FALSE) { 2898*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 2899*4732Sdavemq } 2900*4732Sdavemq 29013859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 29023859Sml29623 29033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 29043859Sml29623 } 29053859Sml29623 29063859Sml29623 /* 29073859Sml29623 * Calculate the bit in the multicast address filter 29083859Sml29623 * that selects the given * address. 29093859Sml29623 * Note: For GEM, the last 8-bits are used. 29103859Sml29623 */ 29113859Sml29623 uint32_t 29123859Sml29623 crc32_mchash(p_ether_addr_t addr) 29133859Sml29623 { 29143859Sml29623 uint8_t *cp; 29153859Sml29623 uint32_t crc; 29163859Sml29623 uint32_t c; 29173859Sml29623 int byte; 29183859Sml29623 int bit; 29193859Sml29623 29203859Sml29623 cp = (uint8_t *)addr; 29213859Sml29623 crc = (uint32_t)0xffffffff; 29223859Sml29623 for (byte = 0; byte < 6; byte++) { 29233859Sml29623 c = (uint32_t)cp[byte]; 29243859Sml29623 for (bit = 0; bit < 8; bit++) { 29253859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 29263859Sml29623 crc = (crc >> 1)^0xedb88320; 29273859Sml29623 else 29283859Sml29623 crc = (crc >> 1); 29293859Sml29623 c >>= 1; 29303859Sml29623 } 29313859Sml29623 } 29323859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 29333859Sml29623 } 29343859Sml29623 29353859Sml29623 /* Reset serdes */ 29363859Sml29623 29373859Sml29623 nxge_status_t 29383859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 29393859Sml29623 { 29403859Sml29623 npi_handle_t handle; 29413859Sml29623 29423859Sml29623 handle = nxgep->npi_handle; 29433859Sml29623 29443859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 29453859Sml29623 drv_usecwait(500); 29463859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 29473859Sml29623 29483859Sml29623 return (NXGE_OK); 29493859Sml29623 } 29503859Sml29623 29513859Sml29623 /* Monitor link status using interrupt or polling */ 29523859Sml29623 29533859Sml29623 nxge_status_t 29543859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 29553859Sml29623 { 29563859Sml29623 nxge_status_t status = NXGE_OK; 29573859Sml29623 29583859Sml29623 /* 29594693Stm144005 * Return immediately if this is an imaginary XMAC port. 29604693Stm144005 * (At least, we don't have 4-port XMAC cards yet.) 29613859Sml29623 */ 29623859Sml29623 if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1)) 29633859Sml29623 return (NXGE_OK); 29643859Sml29623 29653859Sml29623 if (nxgep->statsp == NULL) { 29663859Sml29623 /* stats has not been allocated. */ 29673859Sml29623 return (NXGE_OK); 29683859Sml29623 } 29693859Sml29623 /* Don't check link if we're not in internal loopback mode */ 29703859Sml29623 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 29713859Sml29623 return (NXGE_OK); 29723859Sml29623 29733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 29744693Stm144005 "==> nxge_link_monitor port<%d> enable=%d", 29754693Stm144005 nxgep->mac.portnum, enable)); 29763859Sml29623 if (enable == LINK_MONITOR_START) { 29773859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 29783859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 29794693Stm144005 != NXGE_OK) 29803859Sml29623 goto fail; 29813859Sml29623 } else { 29824693Stm144005 timeout_id_t timerid; 29834693Stm144005 29844693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 29854693Stm144005 return (NXGE_OK); 29864693Stm144005 2987*4732Sdavemq if (nxgep->xcvr.check_link) { 2988*4732Sdavemq timerid = timeout( 2989*4732Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 29904693Stm144005 nxgep, 29914693Stm144005 drv_usectohz(LINK_MONITOR_PERIOD)); 2992*4732Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 2993*4732Sdavemq nxgep->nxge_link_poll_timerid = timerid; 2994*4732Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 2995*4732Sdavemq } else { 29964693Stm144005 return (NXGE_ERROR); 29973859Sml29623 } 29983859Sml29623 } 29993859Sml29623 } else { 30003859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 30013859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 30024693Stm144005 != NXGE_OK) 30033859Sml29623 goto fail; 30043859Sml29623 } else { 30054693Stm144005 clock_t rv; 30064693Stm144005 30074693Stm144005 MUTEX_ENTER(&nxgep->poll_lock); 30084693Stm144005 30094693Stm144005 /* If <timerid> == 0, the link monitor has */ 30104693Stm144005 /* never been started, or just now stopped. */ 30114693Stm144005 if (nxgep->nxge_link_poll_timerid == 0) { 30124693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 30134693Stm144005 return (NXGE_OK); 30144693Stm144005 } 30154693Stm144005 30164693Stm144005 nxgep->poll_state = LINK_MONITOR_STOPPING; 30174693Stm144005 rv = cv_timedwait(&nxgep->poll_cv, 30184693Stm144005 &nxgep->poll_lock, 30194693Stm144005 ddi_get_lbolt() + 30204693Stm144005 drv_usectohz(LM_WAIT_MULTIPLIER * 30214693Stm144005 LINK_MONITOR_PERIOD)); 30224693Stm144005 if (rv == -1) { 30234693Stm144005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30244693Stm144005 "==> stopping port %d: " 30254693Stm144005 "cv_timedwait(%d) timed out", 30264693Stm144005 nxgep->mac.portnum, nxgep->poll_state)); 30274693Stm144005 nxgep->poll_state = LINK_MONITOR_STOP; 30283859Sml29623 nxgep->nxge_link_poll_timerid = 0; 30293859Sml29623 } 30304693Stm144005 30314693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 30323859Sml29623 } 30333859Sml29623 } 30343859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30354693Stm144005 "<== nxge_link_monitor port<%d> enable=%d", 30364693Stm144005 nxgep->mac.portnum, enable)); 30373859Sml29623 return (NXGE_OK); 30383859Sml29623 fail: 30393859Sml29623 return (status); 30403859Sml29623 } 30413859Sml29623 30423859Sml29623 /* Set promiscous mode */ 30433859Sml29623 30443859Sml29623 nxge_status_t 30453859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 30463859Sml29623 { 30473859Sml29623 nxge_status_t status = NXGE_OK; 30483859Sml29623 3049*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 30503859Sml29623 30513859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 30523859Sml29623 30533859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 30543859Sml29623 30553859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 30563859Sml29623 goto fail; 30573859Sml29623 } 30583859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 30593859Sml29623 goto fail; 30603859Sml29623 } 30613859Sml29623 30623859Sml29623 RW_EXIT(&nxgep->filter_lock); 30633859Sml29623 30643859Sml29623 if (on) 30653859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 30663859Sml29623 else 30673859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 30683859Sml29623 30693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 30703859Sml29623 30713859Sml29623 return (NXGE_OK); 30723859Sml29623 fail: 30733859Sml29623 RW_EXIT(&nxgep->filter_lock); 30743859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 3075*4732Sdavemq "Unable to set promisc (%d)", on)); 30763859Sml29623 30773859Sml29623 return (status); 30783859Sml29623 } 30793859Sml29623 30803859Sml29623 /*ARGSUSED*/ 30813859Sml29623 uint_t 30823859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 30833859Sml29623 { 30843859Sml29623 #ifdef NXGE_DEBUG 30853859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 30863859Sml29623 #endif 30873859Sml29623 #if NXGE_MIF 30883859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 30893859Sml29623 uint32_t status; 30903859Sml29623 npi_handle_t handle; 30913859Sml29623 uint8_t portn; 30923859Sml29623 p_nxge_stats_t statsp; 30933859Sml29623 #endif 30943859Sml29623 30953859Sml29623 #ifdef NXGE_MIF 30963859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 30973859Sml29623 nxgep = ldvp->nxgep; 30983859Sml29623 } 30993859Sml29623 nxgep = ldvp->nxgep; 31003859Sml29623 #endif 31013859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 31023859Sml29623 31033859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 31043859Sml29623 return (DDI_INTR_CLAIMED); 31053859Sml29623 31063859Sml29623 mif_intr_fail: 31073859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 31083859Sml29623 return (DDI_INTR_UNCLAIMED); 31093859Sml29623 } 31103859Sml29623 31113859Sml29623 /*ARGSUSED*/ 31123859Sml29623 uint_t 31133859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 31143859Sml29623 { 31153859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 31163859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 31173859Sml29623 p_nxge_ldg_t ldgp; 31183859Sml29623 uint32_t status; 31193859Sml29623 npi_handle_t handle; 31203859Sml29623 uint8_t portn; 31213859Sml29623 p_nxge_stats_t statsp; 31223859Sml29623 npi_status_t rs = NPI_SUCCESS; 31233859Sml29623 31243859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 31253859Sml29623 nxgep = ldvp->nxgep; 31263859Sml29623 } 31273859Sml29623 31283859Sml29623 ldgp = ldvp->ldgp; 31293859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 3130*4732Sdavemq "group %d", ldgp->ldg)); 31313859Sml29623 31323859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 31333859Sml29623 /* 31343859Sml29623 * This interrupt handler is for a specific 31353859Sml29623 * mac port. 31363859Sml29623 */ 31373859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 31383859Sml29623 portn = nxgep->mac.portnum; 31393859Sml29623 31403859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 3141*4732Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 31423859Sml29623 31433859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 31443859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 31453859Sml29623 (xmac_tx_iconfig_t *)&status); 31463859Sml29623 if (rs != NPI_SUCCESS) 31473859Sml29623 goto npi_fail; 31483859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 31493859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 31503859Sml29623 statsp->xmac_stats.tx_underflow_err++; 31513859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31523859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 31533859Sml29623 } 31543859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 31553859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 31563859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31573859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 31583859Sml29623 } 31593859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 31603859Sml29623 statsp->xmac_stats.tx_overflow_err++; 31613859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31623859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 31633859Sml29623 } 31643859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 31653859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 31663859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31673859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 31683859Sml29623 } 31693859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 31703859Sml29623 statsp->xmac_stats.tx_byte_cnt += 31713859Sml29623 XTXMAC_BYTE_CNT_MASK; 31723859Sml29623 } 31733859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 31743859Sml29623 statsp->xmac_stats.tx_frame_cnt += 31753859Sml29623 XTXMAC_FRM_CNT_MASK; 31763859Sml29623 } 31773859Sml29623 } 31783859Sml29623 31793859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 31803859Sml29623 (xmac_rx_iconfig_t *)&status); 31813859Sml29623 if (rs != NPI_SUCCESS) 31823859Sml29623 goto npi_fail; 31833859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 31843859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 31853859Sml29623 statsp->xmac_stats.rx_overflow_err++; 31863859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 31873859Sml29623 statsp->xmac_stats.rx_underflow_err++; 31883859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31893859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 31903859Sml29623 } 31913859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 31923859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 31933859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 31943859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31953859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 31963859Sml29623 } 31973859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 31983859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 31993859Sml29623 MAC_LEN_ER_CNT_MASK; 32003859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32013859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 32023859Sml29623 } 32033859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 32043859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 32053859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 32063859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32073859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 32083859Sml29623 } 32093859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 32103859Sml29623 statsp->xmac_stats.rx_byte_cnt += 32113859Sml29623 XRXMAC_BT_CNT_MASK; 32123859Sml29623 } 32133859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 32143859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 32153859Sml29623 XRXMAC_HIST_CNT1_MASK; 32163859Sml29623 } 32173859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 32183859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 32193859Sml29623 XRXMAC_HIST_CNT2_MASK; 32203859Sml29623 } 32213859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 32223859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 32233859Sml29623 XRXMAC_HIST_CNT3_MASK; 32243859Sml29623 } 32253859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 32263859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 32273859Sml29623 XRXMAC_HIST_CNT4_MASK; 32283859Sml29623 } 32293859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 32303859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 32313859Sml29623 XRXMAC_HIST_CNT5_MASK; 32323859Sml29623 } 32333859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 32343859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 32353859Sml29623 XRXMAC_HIST_CNT6_MASK; 32363859Sml29623 } 32373859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 32383859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 32393859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 32403859Sml29623 } 32413859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 32423859Sml29623 statsp->xmac_stats.rx_mult_cnt += 32433859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 32443859Sml29623 } 32453859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 32463859Sml29623 statsp->xmac_stats.rx_frag_cnt += 32473859Sml29623 XRXMAC_FRAG_CNT_MASK; 32483859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32493859Sml29623 NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 32503859Sml29623 } 32513859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 32523859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 32533859Sml29623 XRXMAC_AL_ER_CNT_MASK; 32543859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32553859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 32563859Sml29623 } 32573859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 32583859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 32593859Sml29623 XMAC_LINK_FLT_CNT_MASK; 32603859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32613859Sml29623 NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 32623859Sml29623 } 32633859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 32643859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 32653859Sml29623 } 32663859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 32673859Sml29623 statsp->xmac_stats.rx_localfault_err++; 32683859Sml29623 } 32693859Sml29623 } 32703859Sml29623 32713859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 32723859Sml29623 (xmac_ctl_iconfig_t *)&status); 32733859Sml29623 if (rs != NPI_SUCCESS) 32743859Sml29623 goto npi_fail; 32753859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 32763859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 32773859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 32783859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 32793859Sml29623 statsp->xmac_stats.tx_pause_state++; 32803859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 32813859Sml29623 statsp->xmac_stats.tx_nopause_state++; 32823859Sml29623 } 32833859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 32843859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 32853859Sml29623 (bmac_tx_iconfig_t *)&status); 32863859Sml29623 if (rs != NPI_SUCCESS) 32873859Sml29623 goto npi_fail; 32883859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 32893859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 32903859Sml29623 statsp->bmac_stats.tx_underrun_err++; 32913859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32923859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 32933859Sml29623 } 32943859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 32953859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 32963859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32973859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 32983859Sml29623 } 32993859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 33003859Sml29623 statsp->bmac_stats.tx_byte_cnt += 33013859Sml29623 BTXMAC_BYTE_CNT_MASK; 33023859Sml29623 } 33033859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 33043859Sml29623 statsp->bmac_stats.tx_frame_cnt += 33053859Sml29623 BTXMAC_FRM_CNT_MASK; 33063859Sml29623 } 33073859Sml29623 } 33083859Sml29623 33093859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 33103859Sml29623 (bmac_rx_iconfig_t *)&status); 33113859Sml29623 if (rs != NPI_SUCCESS) 33123859Sml29623 goto npi_fail; 33133859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 33143859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 33153859Sml29623 statsp->bmac_stats.rx_overflow_err++; 33163859Sml29623 } 33173859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 33183859Sml29623 statsp->bmac_stats.rx_frame_cnt += 33193859Sml29623 RXMAC_FRM_CNT_MASK; 33203859Sml29623 } 33213859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 33223859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 33233859Sml29623 BMAC_CRC_ER_CNT_MASK; 33243859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33253859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 33263859Sml29623 } 33273859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 33283859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 33293859Sml29623 MAC_LEN_ER_CNT_MASK; 33303859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33313859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 33323859Sml29623 } 33333859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 33343859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 33353859Sml29623 BMAC_CD_VIO_CNT_MASK; 33363859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33373859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 33383859Sml29623 } 33393859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 33403859Sml29623 statsp->bmac_stats.rx_byte_cnt += 33413859Sml29623 BRXMAC_BYTE_CNT_MASK; 33423859Sml29623 } 33433859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 33443859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 33453859Sml29623 BMAC_AL_ER_CNT_MASK; 33463859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33473859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 33483859Sml29623 } 33493859Sml29623 33503859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 33513859Sml29623 (bmac_ctl_iconfig_t *)&status); 33523859Sml29623 if (rs != NPI_SUCCESS) 33533859Sml29623 goto npi_fail; 33543859Sml29623 33553859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 33563859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 33573859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 33583859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 33593859Sml29623 statsp->bmac_stats.tx_pause_state++; 33603859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 33613859Sml29623 statsp->bmac_stats.tx_nopause_state++; 33623859Sml29623 } 33633859Sml29623 } 33643859Sml29623 33653859Sml29623 if (ldgp->nldvs == 1) { 33663859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 33673859Sml29623 B_TRUE, ldgp->ldg_timer); 33683859Sml29623 } 33693859Sml29623 33703859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 33713859Sml29623 return (DDI_INTR_CLAIMED); 33723859Sml29623 33733859Sml29623 npi_fail: 33743859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 33753859Sml29623 return (DDI_INTR_UNCLAIMED); 33763859Sml29623 } 33773859Sml29623 33783859Sml29623 nxge_status_t 33793859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 33803859Sml29623 { 33813859Sml29623 uint8_t phy_port_addr; 33823859Sml29623 nxge_status_t status = NXGE_OK; 33833859Sml29623 boolean_t rx_sig_ok; 33843859Sml29623 boolean_t pcs_blk_lock; 33853859Sml29623 boolean_t link_align; 33863859Sml29623 uint16_t val1, val2, val3; 33873859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 33883859Sml29623 uint16_t val_debug; 33893859Sml29623 uint16_t val; 33903859Sml29623 #endif 33913859Sml29623 33923859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 33933859Sml29623 33943859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 33953859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 33963859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 33973859Sml29623 if ((val_debug & ~0x200) != 0) { 33983859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 33993859Sml29623 nxgep->mac.portnum, val_debug); 34003859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 34013859Sml29623 &val_debug); 34023859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 34033859Sml29623 nxgep->mac.portnum, val_debug); 34043859Sml29623 } 34053859Sml29623 34063859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34073859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 34083859Sml29623 if (val != 0) 34093859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 34103859Sml29623 34113859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34123859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 34133859Sml29623 if (val != 0) 34143859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 34153859Sml29623 34163859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34173859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 34183859Sml29623 if (val != 0) 34193859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 34203859Sml29623 #endif 34213859Sml29623 34223859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 34233859Sml29623 34243859Sml29623 /* Check Device 1 Register 0xA bit0 */ 34253859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 34263859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 34273859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 34283859Sml29623 &val1); 34293859Sml29623 if (status != NXGE_OK) 34303859Sml29623 goto fail; 34313859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 34323859Sml29623 34333859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 34343859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 34353859Sml29623 BCM8704_PCS_DEV_ADDR, 34363859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 34373859Sml29623 &val2)) != NPI_SUCCESS) 34383859Sml29623 goto fail; 34393859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 34403859Sml29623 34413859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 34423859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 34433859Sml29623 BCM8704_PHYXS_ADDR, 34443859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 34453859Sml29623 &val3); 34463859Sml29623 if (status != NXGE_OK) 34473859Sml29623 goto fail; 34483859Sml29623 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 34493859Sml29623 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 34503859Sml29623 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 34513859Sml29623 34523859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 34533859Sml29623 /* Temp workaround for link down issue */ 34543859Sml29623 if (pcs_blk_lock == B_FALSE) { 34553859Sml29623 if (val2 != 0x4) { 34563859Sml29623 pcs_blk_lock = B_TRUE; 34573859Sml29623 cmn_err(CE_NOTE, 34583859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 34593859Sml29623 "Reg 0x20 = 0x%x\n", 34603859Sml29623 nxgep->mac.portnum, val2); 34613859Sml29623 } 34623859Sml29623 } 34633859Sml29623 34643859Sml29623 if (link_align == B_FALSE) { 34653859Sml29623 if (val3 != 0x140f) { 34663859Sml29623 link_align = B_TRUE; 34673859Sml29623 cmn_err(CE_NOTE, 34683859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 34693859Sml29623 "Reg 0x18 = 0x%x\n", 34703859Sml29623 nxgep->mac.portnum, val3); 34713859Sml29623 } 34723859Sml29623 } 34733859Sml29623 34743859Sml29623 if (rx_sig_ok == B_FALSE) { 34753859Sml29623 if ((val2 == 0) || (val3 == 0)) { 34763859Sml29623 rx_sig_ok = B_TRUE; 34773859Sml29623 cmn_err(CE_NOTE, 34783859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 34793859Sml29623 nxgep->mac.portnum); 34803859Sml29623 } 34813859Sml29623 } 34823859Sml29623 #endif 34833859Sml29623 34843859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 34853859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 34863859Sml29623 34873859Sml29623 return (NXGE_OK); 34883859Sml29623 fail: 34893859Sml29623 return (status); 34903859Sml29623 } 34913859Sml29623 34923859Sml29623 nxge_status_t 34933859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 34943859Sml29623 { 34953859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 3496*4732Sdavemq != NPI_SUCCESS) 34973859Sml29623 return (NXGE_ERROR); 34983859Sml29623 else 34993859Sml29623 return (NXGE_OK); 35003859Sml29623 } 35013859Sml29623 35023859Sml29623 nxge_status_t 35033859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 35043859Sml29623 { 35053859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 3506*4732Sdavemq != NPI_SUCCESS) 35073859Sml29623 return (NXGE_ERROR); 35083859Sml29623 else 35093859Sml29623 return (NXGE_OK); 35103859Sml29623 } 35114185Sspeer 3512*4732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 3513*4732Sdavemq 3514*4732Sdavemq static boolean_t 3515*4732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 3516*4732Sdavemq { 3517*4732Sdavemq int i; 3518*4732Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 3519*4732Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 3520*4732Sdavemq boolean_t found = B_FALSE; 3521*4732Sdavemq 3522*4732Sdavemq switch (type) { 3523*4732Sdavemq case CLAUSE_45_TYPE: 3524*4732Sdavemq for (i = 0; i < cl45_arr_len; i++) { 3525*4732Sdavemq if ((nxge_supported_cl45_ids[i] & PHY_ID_MASK) == 3526*4732Sdavemq (id & PHY_ID_MASK)) { 3527*4732Sdavemq found = B_TRUE; 3528*4732Sdavemq break; 3529*4732Sdavemq } 3530*4732Sdavemq } 3531*4732Sdavemq break; 3532*4732Sdavemq case CLAUSE_22_TYPE: 3533*4732Sdavemq for (i = 0; i < cl22_arr_len; i++) { 3534*4732Sdavemq if ((nxge_supported_cl22_ids[i] & PHY_ID_MASK) == 3535*4732Sdavemq (id & PHY_ID_MASK)) { 3536*4732Sdavemq found = B_TRUE; 3537*4732Sdavemq break; 3538*4732Sdavemq } 3539*4732Sdavemq } 3540*4732Sdavemq break; 3541*4732Sdavemq default: 3542*4732Sdavemq break; 3543*4732Sdavemq } 3544*4732Sdavemq 3545*4732Sdavemq return (found); 3546*4732Sdavemq } 3547*4732Sdavemq 3548*4732Sdavemq /* 3549*4732Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 3550*4732Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 3551*4732Sdavemq * read. Then use the values obtained to determine the phy type of each port 3552*4732Sdavemq * and the Neptune type. 3553*4732Sdavemq */ 3554*4732Sdavemq 3555*4732Sdavemq nxge_status_t 3556*4732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 3557*4732Sdavemq { 3558*4732Sdavemq int i, j, k, l; 3559*4732Sdavemq uint16_t val1 = 0; 3560*4732Sdavemq uint16_t val2 = 0; 3561*4732Sdavemq uint32_t pma_pmd_dev_id = 0; 3562*4732Sdavemq uint32_t pcs_dev_id = 0; 3563*4732Sdavemq uint32_t phy_id = 0; 3564*4732Sdavemq uint32_t port_pma_pmd_dev_id[4]; 3565*4732Sdavemq uint32_t port_pcs_dev_id[4]; 3566*4732Sdavemq uint32_t port_phy_id[4]; 3567*4732Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 3568*4732Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 3569*4732Sdavemq uint8_t phy_fd[NXGE_MAX_PHY_PORTS]; 3570*4732Sdavemq uint8_t port_fd[NXGE_MAX_PHY_PORTS]; 3571*4732Sdavemq uint8_t total_port_fd, total_phy_fd; 3572*4732Sdavemq nxge_status_t status = NXGE_OK; 3573*4732Sdavemq npi_status_t npi_status = NPI_SUCCESS; 3574*4732Sdavemq npi_handle_t handle; 3575*4732Sdavemq int prt_id = -1; 3576*4732Sdavemq 3577*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 3578*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3579*4732Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 3580*4732Sdavemq nxgep->niu_type)); 3581*4732Sdavemq 3582*4732Sdavemq handle = NXGE_DEV_NPI_HANDLE(nxgep); 3583*4732Sdavemq j = k = l = 0; 3584*4732Sdavemq total_port_fd = total_phy_fd = 0; 3585*4732Sdavemq /* 3586*4732Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 3587*4732Sdavemq * for on chip serdes usages. 3588*4732Sdavemq */ 3589*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 3590*4732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR, 3591*4732Sdavemq NXGE_DEV_ID_REG_1, &val1); 3592*4732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR, 3593*4732Sdavemq NXGE_DEV_ID_REG_2, &val2); 3594*4732Sdavemq pma_pmd_dev_id = val1; 3595*4732Sdavemq pma_pmd_dev_id = (pma_pmd_dev_id << 16); 3596*4732Sdavemq pma_pmd_dev_id |= val2; 3597*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 3598*4732Sdavemq "devid[0x%llx]", i, pma_pmd_dev_id)); 3599*4732Sdavemq 3600*4732Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 3601*4732Sdavemq pma_pmd_dev_fd[i] = 1; 3602*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 3603*4732Sdavemq "PMA/PMD dev found", i)); 3604*4732Sdavemq if (j < 4) { 3605*4732Sdavemq port_pma_pmd_dev_id[j] = pma_pmd_dev_id; 3606*4732Sdavemq j++; 3607*4732Sdavemq } 3608*4732Sdavemq } else { 3609*4732Sdavemq pma_pmd_dev_fd[i] = 0; 3610*4732Sdavemq } 3611*4732Sdavemq 3612*4732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR, 3613*4732Sdavemq NXGE_DEV_ID_REG_1, &val1); 3614*4732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR, 3615*4732Sdavemq NXGE_DEV_ID_REG_2, &val2); 3616*4732Sdavemq pcs_dev_id = val1; 3617*4732Sdavemq pcs_dev_id = (pcs_dev_id << 16); 3618*4732Sdavemq pcs_dev_id |= val2; 3619*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 3620*4732Sdavemq "devid[0x%llx]", i, pcs_dev_id)); 3621*4732Sdavemq 3622*4732Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 3623*4732Sdavemq pcs_dev_fd[i] = 1; 3624*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 3625*4732Sdavemq "dev found", i)); 3626*4732Sdavemq if (k < 4) { 3627*4732Sdavemq port_pcs_dev_id[k] = pcs_dev_id; 3628*4732Sdavemq k++; 3629*4732Sdavemq } 3630*4732Sdavemq } else { 3631*4732Sdavemq pcs_dev_fd[i] = 0; 3632*4732Sdavemq } 3633*4732Sdavemq 3634*4732Sdavemq if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) 3635*4732Sdavemq port_fd[i] = 1; 3636*4732Sdavemq else 3637*4732Sdavemq port_fd[i] = 0; 3638*4732Sdavemq total_port_fd += port_fd[i]; 3639*4732Sdavemq 3640*4732Sdavemq npi_status = npi_mac_mif_mii_read(handle, i, 3641*4732Sdavemq NXGE_PHY_ID_REG_1, &val1); 3642*4732Sdavemq if (npi_status != NPI_SUCCESS) { 3643*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 3644*4732Sdavemq "clause 22 read to reg 2 failed!!!")); 3645*4732Sdavemq goto error_exit; 3646*4732Sdavemq } 3647*4732Sdavemq npi_status = npi_mac_mif_mii_read(handle, i, 3648*4732Sdavemq NXGE_PHY_ID_REG_2, &val2); 3649*4732Sdavemq if (npi_status != 0) { 3650*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 3651*4732Sdavemq "clause 22 read to reg 3 failed!!!")); 3652*4732Sdavemq goto error_exit; 3653*4732Sdavemq } 3654*4732Sdavemq phy_id = val1; 3655*4732Sdavemq phy_id = (phy_id << 16); 3656*4732Sdavemq phy_id |= val2; 3657*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 3658*4732Sdavemq "[0x%llx]", i, phy_id)); 3659*4732Sdavemq 3660*4732Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 3661*4732Sdavemq phy_fd[i] = 1; 3662*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 3663*4732Sdavemq "found", i)); 3664*4732Sdavemq if (l < 4) { 3665*4732Sdavemq port_phy_id[l] = phy_id; 3666*4732Sdavemq l++; 3667*4732Sdavemq } 3668*4732Sdavemq } else { 3669*4732Sdavemq phy_fd[i] = 0; 3670*4732Sdavemq } 3671*4732Sdavemq total_phy_fd += phy_fd[i]; 3672*4732Sdavemq } 3673*4732Sdavemq 3674*4732Sdavemq switch (total_port_fd) { 3675*4732Sdavemq case 2: 3676*4732Sdavemq switch (total_phy_fd) { 3677*4732Sdavemq case 2: 3678*4732Sdavemq /* 2 10G, 2 1G */ 3679*4732Sdavemq if (((port_pcs_dev_id[0] == PHY_10G_FIBRE && 3680*4732Sdavemq port_pcs_dev_id[1] == PHY_10G_FIBRE) || 3681*4732Sdavemq (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE && 3682*4732Sdavemq port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) && 3683*4732Sdavemq (port_phy_id[0] == PHY_1G_COPPER && 3684*4732Sdavemq port_phy_id[1] == PHY_1G_COPPER)) { 3685*4732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 3686*4732Sdavemq } else { 3687*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3688*4732Sdavemq "Unsupported neptune type 1")); 3689*4732Sdavemq goto error_exit; 3690*4732Sdavemq } 3691*4732Sdavemq break; 3692*4732Sdavemq case 1: 3693*4732Sdavemq /* TODO - 2 10G, 1 1G */ 3694*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3695*4732Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 3696*4732Sdavemq goto error_exit; 3697*4732Sdavemq case 0: 3698*4732Sdavemq /* 2 10G */ 3699*4732Sdavemq if ((port_pcs_dev_id[0] == PHY_10G_FIBRE && 3700*4732Sdavemq port_pcs_dev_id[1] == PHY_10G_FIBRE) || 3701*4732Sdavemq (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE && 3702*4732Sdavemq port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) { 3703*4732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF; 3704*4732Sdavemq } else { 3705*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3706*4732Sdavemq "Unsupported neptune type 2")); 3707*4732Sdavemq goto error_exit; 3708*4732Sdavemq } 3709*4732Sdavemq break; 3710*4732Sdavemq case 4: 3711*4732Sdavemq /* Maramba with 2 XAUI */ 3712*4732Sdavemq if (((port_pcs_dev_id[0] == PHY_10G_FIBRE && 3713*4732Sdavemq port_pcs_dev_id[1] == PHY_10G_FIBRE) || 3714*4732Sdavemq (port_pma_pmd_dev_id[0] == PHY_10G_FIBRE && 3715*4732Sdavemq port_pma_pmd_dev_id[1] == PHY_10G_FIBRE)) && 3716*4732Sdavemq (port_phy_id[0] == PHY_1G_COPPER && 3717*4732Sdavemq port_phy_id[1] == PHY_1G_COPPER && 3718*4732Sdavemq port_phy_id[2] == PHY_1G_COPPER && 3719*4732Sdavemq port_phy_id[3] == PHY_1G_COPPER)) { 3720*4732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 3721*4732Sdavemq 3722*4732Sdavemq /* 3723*4732Sdavemq * Check the first phy port address against 3724*4732Sdavemq * the known phy start addresses to determine 3725*4732Sdavemq * the platform type. 3726*4732Sdavemq */ 3727*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 3728*4732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 3729*4732Sdavemq if (phy_fd[i] == 1) 3730*4732Sdavemq break; 3731*4732Sdavemq } 3732*4732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 3733*4732Sdavemq hw_p->platform_type = 3734*4732Sdavemq P_NEPTUNE_MARAMBA_P0; 3735*4732Sdavemq } else if (i == 3736*4732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 3737*4732Sdavemq hw_p->platform_type = 3738*4732Sdavemq P_NEPTUNE_MARAMBA_P1; 3739*4732Sdavemq } else { 3740*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3741*4732Sdavemq "Unknown port %d...Cannot " 3742*4732Sdavemq "determine platform type", i)); 3743*4732Sdavemq } 3744*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3745*4732Sdavemq "Maramba with 2 XAUI")); 3746*4732Sdavemq } else { 3747*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3748*4732Sdavemq "Unsupported neptune type 3")); 3749*4732Sdavemq goto error_exit; 3750*4732Sdavemq } 3751*4732Sdavemq break; 3752*4732Sdavemq default: 3753*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3754*4732Sdavemq "Unsupported neptune type 5")); 3755*4732Sdavemq goto error_exit; 3756*4732Sdavemq } 3757*4732Sdavemq case 1: 3758*4732Sdavemq switch (total_phy_fd) { 3759*4732Sdavemq case 3: 3760*4732Sdavemq if (((port_pcs_dev_id[0] & PHY_ID_MASK) == 3761*4732Sdavemq (BCM8704_DEV_ID & PHY_ID_MASK)) || 3762*4732Sdavemq ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) == 3763*4732Sdavemq (BCM8704_DEV_ID & PHY_ID_MASK))) { 3764*4732Sdavemq /* The 10G port is BCM8704 */ 3765*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 3766*4732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 3767*4732Sdavemq if (port_fd[i] == 1) { 3768*4732Sdavemq prt_id = i; 3769*4732Sdavemq break; 3770*4732Sdavemq } 3771*4732Sdavemq } 3772*4732Sdavemq 3773*4732Sdavemq if (nxgep->niu_type == N2_NIU) 3774*4732Sdavemq prt_id %= BCM8704_N2_PORT_ADDR_BASE; 3775*4732Sdavemq else 3776*4732Sdavemq prt_id %= 3777*4732Sdavemq BCM8704_NEPTUNE_PORT_ADDR_BASE; 3778*4732Sdavemq 3779*4732Sdavemq if (prt_id == 0) { 3780*4732Sdavemq hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 3781*4732Sdavemq } else if (prt_id == 1) { 3782*4732Sdavemq hw_p->niu_type = 3783*4732Sdavemq NEPTUNE_1_1GC_1_10GF_2_1GC; 3784*4732Sdavemq } else { 3785*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3786*4732Sdavemq "Unsupported neptune type 6")); 3787*4732Sdavemq goto error_exit; 3788*4732Sdavemq } 3789*4732Sdavemq } else { 3790*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3791*4732Sdavemq "Unsupported neptune type 7")); 3792*4732Sdavemq goto error_exit; 3793*4732Sdavemq } 3794*4732Sdavemq break; 3795*4732Sdavemq case 2: 3796*4732Sdavemq /* 3797*4732Sdavemq * TODO 2 1G, 1 10G mode. 3798*4732Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 3799*4732Sdavemq * 1_10G_2_1G 3800*4732Sdavemq */ 3801*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3802*4732Sdavemq "Unsupported neptune type 8")); 3803*4732Sdavemq goto error_exit; 3804*4732Sdavemq case 1: 3805*4732Sdavemq /* 3806*4732Sdavemq * TODO 1 1G, 1 10G mode. 3807*4732Sdavemq * Differentiate between 1_1G_1_10G and 3808*4732Sdavemq * 1_10G_1_1G 3809*4732Sdavemq */ 3810*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3811*4732Sdavemq "Unsupported neptune type 9")); 3812*4732Sdavemq goto error_exit; 3813*4732Sdavemq case 0: 3814*4732Sdavemq /* TODO 1 10G mode */ 3815*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3816*4732Sdavemq "Unsupported neptune type 10")); 3817*4732Sdavemq goto error_exit; 3818*4732Sdavemq case 4: 3819*4732Sdavemq /* Maramba with 1 XAUI */ 3820*4732Sdavemq if (((port_pcs_dev_id[0] & PHY_ID_MASK) == 3821*4732Sdavemq (BCM8704_DEV_ID & PHY_ID_MASK)) || 3822*4732Sdavemq ((port_pma_pmd_dev_id[0] & PHY_ID_MASK) == 3823*4732Sdavemq (BCM8704_DEV_ID & PHY_ID_MASK))) { 3824*4732Sdavemq /* The 10G port is BCM8704 */ 3825*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 3826*4732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 3827*4732Sdavemq if (port_fd[i] == 1) { 3828*4732Sdavemq prt_id = i; 3829*4732Sdavemq break; 3830*4732Sdavemq } 3831*4732Sdavemq } 3832*4732Sdavemq 3833*4732Sdavemq prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE; 3834*4732Sdavemq if (prt_id == 0) { 3835*4732Sdavemq hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 3836*4732Sdavemq } else if (prt_id == 1) { 3837*4732Sdavemq hw_p->niu_type = 3838*4732Sdavemq NEPTUNE_1_1GC_1_10GF_2_1GC; 3839*4732Sdavemq } else { 3840*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3841*4732Sdavemq "Unsupported neptune type 11")); 3842*4732Sdavemq goto error_exit; 3843*4732Sdavemq } 3844*4732Sdavemq 3845*4732Sdavemq /* 3846*4732Sdavemq * Check the first phy port address against 3847*4732Sdavemq * the known phy start addresses to determine 3848*4732Sdavemq * the platform type. 3849*4732Sdavemq */ 3850*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 3851*4732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 3852*4732Sdavemq if (phy_fd[i] == 1) 3853*4732Sdavemq break; 3854*4732Sdavemq } 3855*4732Sdavemq 3856*4732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 3857*4732Sdavemq hw_p->platform_type = 3858*4732Sdavemq P_NEPTUNE_MARAMBA_P0; 3859*4732Sdavemq } else if (i == 3860*4732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 3861*4732Sdavemq hw_p->platform_type = 3862*4732Sdavemq P_NEPTUNE_MARAMBA_P1; 3863*4732Sdavemq } else { 3864*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3865*4732Sdavemq "Unknown port %d...Cannot " 3866*4732Sdavemq "determine platform type", i)); 3867*4732Sdavemq } 3868*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3869*4732Sdavemq "Maramba with 1 XAUI")); 3870*4732Sdavemq } else { 3871*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3872*4732Sdavemq "Unsupported neptune type 12")); 3873*4732Sdavemq goto error_exit; 3874*4732Sdavemq } 3875*4732Sdavemq break; 3876*4732Sdavemq default: 3877*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3878*4732Sdavemq "Unsupported neptune type 13")); 3879*4732Sdavemq goto error_exit; 3880*4732Sdavemq } 3881*4732Sdavemq break; 3882*4732Sdavemq case 0: 3883*4732Sdavemq switch (total_phy_fd) { 3884*4732Sdavemq case 4: 3885*4732Sdavemq if (((port_phy_id[0] & PHY_ID_MASK) == 3886*4732Sdavemq (BCM5464R_PHY_ID & PHY_ID_MASK)) && 3887*4732Sdavemq ((port_phy_id[1] & PHY_ID_MASK) == 3888*4732Sdavemq (BCM5464R_PHY_ID & PHY_ID_MASK)) && 3889*4732Sdavemq ((port_phy_id[2] & PHY_ID_MASK) == 3890*4732Sdavemq (BCM5464R_PHY_ID & PHY_ID_MASK)) && 3891*4732Sdavemq ((port_phy_id[3] & PHY_ID_MASK) == 3892*4732Sdavemq (BCM5464R_PHY_ID & PHY_ID_MASK))) { 3893*4732Sdavemq 3894*4732Sdavemq hw_p->niu_type = NEPTUNE_4_1GC; 3895*4732Sdavemq 3896*4732Sdavemq /* 3897*4732Sdavemq * Check the first phy port address against 3898*4732Sdavemq * the known phy start addresses to determine 3899*4732Sdavemq * the platform type. 3900*4732Sdavemq */ 3901*4732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 3902*4732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 3903*4732Sdavemq if (phy_fd[i] == 1) 3904*4732Sdavemq break; 3905*4732Sdavemq } 3906*4732Sdavemq 3907*4732Sdavemq if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 3908*4732Sdavemq hw_p->platform_type = 3909*4732Sdavemq P_NEPTUNE_MARAMBA_P1; 3910*4732Sdavemq } 3911*4732Sdavemq } else { 3912*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3913*4732Sdavemq "Unsupported neptune type 14")); 3914*4732Sdavemq goto error_exit; 3915*4732Sdavemq } 3916*4732Sdavemq break; 3917*4732Sdavemq case 3: 3918*4732Sdavemq /* TODO 3 1G mode */ 3919*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3920*4732Sdavemq "Unsupported neptune type 15")); 3921*4732Sdavemq goto error_exit; 3922*4732Sdavemq case 2: 3923*4732Sdavemq /* TODO 2 1G mode */ 3924*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3925*4732Sdavemq "Unsupported neptune type 16")); 3926*4732Sdavemq goto error_exit; 3927*4732Sdavemq case 1: 3928*4732Sdavemq /* TODO 1 1G mode */ 3929*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3930*4732Sdavemq "Unsupported neptune type 17")); 3931*4732Sdavemq goto error_exit; 3932*4732Sdavemq default: 3933*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3934*4732Sdavemq "Unsupported neptune type 18, total phy fd %d", 3935*4732Sdavemq total_phy_fd)); 3936*4732Sdavemq goto error_exit; 3937*4732Sdavemq } 3938*4732Sdavemq break; 3939*4732Sdavemq default: 3940*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3941*4732Sdavemq "Unsupported neptune type 19")); 3942*4732Sdavemq goto error_exit; 3943*4732Sdavemq } 3944*4732Sdavemq 3945*4732Sdavemq scan_exit: 3946*4732Sdavemq 3947*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 3948*4732Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 3949*4732Sdavemq return (status); 3950*4732Sdavemq 3951*4732Sdavemq error_exit: 3952*4732Sdavemq return (NXGE_ERROR); 3953*4732Sdavemq } 3954*4732Sdavemq 39554185Sspeer boolean_t 39564185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 39574185Sspeer { 39584185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 39594185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 39604185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 39614185Sspeer return (B_FALSE); 39624185Sspeer else 39634185Sspeer return (B_TRUE); 39644185Sspeer } 3965*4732Sdavemq 3966*4732Sdavemq static void 3967*4732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 3968*4732Sdavemq 3969*4732Sdavemq npi_status_t rs = NPI_SUCCESS; 3970*4732Sdavemq uint8_t xcvr_portn; 3971*4732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3972*4732Sdavemq 3973*4732Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 3974*4732Sdavemq 3975*4732Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 3976*4732Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 3977*4732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 3978*4732Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 3979*4732Sdavemq } 3980*4732Sdavemq /* 3981*4732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 3982*4732Sdavemq * swapped with ethernet port number. This is 3983*4732Sdavemq * designed for better signal integrity in routing. 3984*4732Sdavemq */ 3985*4732Sdavemq switch (portn) { 3986*4732Sdavemq case 0: 3987*4732Sdavemq xcvr_portn += 3; 3988*4732Sdavemq break; 3989*4732Sdavemq case 1: 3990*4732Sdavemq xcvr_portn += 2; 3991*4732Sdavemq break; 3992*4732Sdavemq case 2: 3993*4732Sdavemq xcvr_portn += 1; 3994*4732Sdavemq break; 3995*4732Sdavemq case 3: 3996*4732Sdavemq default: 3997*4732Sdavemq break; 3998*4732Sdavemq } 3999*4732Sdavemq 4000*4732Sdavemq MUTEX_ENTER(&nxge_mii_lock); 4001*4732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 4002*4732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 4003*4732Sdavemq if (rs != NPI_SUCCESS) { 4004*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4005*4732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 4006*4732Sdavemq "returned error 0x[%x]", rs)); 4007*4732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 4008*4732Sdavemq return; 4009*4732Sdavemq } 4010*4732Sdavemq 4011*4732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 4012*4732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 4013*4732Sdavemq if (rs != NPI_SUCCESS) { 4014*4732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4015*4732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 4016*4732Sdavemq "returned error 0x[%x]", rs)); 4017*4732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 4018*4732Sdavemq return; 4019*4732Sdavemq } 4020*4732Sdavemq 4021*4732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 4022*4732Sdavemq } 4023