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 313859Sml29623 extern uint32_t nxge_no_link_notify; 32*4185Sspeer extern boolean_t nxge_no_msg; 333859Sml29623 extern uint32_t nxge_lb_dbg; 343859Sml29623 extern nxge_os_mutex_t nxge_mdio_lock; 353859Sml29623 extern nxge_os_mutex_t nxge_mii_lock; 363859Sml29623 extern boolean_t nxge_jumbo_enable; 373859Sml29623 383859Sml29623 /* 393859Sml29623 * Ethernet broadcast address definition. 403859Sml29623 */ 413859Sml29623 static ether_addr_st etherbroadcastaddr = 423859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 43*4185Sspeer static ether_addr_st etherzeroaddr = 44*4185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 453859Sml29623 463859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 473859Sml29623 483859Sml29623 /* Initialize the entire MAC and physical layer */ 493859Sml29623 503859Sml29623 nxge_status_t 513859Sml29623 nxge_mac_init(p_nxge_t nxgep) 523859Sml29623 { 533859Sml29623 uint8_t portn; 543859Sml29623 nxge_status_t status = NXGE_OK; 553859Sml29623 563859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 573859Sml29623 583859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 593859Sml29623 603859Sml29623 nxgep->mac.portnum = portn; 613859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 623859Sml29623 633859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 643859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 653859Sml29623 663859Sml29623 /* Initialize XIF to configure a network mode */ 673859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 683859Sml29623 goto fail; 693859Sml29623 } 703859Sml29623 713859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 723859Sml29623 goto fail; 733859Sml29623 } 743859Sml29623 753859Sml29623 /* Initialize TX and RX MACs */ 763859Sml29623 /* 773859Sml29623 * Always perform XIF init first, before TX and RX MAC init 783859Sml29623 */ 793859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 803859Sml29623 goto fail; 813859Sml29623 823859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 833859Sml29623 goto fail; 843859Sml29623 853859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 863859Sml29623 goto fail; 873859Sml29623 883859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 893859Sml29623 goto fail; 903859Sml29623 913859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 923859Sml29623 goto fail; 933859Sml29623 943859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 953859Sml29623 goto fail; 963859Sml29623 973859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 983859Sml29623 993859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 1003859Sml29623 1013859Sml29623 return (NXGE_OK); 1023859Sml29623 fail: 1033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1043859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 1053859Sml29623 portn)); 1063859Sml29623 return (status); 1073859Sml29623 } 1083859Sml29623 1093859Sml29623 /* Initialize the Ethernet Link */ 1103859Sml29623 1113859Sml29623 nxge_status_t 1123859Sml29623 nxge_link_init(p_nxge_t nxgep) 1133859Sml29623 { 1143859Sml29623 nxge_status_t status = NXGE_OK; 1153859Sml29623 #ifdef NXGE_DEBUG 1163859Sml29623 uint8_t portn; 1173859Sml29623 1183859Sml29623 portn = nxgep->mac.portnum; 1193859Sml29623 1203859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 1213859Sml29623 #endif 1223859Sml29623 1233859Sml29623 if (nxgep->niu_type == N2_NIU) { 1243859Sml29623 /* Workaround to get link up in both NIU ports */ 1253859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 1263859Sml29623 goto fail; 1273859Sml29623 } 1283859Sml29623 NXGE_DELAY(200000); 1293859Sml29623 /* Initialize internal serdes */ 1303859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 1313859Sml29623 goto fail; 1323859Sml29623 NXGE_DELAY(200000); 1333859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 1343859Sml29623 goto fail; 1353859Sml29623 1363859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 1373859Sml29623 1383859Sml29623 return (NXGE_OK); 1393859Sml29623 1403859Sml29623 fail: 1413859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1423859Sml29623 "nxge_link_init: ", 1433859Sml29623 "failed to initialize Ethernet link on port<%d>", 1443859Sml29623 portn)); 1453859Sml29623 1463859Sml29623 return (status); 1473859Sml29623 } 1483859Sml29623 1493859Sml29623 1503859Sml29623 /* Initialize the XIF sub-block within the MAC */ 1513859Sml29623 1523859Sml29623 nxge_status_t 1533859Sml29623 nxge_xif_init(p_nxge_t nxgep) 1543859Sml29623 { 1553859Sml29623 uint32_t xif_cfg = 0; 1563859Sml29623 npi_attr_t ap; 1573859Sml29623 uint8_t portn; 1583859Sml29623 nxge_port_t portt; 1593859Sml29623 nxge_port_mode_t portmode; 1603859Sml29623 p_nxge_stats_t statsp; 1613859Sml29623 npi_status_t rs = NPI_SUCCESS; 1623859Sml29623 npi_handle_t handle; 1633859Sml29623 1643859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1653859Sml29623 1663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 1673859Sml29623 1683859Sml29623 handle = nxgep->npi_handle; 1693859Sml29623 portmode = nxgep->mac.portmode; 1703859Sml29623 portt = nxgep->mac.porttype; 1713859Sml29623 statsp = nxgep->statsp; 1723859Sml29623 1733859Sml29623 if (portt == PORT_TYPE_XMAC) { 1743859Sml29623 1753859Sml29623 /* Setup XIF Configuration for XMAC */ 1763859Sml29623 1773859Sml29623 if ((portmode == PORT_10G_FIBER) || 1783859Sml29623 (portmode == PORT_10G_COPPER)) 1793859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 1803859Sml29623 1813859Sml29623 if (portmode == PORT_1G_COPPER) { 1823859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 1833859Sml29623 } 1843859Sml29623 1853859Sml29623 /* Set MAC Internal Loopback if necessary */ 1863859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 1873859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 1883859Sml29623 1893859Sml29623 if (statsp->mac_stats.link_speed == 100) 1903859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 1913859Sml29623 1923859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 1933859Sml29623 1943859Sml29623 if (portmode == PORT_10G_FIBER) { 1953859Sml29623 if (statsp->mac_stats.link_up) { 1963859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 1973859Sml29623 } else { 1983859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 1993859Sml29623 } 2003859Sml29623 } 2013859Sml29623 2023859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 2033859Sml29623 if (rs != NPI_SUCCESS) 2043859Sml29623 goto fail; 2053859Sml29623 2063859Sml29623 nxgep->mac.xif_config = xif_cfg; 2073859Sml29623 2083859Sml29623 /* Set Port Mode */ 2093859Sml29623 if ((portmode == PORT_10G_FIBER) || 2103859Sml29623 (portmode == PORT_10G_COPPER)) { 2113859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 2123859Sml29623 MAC_XGMII_MODE, rs); 2133859Sml29623 if (rs != NPI_SUCCESS) 2143859Sml29623 goto fail; 2153859Sml29623 if (statsp->mac_stats.link_up) { 2163859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 2173859Sml29623 goto fail; 2183859Sml29623 } else { 2193859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 2203859Sml29623 goto fail; 2213859Sml29623 } 2223859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 2233859Sml29623 (portmode == PORT_1G_COPPER)) { 2243859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 2253859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 2263859Sml29623 MAC_GMII_MODE, rs); 2273859Sml29623 } else { 2283859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 2293859Sml29623 MAC_MII_MODE, rs); 2303859Sml29623 } 2313859Sml29623 if (rs != NPI_SUCCESS) 2323859Sml29623 goto fail; 2333859Sml29623 } else { 2343859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2353859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 2363859Sml29623 " for port<%d>", portmode, portn)); 2373859Sml29623 goto fail; 2383859Sml29623 } 2393859Sml29623 2403859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 2413859Sml29623 2423859Sml29623 /* Setup XIF Configuration for BMAC */ 2433859Sml29623 2443859Sml29623 if (portmode == PORT_1G_COPPER) { 2453859Sml29623 if (statsp->mac_stats.link_speed == 100) 2463859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 2473859Sml29623 } 2483859Sml29623 2493859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 2503859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 2513859Sml29623 2523859Sml29623 if (statsp->mac_stats.link_speed == 1000) 2533859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 2543859Sml29623 2553859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 2563859Sml29623 2573859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 2583859Sml29623 if (rs != NPI_SUCCESS) 2593859Sml29623 goto fail; 2603859Sml29623 nxgep->mac.xif_config = xif_cfg; 2613859Sml29623 } 2623859Sml29623 2633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 2643859Sml29623 return (NXGE_OK); 2653859Sml29623 fail: 2663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2673859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 2683859Sml29623 portn)); 2693859Sml29623 return (NXGE_ERROR | rs); 2703859Sml29623 } 2713859Sml29623 2723859Sml29623 /* Initialize the PCS sub-block in the MAC */ 2733859Sml29623 2743859Sml29623 nxge_status_t 2753859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 2763859Sml29623 { 2773859Sml29623 pcs_cfg_t pcs_cfg; 2783859Sml29623 uint32_t val; 2793859Sml29623 uint8_t portn; 2803859Sml29623 nxge_port_mode_t portmode; 2813859Sml29623 npi_handle_t handle; 2823859Sml29623 p_nxge_stats_t statsp; 2833859Sml29623 npi_status_t rs = NPI_SUCCESS; 2843859Sml29623 2853859Sml29623 handle = nxgep->npi_handle; 2863859Sml29623 portmode = nxgep->mac.portmode; 2873859Sml29623 portn = nxgep->mac.portnum; 2883859Sml29623 statsp = nxgep->statsp; 2893859Sml29623 2903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 2913859Sml29623 2923859Sml29623 if (portmode == PORT_1G_FIBER) { 2933859Sml29623 /* Initialize port's PCS */ 2943859Sml29623 pcs_cfg.value = 0; 2953859Sml29623 pcs_cfg.bits.w0.enable = 1; 2963859Sml29623 pcs_cfg.bits.w0.mask = 1; 2973859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 2983859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 2993859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 3003859Sml29623 goto fail; 3013859Sml29623 3023859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 3033859Sml29623 (portmode == PORT_10G_COPPER)) { 3043859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 3053859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 3063859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 3073859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 3083859Sml29623 3093859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 3103859Sml29623 goto fail; 3113859Sml29623 3123859Sml29623 /* Set XPCS Internal Loopback if necessary */ 3133859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 3143859Sml29623 XPCS_REG_CONTROL1, &val)) 3153859Sml29623 != NPI_SUCCESS) 3163859Sml29623 goto fail; 3173859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 3183859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 3193859Sml29623 val |= XPCS_CTRL1_LOOPBK; 3203859Sml29623 else 3213859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 3223859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 3233859Sml29623 XPCS_REG_CONTROL1, val)) 3243859Sml29623 != NPI_SUCCESS) 3253859Sml29623 goto fail; 3263859Sml29623 3273859Sml29623 /* Clear descw errors */ 3283859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 3293859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 3303859Sml29623 != NPI_SUCCESS) 3313859Sml29623 goto fail; 3323859Sml29623 /* Clear symbol errors */ 3333859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 3343859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 3353859Sml29623 != NPI_SUCCESS) 3363859Sml29623 goto fail; 3373859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 3383859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 3393859Sml29623 != NPI_SUCCESS) 3403859Sml29623 goto fail; 3413859Sml29623 3423859Sml29623 } else if (portmode == PORT_1G_COPPER) { 3433859Sml29623 if (portn < 4) { 3443859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 3453859Sml29623 PCS_DATAPATH_MODE_MII); 3463859Sml29623 } 3473859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 3483859Sml29623 goto fail; 3493859Sml29623 3503859Sml29623 } else { 3513859Sml29623 goto fail; 3523859Sml29623 } 3533859Sml29623 pass: 3543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 3553859Sml29623 return (NXGE_OK); 3563859Sml29623 fail: 3573859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3583859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 3593859Sml29623 portn)); 3603859Sml29623 return (NXGE_ERROR | rs); 3613859Sml29623 } 3623859Sml29623 3633859Sml29623 /* Initialize the Internal Serdes */ 3643859Sml29623 3653859Sml29623 nxge_status_t 3663859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 3673859Sml29623 { 3683859Sml29623 p_nxge_stats_t statsp; 3693859Sml29623 #ifdef NXGE_DEBUG 3703859Sml29623 uint8_t portn; 3713859Sml29623 #endif 3723859Sml29623 nxge_status_t status = NXGE_OK; 3733859Sml29623 3743859Sml29623 #ifdef NXGE_DEBUG 3753859Sml29623 portn = nxgep->mac.portnum; 3763859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3773859Sml29623 "==> nxge_serdes_init port<%d>", portn)); 3783859Sml29623 #endif 3793859Sml29623 3803859Sml29623 statsp = nxgep->statsp; 3813859Sml29623 3823859Sml29623 if (nxgep->niu_type == N2_NIU) { 3833859Sml29623 if (nxge_n2_serdes_init(nxgep) != NXGE_OK) 3843859Sml29623 goto fail; 3853859Sml29623 } else if ((nxgep->niu_type == NEPTUNE) || 3863859Sml29623 (nxgep->niu_type == NEPTUNE_2)) { 3873859Sml29623 if ((status = nxge_neptune_serdes_init(nxgep)) 3883859Sml29623 != NXGE_OK) 3893859Sml29623 goto fail; 3903859Sml29623 } else { 3913859Sml29623 goto fail; 3923859Sml29623 } 3933859Sml29623 3943859Sml29623 statsp->mac_stats.serdes_inits++; 3953859Sml29623 3963859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 3973859Sml29623 portn)); 3983859Sml29623 3993859Sml29623 return (NXGE_OK); 4003859Sml29623 4013859Sml29623 fail: 4023859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4033859Sml29623 "nxge_serdes_init: Failed to initialize serdes for port<%d>", 4043859Sml29623 portn)); 4053859Sml29623 4063859Sml29623 return (status); 4073859Sml29623 } 4083859Sml29623 4093859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 4103859Sml29623 4113859Sml29623 nxge_status_t 4123859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 4133859Sml29623 { 4143859Sml29623 uint8_t portn; 4153859Sml29623 int chan; 4163859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 4173859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 4183859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 4193859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 4203859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 4213859Sml29623 esr_ti_testcfg_t test_cfg; 4223859Sml29623 nxge_status_t status = NXGE_OK; 4233859Sml29623 4243859Sml29623 portn = nxgep->mac.portnum; 4253859Sml29623 4263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 4273859Sml29623 portn)); 4283859Sml29623 4293859Sml29623 tx_cfg_l.value = 0; 4303859Sml29623 tx_cfg_h.value = 0; 4313859Sml29623 rx_cfg_l.value = 0; 4323859Sml29623 rx_cfg_h.value = 0; 4333859Sml29623 pll_cfg_l.value = 0; 4343859Sml29623 test_cfg.value = 0; 4353859Sml29623 4363859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 4373859Sml29623 /* 0x0E01 */ 4383859Sml29623 tx_cfg_l.bits.entx = 1; 4393859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 4403859Sml29623 4413859Sml29623 /* 0x9101 */ 4423859Sml29623 rx_cfg_l.bits.enrx = 1; 4433859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 4443859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 4453859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 4463859Sml29623 4473859Sml29623 /* 0x0008 */ 4483859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 4493859Sml29623 4503859Sml29623 /* Set loopback mode if necessary */ 4513859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 4523859Sml29623 tx_cfg_l.bits.entest = 1; 4533859Sml29623 rx_cfg_l.bits.entest = 1; 4543859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 4553859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 4563859Sml29623 ESR_N2_DEV_ADDR, 4573859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 4583859Sml29623 != NXGE_OK) 4593859Sml29623 goto fail; 4603859Sml29623 } 4613859Sml29623 4623859Sml29623 /* Use default PLL value */ 4633859Sml29623 4643859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 4653859Sml29623 4663859Sml29623 /* 0x0E21 */ 4673859Sml29623 tx_cfg_l.bits.entx = 1; 4683859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 4693859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 4703859Sml29623 4713859Sml29623 /* 0x9121 */ 4723859Sml29623 rx_cfg_l.bits.enrx = 1; 4733859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 4743859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 4753859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 4763859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 4773859Sml29623 4783859Sml29623 /* 0x8 */ 4793859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 4803859Sml29623 4813859Sml29623 /* MPY = 0x100 */ 4823859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 4833859Sml29623 4843859Sml29623 /* Set PLL */ 4853859Sml29623 pll_cfg_l.bits.enpll = 1; 4863859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 4873859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 4883859Sml29623 != NXGE_OK) 4893859Sml29623 goto fail; 4903859Sml29623 } else { 4913859Sml29623 goto fail; 4923859Sml29623 } 4933859Sml29623 4943859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 4953859Sml29623 4963859Sml29623 NXGE_DELAY(20); 4973859Sml29623 4983859Sml29623 /* init TX channels */ 4993859Sml29623 for (chan = 0; chan < 4; chan++) { 5003859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 5013859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 5023859Sml29623 != NXGE_OK) 5033859Sml29623 goto fail; 5043859Sml29623 5053859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 5063859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 5073859Sml29623 != NXGE_OK) 5083859Sml29623 goto fail; 5093859Sml29623 } 5103859Sml29623 5113859Sml29623 /* init RX channels */ 5123859Sml29623 for (chan = 0; chan < 4; chan++) { 5133859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 5143859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 5153859Sml29623 != NXGE_OK) 5163859Sml29623 goto fail; 5173859Sml29623 5183859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 5193859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 5203859Sml29623 != NXGE_OK) 5213859Sml29623 goto fail; 5223859Sml29623 } 5233859Sml29623 5243859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 5253859Sml29623 portn)); 5263859Sml29623 5273859Sml29623 return (NXGE_OK); 5283859Sml29623 fail: 5293859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5303859Sml29623 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 5313859Sml29623 portn)); 5323859Sml29623 5333859Sml29623 return (status); 5343859Sml29623 } 5353859Sml29623 5363859Sml29623 /* Initialize Neptune Internal Serdes (Neptune only) */ 5373859Sml29623 5383859Sml29623 nxge_status_t 5393859Sml29623 nxge_neptune_serdes_init(p_nxge_t nxgep) 5403859Sml29623 { 5413859Sml29623 npi_handle_t handle; 5423859Sml29623 uint8_t portn; 5433859Sml29623 nxge_port_mode_t portmode; 5443859Sml29623 int chan; 5453859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 5463859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 5473859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 5483859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 5493859Sml29623 uint64_t val; 5503859Sml29623 uint16_t val16l; 5513859Sml29623 uint16_t val16h; 5523859Sml29623 nxge_status_t status = NXGE_OK; 5533859Sml29623 5543859Sml29623 portn = nxgep->mac.portnum; 5553859Sml29623 5563859Sml29623 if ((portn != 0) && (portn != 1)) 5573859Sml29623 return (NXGE_OK); 5583859Sml29623 5593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>", 5603859Sml29623 portn)); 5613859Sml29623 5623859Sml29623 handle = nxgep->npi_handle; 5633859Sml29623 portmode = nxgep->mac.portmode; 5643859Sml29623 5653859Sml29623 if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) { 5663859Sml29623 5673859Sml29623 switch (portn) { 5683859Sml29623 case 0: 5693859Sml29623 ESR_REG_WR(handle, ESR_0_CONTROL_REG, 5703859Sml29623 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 5713859Sml29623 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 5723859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 5733859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 5743859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 5753859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 5763859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 5773859Sml29623 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 5783859Sml29623 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 5793859Sml29623 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 5803859Sml29623 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 5813859Sml29623 5823859Sml29623 /* Set Serdes0 Internal Loopback if necessary */ 5833859Sml29623 if (nxgep->statsp->port_stats.lb_mode == 5843859Sml29623 nxge_lb_serdes10g) { 5853859Sml29623 ESR_REG_WR(handle, 5863859Sml29623 ESR_0_TEST_CONFIG_REG, 5873859Sml29623 ESR_PAD_LOOPBACK_CH3 | 5883859Sml29623 ESR_PAD_LOOPBACK_CH2 | 5893859Sml29623 ESR_PAD_LOOPBACK_CH1 | 5903859Sml29623 ESR_PAD_LOOPBACK_CH0); 5913859Sml29623 } else { 5923859Sml29623 ESR_REG_WR(handle, 5933859Sml29623 ESR_0_TEST_CONFIG_REG, 0); 5943859Sml29623 } 5953859Sml29623 break; 5963859Sml29623 case 1: 5973859Sml29623 ESR_REG_WR(handle, ESR_1_CONTROL_REG, 5983859Sml29623 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 5993859Sml29623 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 6003859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 6013859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 6023859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 6033859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 6043859Sml29623 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 6053859Sml29623 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 6063859Sml29623 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 6073859Sml29623 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 6083859Sml29623 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 6093859Sml29623 6103859Sml29623 /* Set Serdes1 Internal Loopback if necessary */ 6113859Sml29623 if (nxgep->statsp->port_stats.lb_mode == 6123859Sml29623 nxge_lb_serdes10g) { 6133859Sml29623 ESR_REG_WR(handle, 6143859Sml29623 ESR_1_TEST_CONFIG_REG, 6153859Sml29623 ESR_PAD_LOOPBACK_CH3 | 6163859Sml29623 ESR_PAD_LOOPBACK_CH2 | 6173859Sml29623 ESR_PAD_LOOPBACK_CH1 | 6183859Sml29623 ESR_PAD_LOOPBACK_CH0); 6193859Sml29623 } else { 6203859Sml29623 ESR_REG_WR(handle, 6213859Sml29623 ESR_1_TEST_CONFIG_REG, 0); 6223859Sml29623 } 6233859Sml29623 break; 6243859Sml29623 default: 6253859Sml29623 /* Nothing to do here */ 6263859Sml29623 goto done; 6273859Sml29623 } 6283859Sml29623 6293859Sml29623 /* init TX RX channels */ 6303859Sml29623 for (chan = 0; chan < 4; chan++) { 6313859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 6323859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6333859Sml29623 ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 6343859Sml29623 &rx_tx_ctrl_l.value)) != NXGE_OK) 6353859Sml29623 goto fail; 6363859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 6373859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6383859Sml29623 ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 6393859Sml29623 &rx_tx_ctrl_h.value)) != NXGE_OK) 6403859Sml29623 goto fail; 6413859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 6423859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6433859Sml29623 ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 6443859Sml29623 &glue_ctrl0_l.value)) != NXGE_OK) 6453859Sml29623 goto fail; 6463859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 6473859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6483859Sml29623 ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 6493859Sml29623 &glue_ctrl0_h.value)) != NXGE_OK) 6503859Sml29623 goto fail; 6513859Sml29623 rx_tx_ctrl_l.bits.enstretch = 1; 6523859Sml29623 rx_tx_ctrl_h.bits.vmuxlo = 2; 6533859Sml29623 rx_tx_ctrl_h.bits.vpulselo = 2; 6543859Sml29623 glue_ctrl0_l.bits.rxlosenable = 1; 6553859Sml29623 glue_ctrl0_l.bits.samplerate = 0xF; 6563859Sml29623 glue_ctrl0_l.bits.thresholdcount = 0xFF; 6573859Sml29623 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 6583859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6593859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6603859Sml29623 ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 6613859Sml29623 rx_tx_ctrl_l.value)) != NXGE_OK) 6623859Sml29623 goto fail; 6633859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6643859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6653859Sml29623 ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 6663859Sml29623 rx_tx_ctrl_h.value)) != NXGE_OK) 6673859Sml29623 goto fail; 6683859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6693859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6703859Sml29623 ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 6713859Sml29623 glue_ctrl0_l.value)) != NXGE_OK) 6723859Sml29623 goto fail; 6733859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6743859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6753859Sml29623 ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 6763859Sml29623 glue_ctrl0_h.value)) != NXGE_OK) 6773859Sml29623 goto fail; 6783859Sml29623 } 6793859Sml29623 6803859Sml29623 /* Apply Tx core reset */ 6813859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6823859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6833859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 6843859Sml29623 (uint16_t)0)) != NXGE_OK) 6853859Sml29623 goto fail; 6863859Sml29623 6873859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6883859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6893859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 6903859Sml29623 (uint16_t)0xffff)) != NXGE_OK) 6913859Sml29623 goto fail; 6923859Sml29623 6933859Sml29623 NXGE_DELAY(200); 6943859Sml29623 6953859Sml29623 /* Apply Rx core reset */ 6963859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6973859Sml29623 ESR_NEPTUNE_DEV_ADDR, 6983859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 6993859Sml29623 (uint16_t)0xffff)) != NXGE_OK) 7003859Sml29623 goto fail; 7013859Sml29623 7023859Sml29623 NXGE_DELAY(200); 7033859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 7043859Sml29623 ESR_NEPTUNE_DEV_ADDR, 7053859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 7063859Sml29623 (uint16_t)0)) != NXGE_OK) 7073859Sml29623 goto fail; 7083859Sml29623 7093859Sml29623 NXGE_DELAY(200); 7103859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 7113859Sml29623 ESR_NEPTUNE_DEV_ADDR, 7123859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 7133859Sml29623 &val16l)) != NXGE_OK) 7143859Sml29623 goto fail; 7153859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 7163859Sml29623 ESR_NEPTUNE_DEV_ADDR, 7173859Sml29623 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 7183859Sml29623 &val16h)) != NXGE_OK) 7193859Sml29623 goto fail; 7203859Sml29623 if ((val16l != 0) || (val16h != 0)) { 7213859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7223859Sml29623 "Failed to reset port<%d> XAUI Serdes", 7233859Sml29623 portn)); 7243859Sml29623 } 7253859Sml29623 7263859Sml29623 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 7273859Sml29623 7283859Sml29623 if (portn == 0) { 7293859Sml29623 if ((val & ESR_SIG_P0_BITS_MASK) != 7303859Sml29623 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 7313859Sml29623 ESR_SIG_XSERDES_RDY_P0 | 7323859Sml29623 ESR_SIG_XDETECT_P0_CH3 | 7333859Sml29623 ESR_SIG_XDETECT_P0_CH2 | 7343859Sml29623 ESR_SIG_XDETECT_P0_CH1 | 7353859Sml29623 ESR_SIG_XDETECT_P0_CH0)) { 7363859Sml29623 goto fail; 7373859Sml29623 } 7383859Sml29623 } else if (portn == 1) { 7393859Sml29623 if ((val & ESR_SIG_P1_BITS_MASK) != 7403859Sml29623 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 7413859Sml29623 ESR_SIG_XSERDES_RDY_P1 | 7423859Sml29623 ESR_SIG_XDETECT_P1_CH3 | 7433859Sml29623 ESR_SIG_XDETECT_P1_CH2 | 7443859Sml29623 ESR_SIG_XDETECT_P1_CH1 | 7453859Sml29623 ESR_SIG_XDETECT_P1_CH0)) { 7463859Sml29623 goto fail; 7473859Sml29623 } 7483859Sml29623 } 7493859Sml29623 7503859Sml29623 } else if (portmode == PORT_1G_FIBER) { 7513859Sml29623 ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val) 7523859Sml29623 val &= ~ESR_PLL_CFG_FBDIV_2; 7533859Sml29623 switch (portn) { 7543859Sml29623 case 0: 7553859Sml29623 val |= ESR_PLL_CFG_HALF_RATE_0; 7563859Sml29623 break; 7573859Sml29623 case 1: 7583859Sml29623 val |= ESR_PLL_CFG_HALF_RATE_1; 7593859Sml29623 break; 7603859Sml29623 case 2: 7613859Sml29623 val |= ESR_PLL_CFG_HALF_RATE_2; 7623859Sml29623 break; 7633859Sml29623 case 3: 7643859Sml29623 val |= ESR_PLL_CFG_HALF_RATE_3; 7653859Sml29623 break; 7663859Sml29623 default: 7673859Sml29623 goto fail; 7683859Sml29623 } 7693859Sml29623 7703859Sml29623 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 7713859Sml29623 } 7723859Sml29623 7733859Sml29623 done: 7743859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>", 7753859Sml29623 portn)); 7763859Sml29623 return (NXGE_OK); 7773859Sml29623 fail: 7783859Sml29623 NXGE_DEBUG_MSG((nxgep, TX_CTL, 7793859Sml29623 "nxge_neptune_serdes_init: " 7803859Sml29623 "Failed to initialize Neptune serdes for port<%d>", 7813859Sml29623 portn)); 7823859Sml29623 7833859Sml29623 return (status); 7843859Sml29623 } 7853859Sml29623 7863859Sml29623 /* Look for transceiver type */ 7873859Sml29623 7883859Sml29623 nxge_status_t 7893859Sml29623 nxge_xcvr_find(p_nxge_t nxgep) 7903859Sml29623 { 7913859Sml29623 uint8_t portn; 7923859Sml29623 7933859Sml29623 portn = nxgep->mac.portnum; 7943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn)); 7953859Sml29623 7963859Sml29623 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 7973859Sml29623 return (NXGE_ERROR); 7983859Sml29623 7993859Sml29623 nxgep->mac.linkchkmode = LINKCHK_TIMER; 8003859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 8013859Sml29623 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 8023859Sml29623 if ((nxgep->niu_type == NEPTUNE) || 8033859Sml29623 (nxgep->niu_type == NEPTUNE_2)) { 8043859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8053859Sml29623 BCM8704_NEPTUNE_PORT_ADDR_BASE + portn; 8063859Sml29623 } else if (nxgep->niu_type == N2_NIU) { 8073859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8083859Sml29623 BCM8704_N2_PORT_ADDR_BASE + portn; 8093859Sml29623 } else 8103859Sml29623 return (NXGE_ERROR); 8113859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_COPPER) { 8123859Sml29623 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 8133859Sml29623 /* 8143859Sml29623 * For Altas, Xcvr port numbers are swapped with ethernet 8153859Sml29623 * port number. This is designed for better signal 8163859Sml29623 * integrity in routing. 8173859Sml29623 */ 8183859Sml29623 8193859Sml29623 switch (portn) { 8203859Sml29623 case 0: 8213859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8223859Sml29623 BCM5464_NEPTUNE_PORT_ADDR_BASE + 3; 8233859Sml29623 break; 8243859Sml29623 case 1: 8253859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8263859Sml29623 BCM5464_NEPTUNE_PORT_ADDR_BASE + 2; 8273859Sml29623 break; 8283859Sml29623 case 2: 8293859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8303859Sml29623 BCM5464_NEPTUNE_PORT_ADDR_BASE + 1; 8313859Sml29623 break; 8323859Sml29623 case 3: 8333859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = 8343859Sml29623 BCM5464_NEPTUNE_PORT_ADDR_BASE; 8353859Sml29623 break; 8363859Sml29623 default: 8373859Sml29623 return (NXGE_ERROR); 8383859Sml29623 } 8393859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 8403859Sml29623 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 8413859Sml29623 nxgep->statsp->mac_stats.xcvr_portn = portn; 8423859Sml29623 } else { 8433859Sml29623 return (NXGE_ERROR); 8443859Sml29623 } 8453859Sml29623 8463859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 8473859Sml29623 nxgep->statsp->mac_stats.xcvr_inuse)); 8483859Sml29623 return (NXGE_OK); 8493859Sml29623 } 8503859Sml29623 8513859Sml29623 /* Initialize transceiver */ 8523859Sml29623 8533859Sml29623 nxge_status_t 8543859Sml29623 nxge_xcvr_init(p_nxge_t nxgep) 8553859Sml29623 { 8563859Sml29623 p_nxge_param_t param_arr; 8573859Sml29623 p_nxge_stats_t statsp; 8583859Sml29623 uint16_t val; 8593859Sml29623 #ifdef NXGE_DEBUG 8603859Sml29623 uint8_t portn; 8613859Sml29623 uint16_t val1; 8623859Sml29623 #endif 8633859Sml29623 uint8_t phy_port_addr; 8643859Sml29623 pmd_tx_control_t tx_ctl; 8653859Sml29623 control_t ctl; 8663859Sml29623 phyxs_control_t phyxs_ctl; 8673859Sml29623 pcs_control_t pcs_ctl; 8683859Sml29623 uint32_t delay = 0; 8693859Sml29623 optics_dcntr_t op_ctr; 8703859Sml29623 nxge_status_t status = NXGE_OK; 8713859Sml29623 #ifdef NXGE_DEBUG 8723859Sml29623 portn = nxgep->mac.portnum; 8733859Sml29623 #endif 8743859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 8753859Sml29623 8763859Sml29623 param_arr = nxgep->param_arr; 8773859Sml29623 statsp = nxgep->statsp; 8783859Sml29623 8793859Sml29623 /* 8803859Sml29623 * Initialize the xcvr statistics. 8813859Sml29623 */ 8823859Sml29623 statsp->mac_stats.cap_autoneg = 0; 8833859Sml29623 statsp->mac_stats.cap_100T4 = 0; 8843859Sml29623 statsp->mac_stats.cap_100fdx = 0; 8853859Sml29623 statsp->mac_stats.cap_100hdx = 0; 8863859Sml29623 statsp->mac_stats.cap_10fdx = 0; 8873859Sml29623 statsp->mac_stats.cap_10hdx = 0; 8883859Sml29623 statsp->mac_stats.cap_asmpause = 0; 8893859Sml29623 statsp->mac_stats.cap_pause = 0; 8903859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 8913859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 8923859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 8933859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 8943859Sml29623 8953859Sml29623 /* 8963859Sml29623 * Initialize the link statistics. 8973859Sml29623 */ 8983859Sml29623 statsp->mac_stats.link_T4 = 0; 8993859Sml29623 statsp->mac_stats.link_asmpause = 0; 9003859Sml29623 statsp->mac_stats.link_pause = 0; 9013859Sml29623 9023859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 9033859Sml29623 9043859Sml29623 switch (nxgep->mac.portmode) { 9053859Sml29623 case PORT_10G_FIBER: 9063859Sml29623 /* Disable Link LEDs */ 9073859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 9083859Sml29623 goto fail; 9093859Sml29623 9103859Sml29623 /* Set Clause 45 */ 9113859Sml29623 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 9123859Sml29623 9133859Sml29623 /* Reset the transceiver */ 9143859Sml29623 if ((status = nxge_mdio_read(nxgep, 9153859Sml29623 phy_port_addr, 9163859Sml29623 BCM8704_PHYXS_ADDR, 9173859Sml29623 BCM8704_PHYXS_CONTROL_REG, 9183859Sml29623 &phyxs_ctl.value)) != NXGE_OK) 9193859Sml29623 goto fail; 9203859Sml29623 9213859Sml29623 phyxs_ctl.bits.reset = 1; 9223859Sml29623 if ((status = nxge_mdio_write(nxgep, 9233859Sml29623 phy_port_addr, 9243859Sml29623 BCM8704_PHYXS_ADDR, 9253859Sml29623 BCM8704_PHYXS_CONTROL_REG, 9263859Sml29623 phyxs_ctl.value)) != NXGE_OK) 9273859Sml29623 goto fail; 9283859Sml29623 9293859Sml29623 do { 9303859Sml29623 drv_usecwait(500); 9313859Sml29623 if ((status = nxge_mdio_read(nxgep, 9323859Sml29623 phy_port_addr, 9333859Sml29623 BCM8704_PHYXS_ADDR, 9343859Sml29623 BCM8704_PHYXS_CONTROL_REG, 9353859Sml29623 &phyxs_ctl.value)) != NXGE_OK) 9363859Sml29623 goto fail; 9373859Sml29623 delay++; 9383859Sml29623 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 9393859Sml29623 if (delay == 100) { 9403859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9413859Sml29623 "nxge_xcvr_init: " 9423859Sml29623 "failed to reset Transceiver on port<%d>", 9433859Sml29623 portn)); 9443859Sml29623 status = NXGE_ERROR; 9453859Sml29623 goto fail; 9463859Sml29623 } 9473859Sml29623 9483859Sml29623 /* Set to 0x7FBF */ 9493859Sml29623 ctl.value = 0; 9503859Sml29623 ctl.bits.res1 = 0x3F; 9513859Sml29623 ctl.bits.optxon_lvl = 1; 9523859Sml29623 ctl.bits.oprxflt_lvl = 1; 9533859Sml29623 ctl.bits.optrxlos_lvl = 1; 9543859Sml29623 ctl.bits.optxflt_lvl = 1; 9553859Sml29623 ctl.bits.opprflt_lvl = 1; 9563859Sml29623 ctl.bits.obtmpflt_lvl = 1; 9573859Sml29623 ctl.bits.opbiasflt_lvl = 1; 9583859Sml29623 ctl.bits.optxrst_lvl = 1; 9593859Sml29623 if ((status = nxge_mdio_write(nxgep, 9603859Sml29623 phy_port_addr, 9613859Sml29623 BCM8704_USER_DEV3_ADDR, 9623859Sml29623 BCM8704_USER_CONTROL_REG, ctl.value)) 9633859Sml29623 != NXGE_OK) 9643859Sml29623 goto fail; 9653859Sml29623 9663859Sml29623 /* Set to 0x164 */ 9673859Sml29623 tx_ctl.value = 0; 9683859Sml29623 tx_ctl.bits.tsck_lpwren = 1; 9693859Sml29623 tx_ctl.bits.tx_dac_txck = 0x2; 9703859Sml29623 tx_ctl.bits.tx_dac_txd = 0x1; 9713859Sml29623 tx_ctl.bits.xfp_clken = 1; 9723859Sml29623 if ((status = nxge_mdio_write(nxgep, 9733859Sml29623 phy_port_addr, 9743859Sml29623 BCM8704_USER_DEV3_ADDR, 9753859Sml29623 BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value)) 9763859Sml29623 != NXGE_OK) 9773859Sml29623 goto fail; 9783859Sml29623 /* 9793859Sml29623 * According to Broadcom's instruction, SW needs to read 9803859Sml29623 * back these registers twice after written. 9813859Sml29623 */ 9823859Sml29623 if ((status = nxge_mdio_read(nxgep, 9833859Sml29623 phy_port_addr, 9843859Sml29623 BCM8704_USER_DEV3_ADDR, 9853859Sml29623 BCM8704_USER_CONTROL_REG, &val)) 9863859Sml29623 != NXGE_OK) 9873859Sml29623 goto fail; 9883859Sml29623 9893859Sml29623 if ((status = nxge_mdio_read(nxgep, 9903859Sml29623 phy_port_addr, 9913859Sml29623 BCM8704_USER_DEV3_ADDR, 9923859Sml29623 BCM8704_USER_CONTROL_REG, &val)) 9933859Sml29623 != NXGE_OK) 9943859Sml29623 goto fail; 9953859Sml29623 9963859Sml29623 if ((status = nxge_mdio_read(nxgep, 9973859Sml29623 phy_port_addr, 9983859Sml29623 BCM8704_USER_DEV3_ADDR, 9993859Sml29623 BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 10003859Sml29623 != NXGE_OK) 10013859Sml29623 goto fail; 10023859Sml29623 10033859Sml29623 if ((status = nxge_mdio_read(nxgep, 10043859Sml29623 phy_port_addr, 10053859Sml29623 BCM8704_USER_DEV3_ADDR, 10063859Sml29623 BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 10073859Sml29623 != NXGE_OK) 10083859Sml29623 goto fail; 10093859Sml29623 10103859Sml29623 10113859Sml29623 /* Enable Tx and Rx LEDs to be driven by traffic */ 10123859Sml29623 if ((status = nxge_mdio_read(nxgep, 10133859Sml29623 phy_port_addr, 10143859Sml29623 BCM8704_USER_DEV3_ADDR, 10153859Sml29623 BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 10163859Sml29623 &op_ctr.value)) != NXGE_OK) 10173859Sml29623 goto fail; 10183859Sml29623 op_ctr.bits.gpio_sel = 0x3; 10193859Sml29623 if ((status = nxge_mdio_write(nxgep, 10203859Sml29623 phy_port_addr, 10213859Sml29623 BCM8704_USER_DEV3_ADDR, 10223859Sml29623 BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 10233859Sml29623 op_ctr.value)) != NXGE_OK) 10243859Sml29623 goto fail; 10253859Sml29623 10263859Sml29623 NXGE_DELAY(1000000); 10273859Sml29623 10283859Sml29623 /* Set BCM8704 Internal Loopback mode if necessary */ 10293859Sml29623 if ((status = nxge_mdio_read(nxgep, 10303859Sml29623 phy_port_addr, 10313859Sml29623 BCM8704_PCS_DEV_ADDR, 10323859Sml29623 BCM8704_PCS_CONTROL_REG, 10333859Sml29623 &pcs_ctl.value)) != NXGE_OK) 10343859Sml29623 goto fail; 10353859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 10363859Sml29623 pcs_ctl.bits.loopback = 1; 10373859Sml29623 else 10383859Sml29623 pcs_ctl.bits.loopback = 0; 10393859Sml29623 if ((status = nxge_mdio_write(nxgep, 10403859Sml29623 phy_port_addr, 10413859Sml29623 BCM8704_PCS_DEV_ADDR, 10423859Sml29623 BCM8704_PCS_CONTROL_REG, 10433859Sml29623 pcs_ctl.value)) != NXGE_OK) 10443859Sml29623 goto fail; 10453859Sml29623 10463859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 10473859Sml29623 0x1, 0xA, &val); 10483859Sml29623 if (status != NXGE_OK) 10493859Sml29623 goto fail; 10503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10513859Sml29623 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", 10523859Sml29623 portn, val)); 10533859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 10543859Sml29623 if (status != NXGE_OK) 10553859Sml29623 goto fail; 10563859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10573859Sml29623 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", 10583859Sml29623 portn, val)); 10593859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 10603859Sml29623 if (status != NXGE_OK) 10613859Sml29623 goto fail; 10623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10633859Sml29623 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", 10643859Sml29623 portn, val)); 10653859Sml29623 10663859Sml29623 #ifdef NXGE_DEBUG 10673859Sml29623 /* Diagnose link issue if link is not up */ 10683859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 10693859Sml29623 BCM8704_USER_DEV3_ADDR, 10703859Sml29623 BCM8704_USER_ANALOG_STATUS0_REG, 10713859Sml29623 &val); 10723859Sml29623 if (status != NXGE_OK) 10733859Sml29623 goto fail; 10743859Sml29623 10753859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 10763859Sml29623 BCM8704_USER_DEV3_ADDR, 10773859Sml29623 BCM8704_USER_ANALOG_STATUS0_REG, 10783859Sml29623 &val); 10793859Sml29623 if (status != NXGE_OK) 10803859Sml29623 goto fail; 10813859Sml29623 10823859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 10833859Sml29623 BCM8704_USER_DEV3_ADDR, 10843859Sml29623 BCM8704_USER_TX_ALARM_STATUS_REG, 10853859Sml29623 &val1); 10863859Sml29623 if (status != NXGE_OK) 10873859Sml29623 goto fail; 10883859Sml29623 10893859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 10903859Sml29623 BCM8704_USER_DEV3_ADDR, 10913859Sml29623 BCM8704_USER_TX_ALARM_STATUS_REG, 10923859Sml29623 &val1); 10933859Sml29623 if (status != NXGE_OK) 10943859Sml29623 goto fail; 10953859Sml29623 10963859Sml29623 if (val != 0x3FC) { 10973859Sml29623 if ((val == 0x43BC) && (val1 != 0)) { 10983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 10993859Sml29623 "Cable not connected to peer or bad" 11003859Sml29623 " cable on port<%d>\n", portn)); 11013859Sml29623 } else if (val == 0x639C) { 11023859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11033859Sml29623 "Optical module (XFP) is bad or absence" 11043859Sml29623 " on port<%d>\n", portn)); 11053859Sml29623 } 11063859Sml29623 } 11073859Sml29623 #endif 11083859Sml29623 11093859Sml29623 statsp->mac_stats.cap_10gfdx = 1; 11103859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 1; 11113859Sml29623 break; 11123859Sml29623 case PORT_10G_COPPER: 11133859Sml29623 break; 11143859Sml29623 case PORT_1G_FIBER: 11153859Sml29623 case PORT_1G_COPPER: 11163859Sml29623 /* Set Clause 22 */ 11173859Sml29623 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 11183859Sml29623 11193859Sml29623 /* Set capability flags */ 11203859Sml29623 statsp->mac_stats.cap_1000fdx = 11213859Sml29623 param_arr[param_anar_1000fdx].value; 11223859Sml29623 statsp->mac_stats.cap_100fdx = 11233859Sml29623 param_arr[param_anar_100fdx].value; 11243859Sml29623 statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value; 11253859Sml29623 11263859Sml29623 if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK) 11273859Sml29623 goto fail; 11283859Sml29623 break; 11293859Sml29623 default: 11303859Sml29623 goto fail; 11313859Sml29623 } 11323859Sml29623 11333859Sml29623 statsp->mac_stats.xcvr_inits++; 11343859Sml29623 11353859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 11363859Sml29623 return (NXGE_OK); 11373859Sml29623 11383859Sml29623 fail: 11393859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11403859Sml29623 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 11413859Sml29623 portn)); 11423859Sml29623 return (status); 11433859Sml29623 } 11443859Sml29623 11453859Sml29623 11463859Sml29623 /* Initialize the TxMAC sub-block */ 11473859Sml29623 11483859Sml29623 nxge_status_t 11493859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 11503859Sml29623 { 11513859Sml29623 npi_attr_t ap; 11523859Sml29623 uint8_t portn; 11533859Sml29623 nxge_port_mode_t portmode; 11543859Sml29623 nxge_port_t portt; 11553859Sml29623 npi_handle_t handle; 11563859Sml29623 npi_status_t rs = NPI_SUCCESS; 11573859Sml29623 11583859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 11593859Sml29623 portt = nxgep->mac.porttype; 11603859Sml29623 handle = nxgep->npi_handle; 11613859Sml29623 portmode = nxgep->mac.portmode; 11623859Sml29623 11633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 11643859Sml29623 portn)); 11653859Sml29623 11663859Sml29623 /* Set Max and Min Frame Size */ 11673859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 11683859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 11693859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 11703859Sml29623 } else { 11713859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 11723859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 11733859Sml29623 } 11743859Sml29623 11753859Sml29623 if (rs != NPI_SUCCESS) 11763859Sml29623 goto fail; 11773859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || 11783859Sml29623 nxgep->mac.is_jumbo == B_TRUE) 11793859Sml29623 nxgep->mac.maxframesize = 0x2400; 11803859Sml29623 else 11813859Sml29623 nxgep->mac.maxframesize = 0x5EE + 4; 11823859Sml29623 nxgep->mac.minframesize = 64; 11833859Sml29623 11843859Sml29623 if (portt == PORT_TYPE_XMAC) { 11853859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 11863859Sml29623 0)) != NPI_SUCCESS) 11873859Sml29623 goto fail; 11883859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 11893859Sml29623 if ((portmode == PORT_10G_FIBER) || 11903859Sml29623 (portmode == PORT_10G_COPPER)) { 11913859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 11923859Sml29623 XGMII_IPG_12_15, rs); 11933859Sml29623 if (rs != NPI_SUCCESS) 11943859Sml29623 goto fail; 11953859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 11963859Sml29623 } else { 11973859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 11983859Sml29623 MII_GMII_IPG_12, rs); 11993859Sml29623 if (rs != NPI_SUCCESS) 12003859Sml29623 goto fail; 12013859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 12023859Sml29623 } 12033859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 12043859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 12053859Sml29623 goto fail; 12063859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 12073859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 12083859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 12093859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 12103859Sml29623 12113859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 12123859Sml29623 != NPI_SUCCESS) 12133859Sml29623 goto fail; 12143859Sml29623 12153859Sml29623 } else { 12163859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 12173859Sml29623 0)) != NPI_SUCCESS) 12183859Sml29623 goto fail; 12193859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 12203859Sml29623 12213859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 12223859Sml29623 rs); 12233859Sml29623 if (rs != NPI_SUCCESS) 12243859Sml29623 goto fail; 12253859Sml29623 nxgep->mac.ctrltype = 0x8808; 12263859Sml29623 12273859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 12283859Sml29623 if (rs != NPI_SUCCESS) 12293859Sml29623 goto fail; 12303859Sml29623 nxgep->mac.pa_size = 0x7; 12313859Sml29623 12323859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 12333859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 12343859Sml29623 goto fail; 12353859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 12363859Sml29623 } 12373859Sml29623 12383859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 12393859Sml29623 portn)); 12403859Sml29623 12413859Sml29623 return (NXGE_OK); 12423859Sml29623 fail: 12433859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12443859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 12453859Sml29623 portn)); 12463859Sml29623 12473859Sml29623 return (NXGE_ERROR | rs); 12483859Sml29623 } 12493859Sml29623 12503859Sml29623 /* Initialize the RxMAC sub-block */ 12513859Sml29623 12523859Sml29623 nxge_status_t 12533859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 12543859Sml29623 { 12553859Sml29623 npi_attr_t ap; 12563859Sml29623 uint32_t i; 12573859Sml29623 uint16_t hashtab_e; 12583859Sml29623 p_hash_filter_t hash_filter; 12593859Sml29623 nxge_port_t portt; 12603859Sml29623 uint8_t portn; 12613859Sml29623 npi_handle_t handle; 12623859Sml29623 npi_status_t rs = NPI_SUCCESS; 12633859Sml29623 uint16_t *addr16p; 12643859Sml29623 uint16_t addr0, addr1, addr2; 12653859Sml29623 xmac_rx_config_t xconfig; 12663859Sml29623 bmac_rx_config_t bconfig; 12673859Sml29623 12683859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 12693859Sml29623 12703859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 12713859Sml29623 portn)); 12723859Sml29623 handle = nxgep->npi_handle; 12733859Sml29623 portt = nxgep->mac.porttype; 12743859Sml29623 12753859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 12763859Sml29623 addr0 = ntohs(addr16p[2]); 12773859Sml29623 addr1 = ntohs(addr16p[1]); 12783859Sml29623 addr2 = ntohs(addr16p[0]); 12793859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 12803859Sml29623 rs); 12813859Sml29623 12823859Sml29623 if (rs != NPI_SUCCESS) 12833859Sml29623 goto fail; 12843859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 12853859Sml29623 if (rs != NPI_SUCCESS) 12863859Sml29623 goto fail; 12873859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 12883859Sml29623 if (rs != NPI_SUCCESS) 12893859Sml29623 goto fail; 12903859Sml29623 12913859Sml29623 /* 12923859Sml29623 * Load the multicast hash filter bits. 12933859Sml29623 */ 12943859Sml29623 hash_filter = nxgep->hash_filter; 12953859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 12963859Sml29623 if (hash_filter != NULL) { 12973859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 12983859Sml29623 (NMCFILTER_REGS - 1) - i]; 12993859Sml29623 } else { 13003859Sml29623 hashtab_e = 0; 13013859Sml29623 } 13023859Sml29623 13033859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 13043859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 13053859Sml29623 goto fail; 13063859Sml29623 } 13073859Sml29623 13083859Sml29623 if (portt == PORT_TYPE_XMAC) { 13093859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 13103859Sml29623 0)) != NPI_SUCCESS) 13113859Sml29623 goto fail; 13123859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 13133859Sml29623 13143859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 13153859Sml29623 13163859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 13173859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 13183859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 13193859Sml29623 13203859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 13213859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 13223859Sml29623 13233859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 13243859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 13253859Sml29623 13263859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 13273859Sml29623 13283859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 13293859Sml29623 xconfig)) != NPI_SUCCESS) 13303859Sml29623 goto fail; 13313859Sml29623 nxgep->mac.rx_config = xconfig; 13323859Sml29623 13333859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 13343859Sml29623 13353859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 13363859Sml29623 != NPI_SUCCESS) 13373859Sml29623 goto fail; 13383859Sml29623 } else { 13393859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 13403859Sml29623 13413859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 13423859Sml29623 0) != NPI_SUCCESS) 13433859Sml29623 goto fail; 13443859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 13453859Sml29623 13463859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 13473859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 13483859Sml29623 13493859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 13503859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 13513859Sml29623 13523859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 13533859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 13543859Sml29623 13553859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 13563859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 13573859Sml29623 bconfig)) != NPI_SUCCESS) 13583859Sml29623 goto fail; 13593859Sml29623 nxgep->mac.rx_config = bconfig; 13603859Sml29623 13613859Sml29623 /* Always enable comparison of mac unique address */ 13623859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 13633859Sml29623 != NPI_SUCCESS) 13643859Sml29623 goto fail; 13653859Sml29623 } 13663859Sml29623 13673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 13683859Sml29623 portn)); 13693859Sml29623 13703859Sml29623 return (NXGE_OK); 13713859Sml29623 13723859Sml29623 fail: 13733859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 13743859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 13753859Sml29623 portn)); 13763859Sml29623 13773859Sml29623 return (NXGE_ERROR | rs); 13783859Sml29623 } 13793859Sml29623 13803859Sml29623 /* Enable TXMAC */ 13813859Sml29623 13823859Sml29623 nxge_status_t 13833859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 13843859Sml29623 { 13853859Sml29623 npi_handle_t handle; 13863859Sml29623 npi_status_t rs = NPI_SUCCESS; 13873859Sml29623 nxge_status_t status = NXGE_OK; 13883859Sml29623 13893859Sml29623 handle = nxgep->npi_handle; 13903859Sml29623 13913859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 13923859Sml29623 nxgep->mac.portnum)); 13933859Sml29623 13943859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 13953859Sml29623 goto fail; 13963859Sml29623 13973859Sml29623 /* based on speed */ 13983859Sml29623 nxgep->msg_min = ETHERMIN; 13993859Sml29623 14003859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 14013859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 14023859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 14033859Sml29623 goto fail; 14043859Sml29623 } else { 14053859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 14063859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 14073859Sml29623 goto fail; 14083859Sml29623 } 14093859Sml29623 14103859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 14113859Sml29623 nxgep->mac.portnum)); 14123859Sml29623 14133859Sml29623 return (NXGE_OK); 14143859Sml29623 fail: 14153859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14163859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 14173859Sml29623 nxgep->mac.portnum)); 14183859Sml29623 if (rs != NPI_SUCCESS) 14193859Sml29623 return (NXGE_ERROR | rs); 14203859Sml29623 else 14213859Sml29623 return (status); 14223859Sml29623 } 14233859Sml29623 14243859Sml29623 /* Disable TXMAC */ 14253859Sml29623 14263859Sml29623 nxge_status_t 14273859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 14283859Sml29623 { 14293859Sml29623 npi_handle_t handle; 14303859Sml29623 npi_status_t rs = NPI_SUCCESS; 14313859Sml29623 14323859Sml29623 handle = nxgep->npi_handle; 14333859Sml29623 14343859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 14353859Sml29623 nxgep->mac.portnum)); 14363859Sml29623 14373859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 14383859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 14393859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 14403859Sml29623 goto fail; 14413859Sml29623 } else { 14423859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 14433859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 14443859Sml29623 goto fail; 14453859Sml29623 } 14463859Sml29623 14473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 14483859Sml29623 nxgep->mac.portnum)); 14493859Sml29623 return (NXGE_OK); 14503859Sml29623 fail: 14513859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14523859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 14533859Sml29623 nxgep->mac.portnum)); 14543859Sml29623 return (NXGE_ERROR | rs); 14553859Sml29623 } 14563859Sml29623 14573859Sml29623 /* Enable RXMAC */ 14583859Sml29623 14593859Sml29623 nxge_status_t 14603859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 14613859Sml29623 { 14623859Sml29623 npi_handle_t handle; 14633859Sml29623 uint8_t portn; 14643859Sml29623 npi_status_t rs = NPI_SUCCESS; 14653859Sml29623 nxge_status_t status = NXGE_OK; 14663859Sml29623 14673859Sml29623 handle = nxgep->npi_handle; 14683859Sml29623 portn = nxgep->mac.portnum; 14693859Sml29623 14703859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 14713859Sml29623 portn)); 14723859Sml29623 14733859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 14743859Sml29623 goto fail; 14753859Sml29623 14763859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 14773859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 14783859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 14793859Sml29623 goto fail; 14803859Sml29623 } else { 14813859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 14823859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 14833859Sml29623 goto fail; 14843859Sml29623 } 14853859Sml29623 14863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 14873859Sml29623 portn)); 14883859Sml29623 14893859Sml29623 return (NXGE_OK); 14903859Sml29623 fail: 14913859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14923859Sml29623 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 14933859Sml29623 portn)); 14943859Sml29623 14953859Sml29623 if (rs != NPI_SUCCESS) 14963859Sml29623 return (NXGE_ERROR | rs); 14973859Sml29623 else 14983859Sml29623 return (status); 14993859Sml29623 } 15003859Sml29623 15013859Sml29623 /* Disable RXMAC */ 15023859Sml29623 15033859Sml29623 nxge_status_t 15043859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 15053859Sml29623 { 15063859Sml29623 npi_handle_t handle; 15073859Sml29623 uint8_t portn; 15083859Sml29623 npi_status_t rs = NPI_SUCCESS; 15093859Sml29623 15103859Sml29623 handle = nxgep->npi_handle; 15113859Sml29623 portn = nxgep->mac.portnum; 15123859Sml29623 15133859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 15143859Sml29623 portn)); 15153859Sml29623 15163859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15173859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 15183859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 15193859Sml29623 goto fail; 15203859Sml29623 } else { 15213859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 15223859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 15233859Sml29623 goto fail; 15243859Sml29623 } 15253859Sml29623 15263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 15273859Sml29623 portn)); 15283859Sml29623 return (NXGE_OK); 15293859Sml29623 fail: 15303859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15313859Sml29623 "nxgep_rx_mac_disable: ", 15323859Sml29623 "Failed to disable port<%d> RxMAC", 15333859Sml29623 portn)); 15343859Sml29623 15353859Sml29623 return (NXGE_ERROR | rs); 15363859Sml29623 } 15373859Sml29623 15383859Sml29623 /* Reset TXMAC */ 15393859Sml29623 15403859Sml29623 nxge_status_t 15413859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 15423859Sml29623 { 15433859Sml29623 npi_handle_t handle; 15443859Sml29623 uint8_t portn; 15453859Sml29623 npi_status_t rs = NPI_SUCCESS; 15463859Sml29623 15473859Sml29623 handle = nxgep->npi_handle; 15483859Sml29623 portn = nxgep->mac.portnum; 15493859Sml29623 15503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 15513859Sml29623 portn)); 15523859Sml29623 15533859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15543859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 15553859Sml29623 != NPI_SUCCESS) 15563859Sml29623 goto fail; 15573859Sml29623 } else { 15583859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 15593859Sml29623 != NPI_SUCCESS) 15603859Sml29623 goto fail; 15613859Sml29623 } 15623859Sml29623 15633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 15643859Sml29623 portn)); 15653859Sml29623 15663859Sml29623 return (NXGE_OK); 15673859Sml29623 fail: 15683859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15693859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 15703859Sml29623 portn)); 15713859Sml29623 15723859Sml29623 return (NXGE_ERROR | rs); 15733859Sml29623 } 15743859Sml29623 15753859Sml29623 /* Reset RXMAC */ 15763859Sml29623 15773859Sml29623 nxge_status_t 15783859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 15793859Sml29623 { 15803859Sml29623 npi_handle_t handle; 15813859Sml29623 uint8_t portn; 15823859Sml29623 npi_status_t rs = NPI_SUCCESS; 15833859Sml29623 15843859Sml29623 handle = nxgep->npi_handle; 15853859Sml29623 portn = nxgep->mac.portnum; 15863859Sml29623 15873859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 15883859Sml29623 portn)); 15893859Sml29623 15903859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15913859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 15923859Sml29623 != NPI_SUCCESS) 15933859Sml29623 goto fail; 15943859Sml29623 } else { 15953859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 15963859Sml29623 != NPI_SUCCESS) 15973859Sml29623 goto fail; 15983859Sml29623 } 15993859Sml29623 16003859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 16013859Sml29623 portn)); 16023859Sml29623 16033859Sml29623 return (NXGE_OK); 16043859Sml29623 fail: 16053859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16063859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 16073859Sml29623 portn)); 16083859Sml29623 return (NXGE_ERROR | rs); 16093859Sml29623 } 16103859Sml29623 16113859Sml29623 16123859Sml29623 /* Enable/Disable MII Link Status change interrupt */ 16133859Sml29623 16143859Sml29623 nxge_status_t 16153859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 16163859Sml29623 { 16173859Sml29623 uint8_t portn; 16183859Sml29623 nxge_port_mode_t portmode; 16193859Sml29623 npi_status_t rs = NPI_SUCCESS; 16203859Sml29623 16213859Sml29623 portn = nxgep->mac.portnum; 16223859Sml29623 portmode = nxgep->mac.portmode; 16233859Sml29623 16243859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 16253859Sml29623 16263859Sml29623 if (enable == LINK_INTR_START) { 16273859Sml29623 if (portmode == PORT_10G_FIBER) { 16283859Sml29623 if ((rs = npi_xmac_xpcs_link_intr_enable( 16293859Sml29623 nxgep->npi_handle, 16303859Sml29623 portn)) != NPI_SUCCESS) 16313859Sml29623 goto fail; 16323859Sml29623 } else if (portmode == PORT_1G_FIBER) { 16333859Sml29623 if ((rs = npi_mac_pcs_link_intr_enable( 16343859Sml29623 nxgep->npi_handle, 16353859Sml29623 portn)) != NPI_SUCCESS) 16363859Sml29623 goto fail; 16373859Sml29623 } else if (portmode == PORT_1G_COPPER) { 16383859Sml29623 if ((rs = npi_mac_mif_link_intr_enable( 16393859Sml29623 nxgep->npi_handle, 16403859Sml29623 portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS) 16413859Sml29623 goto fail; 16423859Sml29623 } else 16433859Sml29623 goto fail; 16443859Sml29623 } else if (enable == LINK_INTR_STOP) { 16453859Sml29623 if (portmode == PORT_10G_FIBER) { 16463859Sml29623 if ((rs = npi_xmac_xpcs_link_intr_disable( 16473859Sml29623 nxgep->npi_handle, 16483859Sml29623 portn)) != NPI_SUCCESS) 16493859Sml29623 goto fail; 16503859Sml29623 } else if (portmode == PORT_1G_FIBER) { 16513859Sml29623 if ((rs = npi_mac_pcs_link_intr_disable( 16523859Sml29623 nxgep->npi_handle, 16533859Sml29623 portn)) != NPI_SUCCESS) 16543859Sml29623 goto fail; 16553859Sml29623 } else if (portmode == PORT_1G_COPPER) { 16563859Sml29623 if ((rs = npi_mac_mif_link_intr_disable( 16573859Sml29623 nxgep->npi_handle, 16583859Sml29623 portn)) != NPI_SUCCESS) 16593859Sml29623 goto fail; 16603859Sml29623 } else 16613859Sml29623 goto fail; 16623859Sml29623 } 16633859Sml29623 16643859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 16653859Sml29623 16663859Sml29623 return (NXGE_OK); 16673859Sml29623 fail: 16683859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16693859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 16703859Sml29623 portn)); 16713859Sml29623 16723859Sml29623 return (NXGE_ERROR | rs); 16733859Sml29623 } 16743859Sml29623 16753859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 16763859Sml29623 16773859Sml29623 nxge_status_t 16783859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 16793859Sml29623 { 16803859Sml29623 p_nxge_param_t param_arr; 16813859Sml29623 p_nxge_stats_t statsp; 16823859Sml29623 uint8_t xcvr_portn; 16833859Sml29623 p_mii_regs_t mii_regs; 16843859Sml29623 mii_bmcr_t bmcr; 16853859Sml29623 mii_bmsr_t bmsr; 16863859Sml29623 mii_anar_t anar; 16873859Sml29623 mii_gcr_t gcr; 16883859Sml29623 mii_esr_t esr; 16893859Sml29623 mii_aux_ctl_t bcm5464r_aux; 16903859Sml29623 int status = NXGE_OK; 16913859Sml29623 16923859Sml29623 uint_t delay; 16933859Sml29623 16943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 16953859Sml29623 16963859Sml29623 param_arr = nxgep->param_arr; 16973859Sml29623 statsp = nxgep->statsp; 16983859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 16993859Sml29623 17003859Sml29623 mii_regs = NULL; 17013859Sml29623 17023859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 17033859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 17043859Sml29623 17053859Sml29623 /* 17063859Sml29623 * Reset the transceiver. 17073859Sml29623 */ 17083859Sml29623 delay = 0; 17093859Sml29623 bmcr.value = 0; 17103859Sml29623 bmcr.bits.reset = 1; 17113859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 17123859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 17133859Sml29623 goto fail; 17143859Sml29623 do { 17153859Sml29623 drv_usecwait(500); 17163859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 17173859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 17183859Sml29623 != NXGE_OK) 17193859Sml29623 goto fail; 17203859Sml29623 delay++; 17213859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 17223859Sml29623 if (delay == 1000) { 17233859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 17243859Sml29623 goto fail; 17253859Sml29623 } 17263859Sml29623 17273859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 17283859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 17293859Sml29623 &bmsr.value)) != NXGE_OK) 17303859Sml29623 goto fail; 17313859Sml29623 17323859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 17333859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 17343859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 17353859Sml29623 param_arr[param_anar_100hdx].value = 0; 17363859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 17373859Sml29623 param_arr[param_anar_10hdx].value = 0; 17383859Sml29623 17393859Sml29623 /* 17403859Sml29623 * Initialize the xcvr statistics. 17413859Sml29623 */ 17423859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 17433859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 17443859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 17453859Sml29623 statsp->mac_stats.cap_100hdx = 0; 17463859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 17473859Sml29623 statsp->mac_stats.cap_10hdx = 0; 17483859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 17493859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 17503859Sml29623 17513859Sml29623 /* 17523859Sml29623 * Initialise the xcvr advertised capability statistics. 17533859Sml29623 */ 17543859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 17553859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 17563859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 17573859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 17583859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 17593859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 17603859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 17613859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 17623859Sml29623 statsp->mac_stats.adv_cap_asmpause = 17633859Sml29623 param_arr[param_anar_asmpause].value; 17643859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 17653859Sml29623 17663859Sml29623 17673859Sml29623 /* 17683859Sml29623 * Check for extended status just in case we're 17693859Sml29623 * running a Gigibit phy. 17703859Sml29623 */ 17713859Sml29623 if (bmsr.bits.extend_status) { 17723859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 17733859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 17743859Sml29623 != NXGE_OK) 17753859Sml29623 goto fail; 17763859Sml29623 param_arr[param_anar_1000fdx].value &= 17773859Sml29623 esr.bits.link_1000fdx; 17783859Sml29623 param_arr[param_anar_1000hdx].value = 0; 17793859Sml29623 17803859Sml29623 statsp->mac_stats.cap_1000fdx = 17813859Sml29623 (esr.bits.link_1000Xfdx || 17823859Sml29623 esr.bits.link_1000fdx); 17833859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 17843859Sml29623 } else { 17853859Sml29623 param_arr[param_anar_1000fdx].value = 0; 17863859Sml29623 param_arr[param_anar_1000hdx].value = 0; 17873859Sml29623 } 17883859Sml29623 17893859Sml29623 /* 17903859Sml29623 * Initialize 1G Statistics once the capability is established. 17913859Sml29623 */ 17923859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 17933859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 17943859Sml29623 17953859Sml29623 /* 17963859Sml29623 * Initialise the link statistics. 17973859Sml29623 */ 17983859Sml29623 statsp->mac_stats.link_T4 = 0; 17993859Sml29623 statsp->mac_stats.link_asmpause = 0; 18003859Sml29623 statsp->mac_stats.link_pause = 0; 18013859Sml29623 statsp->mac_stats.link_speed = 0; 18023859Sml29623 statsp->mac_stats.link_duplex = 0; 18033859Sml29623 statsp->mac_stats.link_up = 0; 18043859Sml29623 18053859Sml29623 /* 18063859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 18073859Sml29623 */ 18083859Sml29623 bmcr.value = 0; 18093859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18103859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 18113859Sml29623 goto fail; 18123859Sml29623 18133859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 18143859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 18153859Sml29623 bmcr.bits.loopback = 1; 18163859Sml29623 bmcr.bits.enable_autoneg = 0; 18173859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 18183859Sml29623 bmcr.bits.speed_1000_sel = 1; 18193859Sml29623 bmcr.bits.duplex_mode = 1; 18203859Sml29623 param_arr[param_autoneg].value = 0; 18213859Sml29623 } else { 18223859Sml29623 bmcr.bits.loopback = 0; 18233859Sml29623 } 18243859Sml29623 18253859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 18263859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 18273859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 18283859Sml29623 param_arr[param_autoneg].value = 0; 18293859Sml29623 bcm5464r_aux.value = 0; 18303859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 18313859Sml29623 bcm5464r_aux.bits.write_1 = 1; 18323859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18333859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 18343859Sml29623 != NXGE_OK) 18353859Sml29623 goto fail; 18363859Sml29623 } 18373859Sml29623 18383859Sml29623 if (param_arr[param_autoneg].value) { 18393859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18403859Sml29623 "Restarting Auto-negotiation.")); 18413859Sml29623 /* 18423859Sml29623 * Setup our Auto-negotiation advertisement register. 18433859Sml29623 */ 18443859Sml29623 anar.value = 0; 18453859Sml29623 anar.bits.selector = 1; 18463859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 18473859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 18483859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 18493859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 18503859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 18513859Sml29623 anar.bits.cap_asmpause = 0; 18523859Sml29623 anar.bits.cap_pause = 0; 18533859Sml29623 if (param_arr[param_anar_1000fdx].value || 18543859Sml29623 param_arr[param_anar_100fdx].value || 18553859Sml29623 param_arr[param_anar_10fdx].value) { 18563859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 18573859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 18583859Sml29623 } 18593859Sml29623 18603859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18613859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 18623859Sml29623 != NXGE_OK) 18633859Sml29623 goto fail; 18643859Sml29623 if (bmsr.bits.extend_status) { 18653859Sml29623 gcr.value = 0; 18663859Sml29623 gcr.bits.ms_mode_en = 18673859Sml29623 param_arr[param_master_cfg_enable].value; 18683859Sml29623 gcr.bits.master = 18693859Sml29623 param_arr[param_master_cfg_value].value; 18703859Sml29623 gcr.bits.link_1000fdx = 18713859Sml29623 param_arr[param_anar_1000fdx].value; 18723859Sml29623 gcr.bits.link_1000hdx = 18733859Sml29623 param_arr[param_anar_1000hdx].value; 18743859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18753859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 18763859Sml29623 != NXGE_OK) 18773859Sml29623 goto fail; 18783859Sml29623 } 18793859Sml29623 18803859Sml29623 bmcr.bits.enable_autoneg = 1; 18813859Sml29623 bmcr.bits.restart_autoneg = 1; 18823859Sml29623 18833859Sml29623 } else { 18843859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 18853859Sml29623 bmcr.bits.speed_1000_sel = 18863859Sml29623 param_arr[param_anar_1000fdx].value | 18873859Sml29623 param_arr[param_anar_1000hdx].value; 18883859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 18893859Sml29623 (param_arr[param_anar_100fdx].value | 18903859Sml29623 param_arr[param_anar_100hdx].value); 18913859Sml29623 if (bmcr.bits.speed_1000_sel) { 18923859Sml29623 statsp->mac_stats.link_speed = 1000; 18933859Sml29623 gcr.value = 0; 18943859Sml29623 gcr.bits.ms_mode_en = 18953859Sml29623 param_arr[param_master_cfg_enable].value; 18963859Sml29623 gcr.bits.master = 18973859Sml29623 param_arr[param_master_cfg_value].value; 18983859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18993859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 19003859Sml29623 gcr.value)) 19013859Sml29623 != NXGE_OK) 19023859Sml29623 goto fail; 19033859Sml29623 if (param_arr[param_anar_1000fdx].value) { 19043859Sml29623 bmcr.bits.duplex_mode = 1; 19053859Sml29623 statsp->mac_stats.link_duplex = 2; 19063859Sml29623 } else 19073859Sml29623 statsp->mac_stats.link_duplex = 1; 19083859Sml29623 } else if (bmcr.bits.speed_sel) { 19093859Sml29623 statsp->mac_stats.link_speed = 100; 19103859Sml29623 if (param_arr[param_anar_100fdx].value) { 19113859Sml29623 bmcr.bits.duplex_mode = 1; 19123859Sml29623 statsp->mac_stats.link_duplex = 2; 19133859Sml29623 } else 19143859Sml29623 statsp->mac_stats.link_duplex = 1; 19153859Sml29623 } else { 19163859Sml29623 statsp->mac_stats.link_speed = 10; 19173859Sml29623 if (param_arr[param_anar_10fdx].value) { 19183859Sml29623 bmcr.bits.duplex_mode = 1; 19193859Sml29623 statsp->mac_stats.link_duplex = 2; 19203859Sml29623 } else 19213859Sml29623 statsp->mac_stats.link_duplex = 1; 19223859Sml29623 } 19233859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 19243859Sml29623 statsp->mac_stats.link_asmpause = 19253859Sml29623 statsp->mac_stats.cap_asmpause; 19263859Sml29623 statsp->mac_stats.link_pause = 19273859Sml29623 statsp->mac_stats.cap_pause; 19283859Sml29623 } 19293859Sml29623 19303859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 19313859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 19323859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 19333859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 19343859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 19353859Sml29623 gcr.value = 0; 19363859Sml29623 gcr.bits.ms_mode_en = 1; 19373859Sml29623 gcr.bits.master = 1; 19383859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 19393859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 19403859Sml29623 gcr.value)) 19413859Sml29623 != NXGE_OK) 19423859Sml29623 goto fail; 19433859Sml29623 bmcr.value = 0; 19443859Sml29623 bmcr.bits.speed_1000_sel = 1; 19453859Sml29623 statsp->mac_stats.link_speed = 1000; 19463859Sml29623 } else if (statsp->port_stats.lb_mode 19473859Sml29623 == nxge_lb_ext100) { 19483859Sml29623 /* BCM5464R 100mbps external loopback mode */ 19493859Sml29623 bmcr.value = 0; 19503859Sml29623 bmcr.bits.speed_sel = 1; 19513859Sml29623 bmcr.bits.duplex_mode = 1; 19523859Sml29623 statsp->mac_stats.link_speed = 100; 19533859Sml29623 } else if (statsp->port_stats.lb_mode 19543859Sml29623 == nxge_lb_ext10) { 19553859Sml29623 /* BCM5464R 10mbps external loopback mode */ 19563859Sml29623 bmcr.value = 0; 19573859Sml29623 bmcr.bits.duplex_mode = 1; 19583859Sml29623 statsp->mac_stats.link_speed = 10; 19593859Sml29623 } 19603859Sml29623 } 19613859Sml29623 } 19623859Sml29623 19633859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 19643859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 19653859Sml29623 bmcr.value)) != NXGE_OK) 19663859Sml29623 goto fail; 19673859Sml29623 19683859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19693859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 19703859Sml29623 goto fail; 19713859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 19723859Sml29623 19733859Sml29623 /* 19743859Sml29623 * Initialize the xcvr status kept in the context structure. 19753859Sml29623 */ 19763859Sml29623 nxgep->soft_bmsr.value = 0; 19773859Sml29623 19783859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19793859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 19803859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 19813859Sml29623 goto fail; 19823859Sml29623 19833859Sml29623 statsp->mac_stats.xcvr_inits++; 19843859Sml29623 nxgep->bmsr.value = 0; 19853859Sml29623 19863859Sml29623 fail: 19873859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 19883859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 19893859Sml29623 return (status); 19903859Sml29623 } 19913859Sml29623 19923859Sml29623 /* Read from a MII compliant register */ 19933859Sml29623 19943859Sml29623 nxge_status_t 19953859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 19963859Sml29623 uint16_t *value) 19973859Sml29623 { 19983859Sml29623 npi_status_t rs = NPI_SUCCESS; 19993859Sml29623 20003859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 20013859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 20023859Sml29623 20033859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 20043859Sml29623 20053859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 20063859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 20073859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 20083859Sml29623 goto fail; 20093859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 20103859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 20113859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 20123859Sml29623 goto fail; 20133859Sml29623 } else 20143859Sml29623 goto fail; 20153859Sml29623 20163859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 20173859Sml29623 20183859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 20193859Sml29623 "xcvr_reg<%d> value=0x%x", 20203859Sml29623 xcvr_portn, xcvr_reg, *value)); 20213859Sml29623 return (NXGE_OK); 20223859Sml29623 fail: 20233859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 20243859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20253859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 20263859Sml29623 xcvr_portn)); 20273859Sml29623 20283859Sml29623 return (NXGE_ERROR | rs); 20293859Sml29623 } 20303859Sml29623 20313859Sml29623 /* Write to a MII compliant Register */ 20323859Sml29623 20333859Sml29623 nxge_status_t 20343859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 20353859Sml29623 uint16_t value) 20363859Sml29623 { 20373859Sml29623 npi_status_t rs = NPI_SUCCESS; 20383859Sml29623 20393859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 20403859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 20413859Sml29623 value)); 20423859Sml29623 20433859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 20443859Sml29623 20453859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 20463859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 20473859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 20483859Sml29623 goto fail; 20493859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 20503859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 20513859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 20523859Sml29623 goto fail; 20533859Sml29623 } else 20543859Sml29623 goto fail; 20553859Sml29623 20563859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 20573859Sml29623 20583859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 20593859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 20603859Sml29623 return (NXGE_OK); 20613859Sml29623 fail: 20623859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 20633859Sml29623 20643859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20653859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 20663859Sml29623 xcvr_portn)); 20673859Sml29623 20683859Sml29623 return (NXGE_ERROR | rs); 20693859Sml29623 } 20703859Sml29623 20713859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 20723859Sml29623 20733859Sml29623 nxge_status_t 20743859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 20753859Sml29623 uint16_t xcvr_reg, uint16_t *value) 20763859Sml29623 { 20773859Sml29623 npi_status_t rs = NPI_SUCCESS; 20783859Sml29623 20793859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 20803859Sml29623 xcvr_portn)); 20813859Sml29623 20823859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 20833859Sml29623 20843859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 20853859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 20863859Sml29623 goto fail; 20873859Sml29623 20883859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 20893859Sml29623 20903859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 20913859Sml29623 xcvr_portn)); 20923859Sml29623 return (NXGE_OK); 20933859Sml29623 fail: 20943859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 20953859Sml29623 20963859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 20973859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 20983859Sml29623 xcvr_portn)); 20993859Sml29623 21003859Sml29623 return (NXGE_ERROR | rs); 21013859Sml29623 } 21023859Sml29623 21033859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 21043859Sml29623 21053859Sml29623 nxge_status_t 21063859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 21073859Sml29623 uint16_t xcvr_reg, uint16_t value) 21083859Sml29623 { 21093859Sml29623 npi_status_t rs = NPI_SUCCESS; 21103859Sml29623 21113859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 21123859Sml29623 xcvr_portn)); 21133859Sml29623 21143859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 21153859Sml29623 21163859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 21173859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 21183859Sml29623 goto fail; 21193859Sml29623 21203859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 21213859Sml29623 21223859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 21233859Sml29623 xcvr_portn)); 21243859Sml29623 return (NXGE_OK); 21253859Sml29623 fail: 21263859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 21273859Sml29623 21283859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 21293859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 21303859Sml29623 xcvr_portn)); 21313859Sml29623 21323859Sml29623 return (NXGE_ERROR | rs); 21333859Sml29623 } 21343859Sml29623 21353859Sml29623 21363859Sml29623 /* Check MII to see if there is any link status change */ 21373859Sml29623 21383859Sml29623 nxge_status_t 21393859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 21403859Sml29623 nxge_link_state_t *link_up) 21413859Sml29623 { 21423859Sml29623 p_nxge_param_t param_arr; 21433859Sml29623 p_nxge_stats_t statsp; 21443859Sml29623 p_mii_regs_t mii_regs; 21453859Sml29623 p_mii_bmsr_t soft_bmsr; 21463859Sml29623 mii_anar_t anar; 21473859Sml29623 mii_anlpar_t anlpar; 21483859Sml29623 mii_anar_t an_common; 21493859Sml29623 mii_aner_t aner; 21503859Sml29623 mii_gsr_t gsr; 21513859Sml29623 nxge_status_t status = NXGE_OK; 21523859Sml29623 21533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 21543859Sml29623 21553859Sml29623 mii_regs = NULL; 21563859Sml29623 param_arr = nxgep->param_arr; 21573859Sml29623 statsp = nxgep->statsp; 21583859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 21593859Sml29623 *link_up = LINK_NO_CHANGE; 21603859Sml29623 21613859Sml29623 if (bmsr_ints.bits.link_status) { 21623859Sml29623 if (bmsr.bits.link_status) { 21633859Sml29623 soft_bmsr->bits.link_status = 1; 21643859Sml29623 } else { 21653859Sml29623 statsp->mac_stats.link_up = 0; 21663859Sml29623 soft_bmsr->bits.link_status = 0; 21673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 21683859Sml29623 "Link down cable problem")); 21693859Sml29623 *link_up = LINK_IS_DOWN; 21703859Sml29623 } 21713859Sml29623 } 21723859Sml29623 21733859Sml29623 if (param_arr[param_autoneg].value) { 21743859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 21753859Sml29623 if (bmsr.bits.auto_neg_complete) 21763859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 21773859Sml29623 else 21783859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 21793859Sml29623 } 21803859Sml29623 if (soft_bmsr->bits.link_status == 0) { 21813859Sml29623 statsp->mac_stats.link_T4 = 0; 21823859Sml29623 statsp->mac_stats.link_speed = 0; 21833859Sml29623 statsp->mac_stats.link_duplex = 0; 21843859Sml29623 statsp->mac_stats.link_asmpause = 0; 21853859Sml29623 statsp->mac_stats.link_pause = 0; 21863859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 21873859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 21883859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 21893859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 21903859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 21913859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 21923859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 21933859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 21943859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 21953859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 21963859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 21973859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 21983859Sml29623 } 21993859Sml29623 } else 22003859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 22013859Sml29623 22023859Sml29623 if ((bmsr_ints.bits.link_status || 22033859Sml29623 bmsr_ints.bits.auto_neg_complete) && 22043859Sml29623 soft_bmsr->bits.link_status && 22053859Sml29623 soft_bmsr->bits.auto_neg_complete) { 22063859Sml29623 statsp->mac_stats.link_up = 1; 22073859Sml29623 if (param_arr[param_autoneg].value) { 22083859Sml29623 if ((status = nxge_mii_read(nxgep, 22093859Sml29623 statsp->mac_stats.xcvr_portn, 22103859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 22113859Sml29623 &anar.value)) != NXGE_OK) 22123859Sml29623 goto fail; 22133859Sml29623 if ((status = nxge_mii_read(nxgep, 22143859Sml29623 statsp->mac_stats.xcvr_portn, 22153859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 22163859Sml29623 &anlpar.value)) != NXGE_OK) 22173859Sml29623 goto fail; 22183859Sml29623 if ((status = nxge_mii_read(nxgep, 22193859Sml29623 statsp->mac_stats.xcvr_portn, 22203859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 22213859Sml29623 &aner.value)) != NXGE_OK) 22223859Sml29623 goto fail; 22233859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 22243859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 22253859Sml29623 statsp->mac_stats.lp_cap_100fdx = 22263859Sml29623 anlpar.bits.cap_100fdx; 22273859Sml29623 statsp->mac_stats.lp_cap_100hdx = 22283859Sml29623 anlpar.bits.cap_100hdx; 22293859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 22303859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 22313859Sml29623 statsp->mac_stats.lp_cap_asmpause = 22323859Sml29623 anlpar.bits.cap_asmpause; 22333859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 22343859Sml29623 an_common.value = anar.value & anlpar.value; 22353859Sml29623 if (param_arr[param_anar_1000fdx].value || 22363859Sml29623 param_arr[param_anar_1000hdx].value) { 22373859Sml29623 if ((status = nxge_mii_read(nxgep, 22383859Sml29623 statsp->mac_stats.xcvr_portn, 22393859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 22403859Sml29623 &gsr.value)) 22413859Sml29623 != NXGE_OK) 22423859Sml29623 goto fail; 22433859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 22443859Sml29623 gsr.bits.link_1000fdx; 22453859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 22463859Sml29623 gsr.bits.link_1000hdx; 22473859Sml29623 if (param_arr[param_anar_1000fdx].value && 22483859Sml29623 gsr.bits.link_1000fdx) { 22493859Sml29623 statsp->mac_stats.link_speed = 1000; 22503859Sml29623 statsp->mac_stats.link_duplex = 2; 22513859Sml29623 } else if ( 22523859Sml29623 param_arr[param_anar_1000hdx].value && 22533859Sml29623 gsr.bits.link_1000hdx) { 22543859Sml29623 statsp->mac_stats.link_speed = 1000; 22553859Sml29623 statsp->mac_stats.link_duplex = 1; 22563859Sml29623 } 22573859Sml29623 } 22583859Sml29623 if ((an_common.value != 0) && 22593859Sml29623 !(statsp->mac_stats.link_speed)) { 22603859Sml29623 if (an_common.bits.cap_100T4) { 22613859Sml29623 statsp->mac_stats.link_T4 = 1; 22623859Sml29623 statsp->mac_stats.link_speed = 100; 22633859Sml29623 statsp->mac_stats.link_duplex = 1; 22643859Sml29623 } else if (an_common.bits.cap_100fdx) { 22653859Sml29623 statsp->mac_stats.link_speed = 100; 22663859Sml29623 statsp->mac_stats.link_duplex = 2; 22673859Sml29623 } else if (an_common.bits.cap_100hdx) { 22683859Sml29623 statsp->mac_stats.link_speed = 100; 22693859Sml29623 statsp->mac_stats.link_duplex = 1; 22703859Sml29623 } else if (an_common.bits.cap_10fdx) { 22713859Sml29623 statsp->mac_stats.link_speed = 10; 22723859Sml29623 statsp->mac_stats.link_duplex = 2; 22733859Sml29623 } else if (an_common.bits.cap_10hdx) { 22743859Sml29623 statsp->mac_stats.link_speed = 10; 22753859Sml29623 statsp->mac_stats.link_duplex = 1; 22763859Sml29623 } else { 22773859Sml29623 goto fail; 22783859Sml29623 } 22793859Sml29623 } 22803859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 22813859Sml29623 statsp->mac_stats.link_asmpause = 22823859Sml29623 an_common.bits.cap_asmpause; 22833859Sml29623 if (statsp->mac_stats.link_asmpause) 22843859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 22853859Sml29623 (statsp->mac_stats.lp_cap_pause 22863859Sml29623 == 1)) 22873859Sml29623 statsp->mac_stats.link_pause 22883859Sml29623 = 0; 22893859Sml29623 else 22903859Sml29623 statsp->mac_stats.link_pause 22913859Sml29623 = 1; 22923859Sml29623 else 22933859Sml29623 statsp->mac_stats.link_pause = 22943859Sml29623 an_common.bits.cap_pause; 22953859Sml29623 } 22963859Sml29623 } 22973859Sml29623 *link_up = LINK_IS_UP; 22983859Sml29623 } 22993859Sml29623 23003859Sml29623 if (nxgep->link_notify) { 23013859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 23023859Sml29623 LINK_IS_DOWN); 23033859Sml29623 nxgep->link_notify = B_FALSE; 23043859Sml29623 } 23053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 23063859Sml29623 return (NXGE_OK); 23073859Sml29623 fail: 23083859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23093859Sml29623 "nxge_mii_check: Unable to check MII")); 23103859Sml29623 return (status); 23113859Sml29623 } 23123859Sml29623 23133859Sml29623 /* Add a multicast address entry into the HW hash table */ 23143859Sml29623 23153859Sml29623 nxge_status_t 23163859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 23173859Sml29623 { 23183859Sml29623 uint32_t mchash; 23193859Sml29623 p_hash_filter_t hash_filter; 23203859Sml29623 uint16_t hash_bit; 23213859Sml29623 boolean_t rx_init = B_FALSE; 23223859Sml29623 uint_t j; 23233859Sml29623 nxge_status_t status = NXGE_OK; 23243859Sml29623 23253859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 23263859Sml29623 23273859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 23283859Sml29623 mchash = crc32_mchash(addrp); 23293859Sml29623 if (nxgep->hash_filter == NULL) { 23303859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 23313859Sml29623 "Allocating hash filter storage.")); 23323859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 23333859Sml29623 KM_SLEEP); 23343859Sml29623 } 23353859Sml29623 hash_filter = nxgep->hash_filter; 23363859Sml29623 j = mchash / HASH_REG_WIDTH; 23373859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 23383859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 23393859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 23403859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 23413859Sml29623 hash_filter->hash_ref_cnt++; 23423859Sml29623 rx_init = B_TRUE; 23433859Sml29623 } 23443859Sml29623 if (rx_init) { 23453859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 23463859Sml29623 goto fail; 23473859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 23483859Sml29623 goto fail; 23493859Sml29623 } 23503859Sml29623 23513859Sml29623 RW_EXIT(&nxgep->filter_lock); 23523859Sml29623 23533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 23543859Sml29623 23553859Sml29623 return (NXGE_OK); 23563859Sml29623 fail: 23573859Sml29623 RW_EXIT(&nxgep->filter_lock); 23583859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 23593859Sml29623 "Unable to add multicast address")); 23603859Sml29623 return (status); 23613859Sml29623 } 23623859Sml29623 23633859Sml29623 /* Remove a multicast address entry from the HW hash table */ 23643859Sml29623 23653859Sml29623 nxge_status_t 23663859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 23673859Sml29623 { 23683859Sml29623 uint32_t mchash; 23693859Sml29623 p_hash_filter_t hash_filter; 23703859Sml29623 uint16_t hash_bit; 23713859Sml29623 boolean_t rx_init = B_FALSE; 23723859Sml29623 uint_t j; 23733859Sml29623 nxge_status_t status = NXGE_OK; 23743859Sml29623 23753859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 23763859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 23773859Sml29623 mchash = crc32_mchash(addrp); 23783859Sml29623 if (nxgep->hash_filter == NULL) { 23793859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 23803859Sml29623 "Hash filter already de_allocated.")); 23813859Sml29623 RW_EXIT(&nxgep->filter_lock); 23823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 23833859Sml29623 return (NXGE_OK); 23843859Sml29623 } 23853859Sml29623 hash_filter = nxgep->hash_filter; 23863859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 23873859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 23883859Sml29623 j = mchash / HASH_REG_WIDTH; 23893859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 23903859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 23913859Sml29623 hash_filter->hash_ref_cnt--; 23923859Sml29623 rx_init = B_TRUE; 23933859Sml29623 } 23943859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 23953859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 23963859Sml29623 "De-allocating hash filter storage.")); 23973859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 23983859Sml29623 nxgep->hash_filter = NULL; 23993859Sml29623 } 24003859Sml29623 24013859Sml29623 if (rx_init) { 24023859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 24033859Sml29623 goto fail; 24043859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 24053859Sml29623 goto fail; 24063859Sml29623 } 24073859Sml29623 RW_EXIT(&nxgep->filter_lock); 24083859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 24093859Sml29623 24103859Sml29623 return (NXGE_OK); 24113859Sml29623 fail: 24123859Sml29623 RW_EXIT(&nxgep->filter_lock); 24133859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 24143859Sml29623 "Unable to remove multicast address")); 24153859Sml29623 24163859Sml29623 return (status); 24173859Sml29623 } 24183859Sml29623 24193859Sml29623 /* Set MAC address into MAC address HW registers */ 24203859Sml29623 24213859Sml29623 nxge_status_t 24223859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 24233859Sml29623 { 24243859Sml29623 nxge_status_t status = NXGE_OK; 24253859Sml29623 24263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 24273859Sml29623 24283859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 24293859Sml29623 /* 24303859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 24313859Sml29623 */ 24323859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 24333859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 24343859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 24353859Sml29623 goto nxge_set_mac_addr_exit; 24363859Sml29623 } 24373859Sml29623 nxgep->ouraddr = *addrp; 24383859Sml29623 /* 24393859Sml29623 * Set new interface local address and re-init device. 24403859Sml29623 * This is destructive to any other streams attached 24413859Sml29623 * to this device. 24423859Sml29623 */ 24433859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 24443859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 24453859Sml29623 goto fail; 24463859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 24473859Sml29623 goto fail; 24483859Sml29623 24493859Sml29623 RW_EXIT(&nxgep->filter_lock); 24503859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 24513859Sml29623 goto nxge_set_mac_addr_end; 24523859Sml29623 nxge_set_mac_addr_exit: 24533859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 24543859Sml29623 nxge_set_mac_addr_end: 24553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 24563859Sml29623 24573859Sml29623 return (NXGE_OK); 24583859Sml29623 fail: 24593859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 24603859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 24613859Sml29623 "Unable to set mac address")); 24623859Sml29623 return (status); 24633859Sml29623 } 24643859Sml29623 24653859Sml29623 /* Check status of MII (MIF or PCS) link */ 24663859Sml29623 24673859Sml29623 nxge_status_t 24683859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 24693859Sml29623 { 24703859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 24713859Sml29623 mii_anlpar_t anlpar; 24723859Sml29623 mii_gsr_t gsr; 24733859Sml29623 p_mii_regs_t mii_regs; 24743859Sml29623 nxge_status_t status = NXGE_OK; 24753859Sml29623 uint8_t portn; 24763859Sml29623 nxge_link_state_t link_up; 24773859Sml29623 24783859Sml29623 portn = nxgep->mac.portnum; 24793859Sml29623 24803859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 24813859Sml29623 portn)); 24823859Sml29623 24833859Sml29623 mii_regs = NULL; 24843859Sml29623 24853859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 24863859Sml29623 24873859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 24883859Sml29623 goto nxge_check_mii_link_exit; 24893859Sml29623 24903859Sml29623 if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 24913859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 24923859Sml29623 &bmsr_data.value)) != NXGE_OK) 24933859Sml29623 goto fail; 24943859Sml29623 24953859Sml29623 if (nxgep->param_arr[param_autoneg].value) { 24963859Sml29623 if ((status = nxge_mii_read(nxgep, 24973859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 24983859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 24993859Sml29623 &gsr.value)) != NXGE_OK) 25003859Sml29623 goto fail; 25013859Sml29623 if ((status = nxge_mii_read(nxgep, 25023859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 25033859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 25043859Sml29623 &anlpar.value)) != NXGE_OK) 25053859Sml29623 goto fail; 25063859Sml29623 if (nxgep->statsp->mac_stats.link_up && 25073859Sml29623 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 25083859Sml29623 gsr.bits.link_1000fdx) || 25093859Sml29623 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 25103859Sml29623 gsr.bits.link_1000hdx) || 25113859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 25123859Sml29623 anlpar.bits.cap_100T4) || 25133859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 25143859Sml29623 anlpar.bits.cap_100fdx) || 25153859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 25163859Sml29623 anlpar.bits.cap_100hdx) || 25173859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 25183859Sml29623 anlpar.bits.cap_10fdx) || 25193859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 25203859Sml29623 anlpar.bits.cap_10hdx))) { 25213859Sml29623 bmsr_data.bits.link_status = 0; 25223859Sml29623 } 25233859Sml29623 } 25243859Sml29623 25253859Sml29623 /* Workaround for link down issue */ 25263859Sml29623 if (bmsr_data.value == 0) { 25273859Sml29623 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 25283859Sml29623 goto nxge_check_mii_link_exit; 25293859Sml29623 } 25303859Sml29623 25313859Sml29623 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 25323859Sml29623 nxgep->bmsr.value = bmsr_data.value; 25333859Sml29623 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up)) 25343859Sml29623 != NXGE_OK) 25353859Sml29623 goto fail; 25363859Sml29623 25373859Sml29623 nxge_check_mii_link_exit: 25383859Sml29623 RW_EXIT(&nxgep->filter_lock); 25393859Sml29623 if (link_up == LINK_IS_UP) { 25403859Sml29623 nxge_link_is_up(nxgep); 25413859Sml29623 } else if (link_up == LINK_IS_DOWN) { 25423859Sml29623 nxge_link_is_down(nxgep); 25433859Sml29623 } 25443859Sml29623 25453859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 25463859Sml29623 25473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 25483859Sml29623 portn)); 25493859Sml29623 return (NXGE_OK); 25503859Sml29623 25513859Sml29623 fail: 25523859Sml29623 RW_EXIT(&nxgep->filter_lock); 25533859Sml29623 25543859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 25553859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 25563859Sml29623 "nxge_check_mii_link: Failed to check link port<%d>", 25573859Sml29623 portn)); 25583859Sml29623 return (status); 25593859Sml29623 } 25603859Sml29623 25613859Sml29623 25623859Sml29623 /*ARGSUSED*/ 25633859Sml29623 nxge_status_t 25643859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 25653859Sml29623 { 25663859Sml29623 uint8_t portn; 25673859Sml29623 25683859Sml29623 nxge_status_t status = NXGE_OK; 25693859Sml29623 boolean_t link_up; 25703859Sml29623 25713859Sml29623 portn = nxgep->mac.portnum; 25723859Sml29623 25733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 25743859Sml29623 portn)); 25753859Sml29623 25763859Sml29623 status = nxge_check_bcm8704_link(nxgep, &link_up); 25773859Sml29623 25783859Sml29623 if (status != NXGE_OK) 25793859Sml29623 goto fail; 25803859Sml29623 25813859Sml29623 if (link_up) { 25823859Sml29623 if (nxgep->link_notify || 25833859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 25843859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 25853859Sml29623 goto fail; 25863859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 25873859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 25883859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 25893859Sml29623 25903859Sml29623 nxge_link_is_up(nxgep); 25913859Sml29623 nxgep->link_notify = B_FALSE; 25923859Sml29623 } 25933859Sml29623 } else { 25943859Sml29623 if (nxgep->link_notify || 25953859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 25963859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 25973859Sml29623 goto fail; 25983859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 25993859Sml29623 "Link down cable problem")); 26003859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 26013859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 26023859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 26033859Sml29623 26043859Sml29623 nxge_link_is_down(nxgep); 26053859Sml29623 nxgep->link_notify = B_FALSE; 26063859Sml29623 } 26073859Sml29623 } 26083859Sml29623 26093859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 26103859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 26113859Sml29623 portn)); 26123859Sml29623 return (NXGE_OK); 26133859Sml29623 26143859Sml29623 fail: 26153859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 26163859Sml29623 "nxge_check_10g_link: Failed to check link port<%d>", 26173859Sml29623 portn)); 26183859Sml29623 return (status); 26193859Sml29623 } 26203859Sml29623 26213859Sml29623 26223859Sml29623 /* Declare link down */ 26233859Sml29623 26243859Sml29623 void 26253859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 26263859Sml29623 { 26273859Sml29623 p_nxge_stats_t statsp; 26283859Sml29623 char link_stat_msg[64]; 26293859Sml29623 26303859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 26313859Sml29623 26323859Sml29623 statsp = nxgep->statsp; 2633*4185Sspeer (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 26343859Sml29623 statsp->mac_stats.xcvr_portn); 26353859Sml29623 2636*4185Sspeer if (nxge_no_msg == B_FALSE) { 2637*4185Sspeer NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 2638*4185Sspeer } 2639*4185Sspeer 26403859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 26413859Sml29623 26423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 26433859Sml29623 } 26443859Sml29623 26453859Sml29623 /* Declare link up */ 26463859Sml29623 26473859Sml29623 void 26483859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 26493859Sml29623 { 26503859Sml29623 p_nxge_stats_t statsp; 26513859Sml29623 char link_stat_msg[64]; 26523859Sml29623 uint32_t val; 26533859Sml29623 26543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 26553859Sml29623 26563859Sml29623 statsp = nxgep->statsp; 2657*4185Sspeer (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 26583859Sml29623 statsp->mac_stats.xcvr_portn, 26593859Sml29623 statsp->mac_stats.link_speed); 26603859Sml29623 26613859Sml29623 if (statsp->mac_stats.link_T4) 26623859Sml29623 (void) strcat(link_stat_msg, "T4"); 26633859Sml29623 else if (statsp->mac_stats.link_duplex == 2) 26643859Sml29623 (void) strcat(link_stat_msg, "full duplex"); 26653859Sml29623 else 26663859Sml29623 (void) strcat(link_stat_msg, "half duplex"); 26673859Sml29623 26683859Sml29623 (void) nxge_xif_init(nxgep); 26693859Sml29623 26703859Sml29623 /* Clean up symbol errors incurred during link transition */ 26713859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 26723859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 26733859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 26743859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 26753859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 26763859Sml29623 } 26773859Sml29623 2678*4185Sspeer if (nxge_no_msg == B_FALSE) { 2679*4185Sspeer NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 2680*4185Sspeer } 2681*4185Sspeer 26823859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 26833859Sml29623 26843859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 26853859Sml29623 } 26863859Sml29623 26873859Sml29623 /* 26883859Sml29623 * Calculate the bit in the multicast address filter 26893859Sml29623 * that selects the given * address. 26903859Sml29623 * Note: For GEM, the last 8-bits are used. 26913859Sml29623 */ 26923859Sml29623 uint32_t 26933859Sml29623 crc32_mchash(p_ether_addr_t addr) 26943859Sml29623 { 26953859Sml29623 uint8_t *cp; 26963859Sml29623 uint32_t crc; 26973859Sml29623 uint32_t c; 26983859Sml29623 int byte; 26993859Sml29623 int bit; 27003859Sml29623 27013859Sml29623 cp = (uint8_t *)addr; 27023859Sml29623 crc = (uint32_t)0xffffffff; 27033859Sml29623 for (byte = 0; byte < 6; byte++) { 27043859Sml29623 c = (uint32_t)cp[byte]; 27053859Sml29623 for (bit = 0; bit < 8; bit++) { 27063859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 27073859Sml29623 crc = (crc >> 1)^0xedb88320; 27083859Sml29623 else 27093859Sml29623 crc = (crc >> 1); 27103859Sml29623 c >>= 1; 27113859Sml29623 } 27123859Sml29623 } 27133859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 27143859Sml29623 } 27153859Sml29623 27163859Sml29623 /* Reset serdes */ 27173859Sml29623 27183859Sml29623 nxge_status_t 27193859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 27203859Sml29623 { 27213859Sml29623 npi_handle_t handle; 27223859Sml29623 27233859Sml29623 handle = nxgep->npi_handle; 27243859Sml29623 27253859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 27263859Sml29623 drv_usecwait(500); 27273859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 27283859Sml29623 27293859Sml29623 return (NXGE_OK); 27303859Sml29623 } 27313859Sml29623 27323859Sml29623 /* Monitor link status using interrupt or polling */ 27333859Sml29623 27343859Sml29623 nxge_status_t 27353859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 27363859Sml29623 { 27373859Sml29623 nxge_status_t status = NXGE_OK; 27383859Sml29623 27393859Sml29623 /* 27403859Sml29623 * Make sure that we don't check the link if this happen to 27413859Sml29623 * be not port0 or 1 and it is not BMAC port. 27423859Sml29623 */ 27433859Sml29623 if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1)) 27443859Sml29623 return (NXGE_OK); 27453859Sml29623 27463859Sml29623 if (nxgep->statsp == NULL) { 27473859Sml29623 /* stats has not been allocated. */ 27483859Sml29623 return (NXGE_OK); 27493859Sml29623 } 27503859Sml29623 /* Don't check link if we're not in internal loopback mode */ 27513859Sml29623 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 27523859Sml29623 return (NXGE_OK); 27533859Sml29623 27543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 27553859Sml29623 "==> nxge_link_monitor port<%d> enable=%d", 27563859Sml29623 nxgep->mac.portnum, enable)); 27573859Sml29623 if (enable == LINK_MONITOR_START) { 27583859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 27593859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 27603859Sml29623 != NXGE_OK) 27613859Sml29623 goto fail; 27623859Sml29623 } else { 27633859Sml29623 switch (nxgep->mac.portmode) { 27643859Sml29623 case PORT_10G_FIBER: 27653859Sml29623 nxgep->nxge_link_poll_timerid = timeout( 27663859Sml29623 (fptrv_t)nxge_check_10g_link, 27673859Sml29623 nxgep, 27683859Sml29623 drv_usectohz(1000 * 1000)); 27693859Sml29623 break; 27703859Sml29623 27713859Sml29623 case PORT_1G_COPPER: 27723859Sml29623 case PORT_1G_FIBER: 27733859Sml29623 nxgep->nxge_link_poll_timerid = timeout( 27743859Sml29623 (fptrv_t)nxge_check_mii_link, 27753859Sml29623 nxgep, 27763859Sml29623 drv_usectohz(1000 * 1000)); 27773859Sml29623 break; 27783859Sml29623 default: 27793859Sml29623 ; 27803859Sml29623 } 27813859Sml29623 } 27823859Sml29623 } else { 27833859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 27843859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 27853859Sml29623 != NXGE_OK) 27863859Sml29623 goto fail; 27873859Sml29623 } else { 27883859Sml29623 if (nxgep->nxge_link_poll_timerid != 0) { 27893859Sml29623 (void) untimeout(nxgep->nxge_link_poll_timerid); 27903859Sml29623 nxgep->nxge_link_poll_timerid = 0; 27913859Sml29623 } 27923859Sml29623 } 27933859Sml29623 } 27943859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 27953859Sml29623 "<== nxge_link_monitor port<%d> enable=%d", 27963859Sml29623 nxgep->mac.portnum, enable)); 27973859Sml29623 return (NXGE_OK); 27983859Sml29623 fail: 27993859Sml29623 return (status); 28003859Sml29623 } 28013859Sml29623 28023859Sml29623 /* Set promiscous mode */ 28033859Sml29623 28043859Sml29623 nxge_status_t 28053859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 28063859Sml29623 { 28073859Sml29623 nxge_status_t status = NXGE_OK; 28083859Sml29623 28093859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 28103859Sml29623 "==> nxge_set_promisc: on %d", on)); 28113859Sml29623 28123859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 28133859Sml29623 28143859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 28153859Sml29623 28163859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 28173859Sml29623 goto fail; 28183859Sml29623 } 28193859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 28203859Sml29623 goto fail; 28213859Sml29623 } 28223859Sml29623 28233859Sml29623 RW_EXIT(&nxgep->filter_lock); 28243859Sml29623 28253859Sml29623 if (on) 28263859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 28273859Sml29623 else 28283859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 28293859Sml29623 28303859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 28313859Sml29623 28323859Sml29623 return (NXGE_OK); 28333859Sml29623 fail: 28343859Sml29623 RW_EXIT(&nxgep->filter_lock); 28353859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 28363859Sml29623 "Unable to set promisc (%d)", on)); 28373859Sml29623 28383859Sml29623 return (status); 28393859Sml29623 } 28403859Sml29623 28413859Sml29623 /*ARGSUSED*/ 28423859Sml29623 uint_t 28433859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 28443859Sml29623 { 28453859Sml29623 #ifdef NXGE_DEBUG 28463859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 28473859Sml29623 #endif 28483859Sml29623 #if NXGE_MIF 28493859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 28503859Sml29623 uint32_t status; 28513859Sml29623 npi_handle_t handle; 28523859Sml29623 uint8_t portn; 28533859Sml29623 p_nxge_stats_t statsp; 28543859Sml29623 #endif 28553859Sml29623 28563859Sml29623 #ifdef NXGE_MIF 28573859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 28583859Sml29623 nxgep = ldvp->nxgep; 28593859Sml29623 } 28603859Sml29623 nxgep = ldvp->nxgep; 28613859Sml29623 #endif 28623859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 28633859Sml29623 28643859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 28653859Sml29623 return (DDI_INTR_CLAIMED); 28663859Sml29623 28673859Sml29623 mif_intr_fail: 28683859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 28693859Sml29623 return (DDI_INTR_UNCLAIMED); 28703859Sml29623 } 28713859Sml29623 28723859Sml29623 /*ARGSUSED*/ 28733859Sml29623 uint_t 28743859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 28753859Sml29623 { 28763859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 28773859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 28783859Sml29623 p_nxge_ldg_t ldgp; 28793859Sml29623 uint32_t status; 28803859Sml29623 npi_handle_t handle; 28813859Sml29623 uint8_t portn; 28823859Sml29623 p_nxge_stats_t statsp; 28833859Sml29623 npi_status_t rs = NPI_SUCCESS; 28843859Sml29623 28853859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 28863859Sml29623 nxgep = ldvp->nxgep; 28873859Sml29623 } 28883859Sml29623 28893859Sml29623 ldgp = ldvp->ldgp; 28903859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 28913859Sml29623 "group %d", ldgp->ldg)); 28923859Sml29623 28933859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 28943859Sml29623 /* 28953859Sml29623 * This interrupt handler is for a specific 28963859Sml29623 * mac port. 28973859Sml29623 */ 28983859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 28993859Sml29623 portn = nxgep->mac.portnum; 29003859Sml29623 29013859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 29023859Sml29623 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 29033859Sml29623 29043859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 29053859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 29063859Sml29623 (xmac_tx_iconfig_t *)&status); 29073859Sml29623 if (rs != NPI_SUCCESS) 29083859Sml29623 goto npi_fail; 29093859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 29103859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 29113859Sml29623 statsp->xmac_stats.tx_underflow_err++; 29123859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29133859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 29143859Sml29623 } 29153859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 29163859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 29173859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29183859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 29193859Sml29623 } 29203859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 29213859Sml29623 statsp->xmac_stats.tx_overflow_err++; 29223859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29233859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 29243859Sml29623 } 29253859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 29263859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 29273859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29283859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 29293859Sml29623 } 29303859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 29313859Sml29623 statsp->xmac_stats.tx_byte_cnt += 29323859Sml29623 XTXMAC_BYTE_CNT_MASK; 29333859Sml29623 } 29343859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 29353859Sml29623 statsp->xmac_stats.tx_frame_cnt += 29363859Sml29623 XTXMAC_FRM_CNT_MASK; 29373859Sml29623 } 29383859Sml29623 } 29393859Sml29623 29403859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 29413859Sml29623 (xmac_rx_iconfig_t *)&status); 29423859Sml29623 if (rs != NPI_SUCCESS) 29433859Sml29623 goto npi_fail; 29443859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 29453859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 29463859Sml29623 statsp->xmac_stats.rx_overflow_err++; 29473859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 29483859Sml29623 statsp->xmac_stats.rx_underflow_err++; 29493859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29503859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 29513859Sml29623 } 29523859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 29533859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 29543859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 29553859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29563859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 29573859Sml29623 } 29583859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 29593859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 29603859Sml29623 MAC_LEN_ER_CNT_MASK; 29613859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29623859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 29633859Sml29623 } 29643859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 29653859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 29663859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 29673859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 29683859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 29693859Sml29623 } 29703859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 29713859Sml29623 statsp->xmac_stats.rx_byte_cnt += 29723859Sml29623 XRXMAC_BT_CNT_MASK; 29733859Sml29623 } 29743859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 29753859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 29763859Sml29623 XRXMAC_HIST_CNT1_MASK; 29773859Sml29623 } 29783859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 29793859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 29803859Sml29623 XRXMAC_HIST_CNT2_MASK; 29813859Sml29623 } 29823859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 29833859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 29843859Sml29623 XRXMAC_HIST_CNT3_MASK; 29853859Sml29623 } 29863859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 29873859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 29883859Sml29623 XRXMAC_HIST_CNT4_MASK; 29893859Sml29623 } 29903859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 29913859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 29923859Sml29623 XRXMAC_HIST_CNT5_MASK; 29933859Sml29623 } 29943859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 29953859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 29963859Sml29623 XRXMAC_HIST_CNT6_MASK; 29973859Sml29623 } 29983859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 29993859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 30003859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 30013859Sml29623 } 30023859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 30033859Sml29623 statsp->xmac_stats.rx_mult_cnt += 30043859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 30053859Sml29623 } 30063859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 30073859Sml29623 statsp->xmac_stats.rx_frag_cnt += 30083859Sml29623 XRXMAC_FRAG_CNT_MASK; 30093859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30103859Sml29623 NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 30113859Sml29623 } 30123859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 30133859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 30143859Sml29623 XRXMAC_AL_ER_CNT_MASK; 30153859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30163859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 30173859Sml29623 } 30183859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 30193859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 30203859Sml29623 XMAC_LINK_FLT_CNT_MASK; 30213859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30223859Sml29623 NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 30233859Sml29623 } 30243859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 30253859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 30263859Sml29623 } 30273859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 30283859Sml29623 statsp->xmac_stats.rx_localfault_err++; 30293859Sml29623 } 30303859Sml29623 } 30313859Sml29623 30323859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 30333859Sml29623 (xmac_ctl_iconfig_t *)&status); 30343859Sml29623 if (rs != NPI_SUCCESS) 30353859Sml29623 goto npi_fail; 30363859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 30373859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 30383859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 30393859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 30403859Sml29623 statsp->xmac_stats.tx_pause_state++; 30413859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 30423859Sml29623 statsp->xmac_stats.tx_nopause_state++; 30433859Sml29623 } 30443859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 30453859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 30463859Sml29623 (bmac_tx_iconfig_t *)&status); 30473859Sml29623 if (rs != NPI_SUCCESS) 30483859Sml29623 goto npi_fail; 30493859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 30503859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 30513859Sml29623 statsp->bmac_stats.tx_underrun_err++; 30523859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30533859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 30543859Sml29623 } 30553859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 30563859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 30573859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30583859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 30593859Sml29623 } 30603859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 30613859Sml29623 statsp->bmac_stats.tx_byte_cnt += 30623859Sml29623 BTXMAC_BYTE_CNT_MASK; 30633859Sml29623 } 30643859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 30653859Sml29623 statsp->bmac_stats.tx_frame_cnt += 30663859Sml29623 BTXMAC_FRM_CNT_MASK; 30673859Sml29623 } 30683859Sml29623 } 30693859Sml29623 30703859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 30713859Sml29623 (bmac_rx_iconfig_t *)&status); 30723859Sml29623 if (rs != NPI_SUCCESS) 30733859Sml29623 goto npi_fail; 30743859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 30753859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 30763859Sml29623 statsp->bmac_stats.rx_overflow_err++; 30773859Sml29623 } 30783859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 30793859Sml29623 statsp->bmac_stats.rx_frame_cnt += 30803859Sml29623 RXMAC_FRM_CNT_MASK; 30813859Sml29623 } 30823859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 30833859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 30843859Sml29623 BMAC_CRC_ER_CNT_MASK; 30853859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30863859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 30873859Sml29623 } 30883859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 30893859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 30903859Sml29623 MAC_LEN_ER_CNT_MASK; 30913859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30923859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 30933859Sml29623 } 30943859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 30953859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 30963859Sml29623 BMAC_CD_VIO_CNT_MASK; 30973859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 30983859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 30993859Sml29623 } 31003859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 31013859Sml29623 statsp->bmac_stats.rx_byte_cnt += 31023859Sml29623 BRXMAC_BYTE_CNT_MASK; 31033859Sml29623 } 31043859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 31053859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 31063859Sml29623 BMAC_AL_ER_CNT_MASK; 31073859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31083859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 31093859Sml29623 } 31103859Sml29623 31113859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 31123859Sml29623 (bmac_ctl_iconfig_t *)&status); 31133859Sml29623 if (rs != NPI_SUCCESS) 31143859Sml29623 goto npi_fail; 31153859Sml29623 31163859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 31173859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 31183859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 31193859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 31203859Sml29623 statsp->bmac_stats.tx_pause_state++; 31213859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 31223859Sml29623 statsp->bmac_stats.tx_nopause_state++; 31233859Sml29623 } 31243859Sml29623 } 31253859Sml29623 31263859Sml29623 if (ldgp->nldvs == 1) { 31273859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 31283859Sml29623 B_TRUE, ldgp->ldg_timer); 31293859Sml29623 } 31303859Sml29623 31313859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 31323859Sml29623 return (DDI_INTR_CLAIMED); 31333859Sml29623 31343859Sml29623 npi_fail: 31353859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 31363859Sml29623 return (DDI_INTR_UNCLAIMED); 31373859Sml29623 } 31383859Sml29623 31393859Sml29623 nxge_status_t 31403859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 31413859Sml29623 { 31423859Sml29623 uint8_t phy_port_addr; 31433859Sml29623 nxge_status_t status = NXGE_OK; 31443859Sml29623 boolean_t rx_sig_ok; 31453859Sml29623 boolean_t pcs_blk_lock; 31463859Sml29623 boolean_t link_align; 31473859Sml29623 uint16_t val1, val2, val3; 31483859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 31493859Sml29623 uint16_t val_debug; 31503859Sml29623 uint16_t val; 31513859Sml29623 #endif 31523859Sml29623 31533859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 31543859Sml29623 31553859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 31563859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 31573859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 31583859Sml29623 if ((val_debug & ~0x200) != 0) { 31593859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 31603859Sml29623 nxgep->mac.portnum, val_debug); 31613859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 31623859Sml29623 &val_debug); 31633859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 31643859Sml29623 nxgep->mac.portnum, val_debug); 31653859Sml29623 } 31663859Sml29623 31673859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 31683859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 31693859Sml29623 if (val != 0) 31703859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 31713859Sml29623 31723859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 31733859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 31743859Sml29623 if (val != 0) 31753859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 31763859Sml29623 31773859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 31783859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 31793859Sml29623 if (val != 0) 31803859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 31813859Sml29623 #endif 31823859Sml29623 31833859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 31843859Sml29623 31853859Sml29623 /* Check Device 1 Register 0xA bit0 */ 31863859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 31873859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 31883859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 31893859Sml29623 &val1); 31903859Sml29623 if (status != NXGE_OK) 31913859Sml29623 goto fail; 31923859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 31933859Sml29623 31943859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 31953859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 31963859Sml29623 BCM8704_PCS_DEV_ADDR, 31973859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 31983859Sml29623 &val2)) != NPI_SUCCESS) 31993859Sml29623 goto fail; 32003859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 32013859Sml29623 32023859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 32033859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 32043859Sml29623 BCM8704_PHYXS_ADDR, 32053859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 32063859Sml29623 &val3); 32073859Sml29623 if (status != NXGE_OK) 32083859Sml29623 goto fail; 32093859Sml29623 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 32103859Sml29623 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 32113859Sml29623 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 32123859Sml29623 32133859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 32143859Sml29623 /* Temp workaround for link down issue */ 32153859Sml29623 if (pcs_blk_lock == B_FALSE) { 32163859Sml29623 if (val2 != 0x4) { 32173859Sml29623 pcs_blk_lock = B_TRUE; 32183859Sml29623 cmn_err(CE_NOTE, 32193859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 32203859Sml29623 "Reg 0x20 = 0x%x\n", 32213859Sml29623 nxgep->mac.portnum, val2); 32223859Sml29623 } 32233859Sml29623 } 32243859Sml29623 32253859Sml29623 if (link_align == B_FALSE) { 32263859Sml29623 if (val3 != 0x140f) { 32273859Sml29623 link_align = B_TRUE; 32283859Sml29623 cmn_err(CE_NOTE, 32293859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 32303859Sml29623 "Reg 0x18 = 0x%x\n", 32313859Sml29623 nxgep->mac.portnum, val3); 32323859Sml29623 } 32333859Sml29623 } 32343859Sml29623 32353859Sml29623 if (rx_sig_ok == B_FALSE) { 32363859Sml29623 if ((val2 == 0) || (val3 == 0)) { 32373859Sml29623 rx_sig_ok = B_TRUE; 32383859Sml29623 cmn_err(CE_NOTE, 32393859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 32403859Sml29623 nxgep->mac.portnum); 32413859Sml29623 } 32423859Sml29623 } 32433859Sml29623 #endif 32443859Sml29623 32453859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 32463859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 32473859Sml29623 32483859Sml29623 return (NXGE_OK); 32493859Sml29623 fail: 32503859Sml29623 return (status); 32513859Sml29623 } 32523859Sml29623 32533859Sml29623 32543859Sml29623 nxge_status_t 32553859Sml29623 nxge_get_xcvr_type(p_nxge_t nxgep) 32563859Sml29623 { 32573859Sml29623 nxge_status_t status = NXGE_OK; 3258*4185Sspeer char *phy_type; 32593859Sml29623 char *prop_val; 32603859Sml29623 3261*4185Sspeer if (nxgep->niu_type == N2_NIU) { 3262*4185Sspeer if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 3263*4185Sspeer "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 3264*4185Sspeer if (strcmp("xgf", prop_val) == 0) { 3265*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = 3266*4185Sspeer XPCS_XCVR; 3267*4185Sspeer nxgep->mac.portmode = PORT_10G_FIBER; 3268*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3269*4185Sspeer "10G Fiber Xcvr")); 3270*4185Sspeer } else if (strcmp("mif", prop_val) == 0) { 3271*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = 3272*4185Sspeer INT_MII_XCVR; 3273*4185Sspeer nxgep->mac.portmode = PORT_1G_COPPER; 3274*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3275*4185Sspeer "1G Copper Xcvr")); 3276*4185Sspeer } else if (strcmp("pcs", prop_val) == 0) { 3277*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3278*4185Sspeer nxgep->mac.portmode = PORT_1G_FIBER; 3279*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3280*4185Sspeer "1G Fiber Xcvr")); 3281*4185Sspeer } else if (strcmp("xgc", prop_val) == 0) { 3282*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = 3283*4185Sspeer XPCS_XCVR; 3284*4185Sspeer nxgep->mac.portmode = PORT_10G_COPPER; 3285*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3286*4185Sspeer "10G Copper Xcvr")); 3287*4185Sspeer } else { 3288*4185Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3289*4185Sspeer "Unknown phy-type: %s", prop_val)); 3290*4185Sspeer ddi_prop_free(prop_val); 3291*4185Sspeer return (NXGE_ERROR); 3292*4185Sspeer } 3293*4185Sspeer status = NXGE_OK; 3294*4185Sspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3295*4185Sspeer nxgep->dip, "phy-type", prop_val); 3296*4185Sspeer ddi_prop_free(prop_val); 3297*4185Sspeer return (status); 32983859Sml29623 } else { 32993859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3300*4185Sspeer "Exiting...phy-type property not found")); 33013859Sml29623 return (NXGE_ERROR); 33023859Sml29623 } 33033859Sml29623 } 3304*4185Sspeer 3305*4185Sspeer if (!nxgep->vpd_info.ver_valid) { 3306*4185Sspeer /* 3307*4185Sspeer * read the phy type from the SEEPROM - NCR registers 3308*4185Sspeer */ 3309*4185Sspeer status = nxge_espc_phy_type_get(nxgep); 3310*4185Sspeer if (status != NXGE_OK) 3311*4185Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3312*4185Sspeer "[%s] invalid...please update", 3313*4185Sspeer nxgep->vpd_info.ver)); 3314*4185Sspeer return (status); 3315*4185Sspeer } 3316*4185Sspeer 3317*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3318*4185Sspeer "Reading phy type from expansion ROM")); 3319*4185Sspeer /* 3320*4185Sspeer * Try to read the phy type from the vpd data read off the 3321*4185Sspeer * expansion ROM. 3322*4185Sspeer */ 3323*4185Sspeer phy_type = nxgep->vpd_info.phy_type; 3324*4185Sspeer if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') { 3325*4185Sspeer nxgep->mac.portmode = PORT_1G_COPPER; 3326*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3327*4185Sspeer } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 3328*4185Sspeer phy_type[2] == 'f') { 3329*4185Sspeer nxgep->mac.portmode = PORT_10G_FIBER; 3330*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3331*4185Sspeer } else if (phy_type[0] == 'p' && phy_type[1] == 'c' && 3332*4185Sspeer phy_type[2] == 's') { 3333*4185Sspeer nxgep->mac.portmode = PORT_1G_FIBER; 3334*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3335*4185Sspeer } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 3336*4185Sspeer phy_type[2] == 'c') { 3337*4185Sspeer nxgep->mac.portmode = PORT_10G_COPPER; 3338*4185Sspeer nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3339*4185Sspeer } else { 3340*4185Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3341*4185Sspeer "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3342*4185Sspeer phy_type[0], phy_type[1], phy_type[2])); 3343*4185Sspeer /* 3344*4185Sspeer * read the phy type from the SEEPROM - NCR registers 3345*4185Sspeer */ 3346*4185Sspeer status = nxge_espc_phy_type_get(nxgep); 3347*4185Sspeer if (status != NXGE_OK) 3348*4185Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3349*4185Sspeer "[%s] invalid...please update", 3350*4185Sspeer nxgep->vpd_info.ver)); 3351*4185Sspeer } 33523859Sml29623 33533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 33543859Sml29623 return (status); 33553859Sml29623 } 33563859Sml29623 33573859Sml29623 nxge_status_t 33583859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 33593859Sml29623 { 33603859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 33613859Sml29623 != NPI_SUCCESS) 33623859Sml29623 return (NXGE_ERROR); 33633859Sml29623 else 33643859Sml29623 return (NXGE_OK); 33653859Sml29623 } 33663859Sml29623 33673859Sml29623 nxge_status_t 33683859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 33693859Sml29623 { 33703859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 33713859Sml29623 != NPI_SUCCESS) 33723859Sml29623 return (NXGE_ERROR); 33733859Sml29623 else 33743859Sml29623 return (NXGE_OK); 33753859Sml29623 } 3376*4185Sspeer 3377*4185Sspeer boolean_t 3378*4185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 3379*4185Sspeer { 3380*4185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 3381*4185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 3382*4185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 3383*4185Sspeer return (B_FALSE); 3384*4185Sspeer else 3385*4185Sspeer return (B_TRUE); 3386*4185Sspeer } 3387