144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 22a3c5bd6dSspeer * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <sys/nxge/nxge_impl.h> 2944961713Sgirish #include <sys/nxge/nxge_mac.h> 3044961713Sgirish 31*98ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 32*98ecde52Stm #define LM_WAIT_MULTIPLIER 8 33*98ecde52Stm 3444961713Sgirish extern uint32_t nxge_no_link_notify; 3544961713Sgirish extern uint32_t nxge_lb_dbg; 3644961713Sgirish extern nxge_os_mutex_t nxge_mdio_lock; 3744961713Sgirish extern nxge_os_mutex_t nxge_mii_lock; 3844961713Sgirish extern boolean_t nxge_jumbo_enable; 3944961713Sgirish 40*98ecde52Stm typedef enum { 41*98ecde52Stm CHECK_LINK_RESCHEDULE, 42*98ecde52Stm CHECK_LINK_STOP 43*98ecde52Stm } check_link_state_t; 44*98ecde52Stm 45*98ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 46*98ecde52Stm 4744961713Sgirish /* 4844961713Sgirish * Ethernet broadcast address definition. 4944961713Sgirish */ 5044961713Sgirish static ether_addr_st etherbroadcastaddr = 5144961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 5256d930aeSspeer static ether_addr_st etherzeroaddr = 5356d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 5444961713Sgirish 5544961713Sgirish nxge_status_t nxge_mac_init(p_nxge_t); 5644961713Sgirish 5744961713Sgirish /* Initialize the entire MAC and physical layer */ 5844961713Sgirish 5944961713Sgirish nxge_status_t 6044961713Sgirish nxge_mac_init(p_nxge_t nxgep) 6144961713Sgirish { 6244961713Sgirish uint8_t portn; 6344961713Sgirish nxge_status_t status = NXGE_OK; 6444961713Sgirish 6544961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6644961713Sgirish 6744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 6844961713Sgirish 6944961713Sgirish nxgep->mac.portnum = portn; 7044961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 7144961713Sgirish 7244961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 7344961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 7444961713Sgirish 7544961713Sgirish /* Initialize XIF to configure a network mode */ 7644961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 7744961713Sgirish goto fail; 7844961713Sgirish } 7944961713Sgirish 8044961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 8144961713Sgirish goto fail; 8244961713Sgirish } 8344961713Sgirish 8444961713Sgirish /* Initialize TX and RX MACs */ 8544961713Sgirish /* 8644961713Sgirish * Always perform XIF init first, before TX and RX MAC init 8744961713Sgirish */ 8844961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 8944961713Sgirish goto fail; 9044961713Sgirish 9144961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 9244961713Sgirish goto fail; 9344961713Sgirish 9444961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 9544961713Sgirish goto fail; 9644961713Sgirish 9744961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 9844961713Sgirish goto fail; 9944961713Sgirish 10044961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 10144961713Sgirish goto fail; 10244961713Sgirish 10344961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 10444961713Sgirish goto fail; 10544961713Sgirish 10644961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 10744961713Sgirish 10844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 10944961713Sgirish 11044961713Sgirish return (NXGE_OK); 11144961713Sgirish fail: 11244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11344961713Sgirish "nxge_mac_init: failed to initialize MAC port<%d>", 11444961713Sgirish portn)); 11544961713Sgirish return (status); 11644961713Sgirish } 11744961713Sgirish 11844961713Sgirish /* Initialize the Ethernet Link */ 11944961713Sgirish 12044961713Sgirish nxge_status_t 12144961713Sgirish nxge_link_init(p_nxge_t nxgep) 12244961713Sgirish { 12344961713Sgirish nxge_status_t status = NXGE_OK; 12444961713Sgirish #ifdef NXGE_DEBUG 12544961713Sgirish uint8_t portn; 12644961713Sgirish 12744961713Sgirish portn = nxgep->mac.portnum; 12844961713Sgirish 12944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 13044961713Sgirish #endif 13144961713Sgirish 13244961713Sgirish if (nxgep->niu_type == N2_NIU) { 13344961713Sgirish /* Workaround to get link up in both NIU ports */ 13444961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 13544961713Sgirish goto fail; 13644961713Sgirish } 13744961713Sgirish NXGE_DELAY(200000); 13844961713Sgirish /* Initialize internal serdes */ 13944961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 14044961713Sgirish goto fail; 14144961713Sgirish NXGE_DELAY(200000); 14244961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 14344961713Sgirish goto fail; 14444961713Sgirish 14544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 14644961713Sgirish 14744961713Sgirish return (NXGE_OK); 14844961713Sgirish 14944961713Sgirish fail: 15044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15144961713Sgirish "nxge_link_init: ", 15244961713Sgirish "failed to initialize Ethernet link on port<%d>", 15344961713Sgirish portn)); 15444961713Sgirish 15544961713Sgirish return (status); 15644961713Sgirish } 15744961713Sgirish 15844961713Sgirish 15944961713Sgirish /* Initialize the XIF sub-block within the MAC */ 16044961713Sgirish 16144961713Sgirish nxge_status_t 16244961713Sgirish nxge_xif_init(p_nxge_t nxgep) 16344961713Sgirish { 16444961713Sgirish uint32_t xif_cfg = 0; 16544961713Sgirish npi_attr_t ap; 16644961713Sgirish uint8_t portn; 16744961713Sgirish nxge_port_t portt; 16844961713Sgirish nxge_port_mode_t portmode; 16944961713Sgirish p_nxge_stats_t statsp; 17044961713Sgirish npi_status_t rs = NPI_SUCCESS; 17144961713Sgirish npi_handle_t handle; 17244961713Sgirish 17344961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 17444961713Sgirish 17544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 17644961713Sgirish 17744961713Sgirish handle = nxgep->npi_handle; 17844961713Sgirish portmode = nxgep->mac.portmode; 17944961713Sgirish portt = nxgep->mac.porttype; 18044961713Sgirish statsp = nxgep->statsp; 18144961713Sgirish 18244961713Sgirish if (portt == PORT_TYPE_XMAC) { 18344961713Sgirish 18444961713Sgirish /* Setup XIF Configuration for XMAC */ 18544961713Sgirish 18644961713Sgirish if ((portmode == PORT_10G_FIBER) || 18744961713Sgirish (portmode == PORT_10G_COPPER)) 18844961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 18944961713Sgirish 19044961713Sgirish if (portmode == PORT_1G_COPPER) { 19144961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 19244961713Sgirish } 19344961713Sgirish 19444961713Sgirish /* Set MAC Internal Loopback if necessary */ 19544961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 19644961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 19744961713Sgirish 19844961713Sgirish if (statsp->mac_stats.link_speed == 100) 19944961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 20044961713Sgirish 20144961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 20244961713Sgirish 20344961713Sgirish if (portmode == PORT_10G_FIBER) { 20444961713Sgirish if (statsp->mac_stats.link_up) { 20544961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 20644961713Sgirish } else { 20744961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 20844961713Sgirish } 20944961713Sgirish } 21044961713Sgirish 21144961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 21244961713Sgirish if (rs != NPI_SUCCESS) 21344961713Sgirish goto fail; 21444961713Sgirish 21544961713Sgirish nxgep->mac.xif_config = xif_cfg; 21644961713Sgirish 21744961713Sgirish /* Set Port Mode */ 21844961713Sgirish if ((portmode == PORT_10G_FIBER) || 21944961713Sgirish (portmode == PORT_10G_COPPER)) { 22044961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 22144961713Sgirish MAC_XGMII_MODE, rs); 22244961713Sgirish if (rs != NPI_SUCCESS) 22344961713Sgirish goto fail; 22444961713Sgirish if (statsp->mac_stats.link_up) { 22544961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 22644961713Sgirish goto fail; 22744961713Sgirish } else { 22844961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 22944961713Sgirish goto fail; 23044961713Sgirish } 23144961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 23244961713Sgirish (portmode == PORT_1G_COPPER)) { 23344961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 23444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 23544961713Sgirish MAC_GMII_MODE, rs); 23644961713Sgirish } else { 23744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 23844961713Sgirish MAC_MII_MODE, rs); 23944961713Sgirish } 24044961713Sgirish if (rs != NPI_SUCCESS) 24144961713Sgirish goto fail; 24244961713Sgirish } else { 24344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 24444961713Sgirish "nxge_xif_init: Unknown port mode (%d)" 24544961713Sgirish " for port<%d>", portmode, portn)); 24644961713Sgirish goto fail; 24744961713Sgirish } 24844961713Sgirish 24944961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 25044961713Sgirish 25144961713Sgirish /* Setup XIF Configuration for BMAC */ 25244961713Sgirish 25344961713Sgirish if (portmode == PORT_1G_COPPER) { 25444961713Sgirish if (statsp->mac_stats.link_speed == 100) 25544961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 25644961713Sgirish } 25744961713Sgirish 25844961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 25944961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 26044961713Sgirish 26144961713Sgirish if (statsp->mac_stats.link_speed == 1000) 26244961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 26344961713Sgirish 26444961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 26544961713Sgirish 26644961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 26744961713Sgirish if (rs != NPI_SUCCESS) 26844961713Sgirish goto fail; 26944961713Sgirish nxgep->mac.xif_config = xif_cfg; 27044961713Sgirish } 27144961713Sgirish 27244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 27344961713Sgirish return (NXGE_OK); 27444961713Sgirish fail: 27544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 27644961713Sgirish "nxge_xif_init: Failed to initialize XIF port<%d>", 27744961713Sgirish portn)); 27844961713Sgirish return (NXGE_ERROR | rs); 27944961713Sgirish } 28044961713Sgirish 28144961713Sgirish /* Initialize the PCS sub-block in the MAC */ 28244961713Sgirish 28344961713Sgirish nxge_status_t 28444961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 28544961713Sgirish { 28644961713Sgirish pcs_cfg_t pcs_cfg; 28744961713Sgirish uint32_t val; 28844961713Sgirish uint8_t portn; 28944961713Sgirish nxge_port_mode_t portmode; 29044961713Sgirish npi_handle_t handle; 29144961713Sgirish p_nxge_stats_t statsp; 29244961713Sgirish npi_status_t rs = NPI_SUCCESS; 29344961713Sgirish 29444961713Sgirish handle = nxgep->npi_handle; 29544961713Sgirish portmode = nxgep->mac.portmode; 29644961713Sgirish portn = nxgep->mac.portnum; 29744961713Sgirish statsp = nxgep->statsp; 29844961713Sgirish 29944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 30044961713Sgirish 30144961713Sgirish if (portmode == PORT_1G_FIBER) { 30244961713Sgirish /* Initialize port's PCS */ 30344961713Sgirish pcs_cfg.value = 0; 30444961713Sgirish pcs_cfg.bits.w0.enable = 1; 30544961713Sgirish pcs_cfg.bits.w0.mask = 1; 30644961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 30744961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 30844961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 30944961713Sgirish goto fail; 31044961713Sgirish 31144961713Sgirish } else if ((portmode == PORT_10G_FIBER) || 31244961713Sgirish (portmode == PORT_10G_COPPER)) { 31344961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 31444961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 31544961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 31644961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 31744961713Sgirish 31844961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 31944961713Sgirish goto fail; 32044961713Sgirish 32144961713Sgirish /* Set XPCS Internal Loopback if necessary */ 32244961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 32344961713Sgirish XPCS_REG_CONTROL1, &val)) 32444961713Sgirish != NPI_SUCCESS) 32544961713Sgirish goto fail; 32644961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 32744961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 32844961713Sgirish val |= XPCS_CTRL1_LOOPBK; 32944961713Sgirish else 33044961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 33144961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 33244961713Sgirish XPCS_REG_CONTROL1, val)) 33344961713Sgirish != NPI_SUCCESS) 33444961713Sgirish goto fail; 33544961713Sgirish 33644961713Sgirish /* Clear descw errors */ 33744961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 33844961713Sgirish XPCS_REG_DESCWERR_COUNTER, 0)) 33944961713Sgirish != NPI_SUCCESS) 34044961713Sgirish goto fail; 34144961713Sgirish /* Clear symbol errors */ 34244961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 34344961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 34444961713Sgirish != NPI_SUCCESS) 34544961713Sgirish goto fail; 34644961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 34744961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 34844961713Sgirish != NPI_SUCCESS) 34944961713Sgirish goto fail; 35044961713Sgirish 35144961713Sgirish } else if (portmode == PORT_1G_COPPER) { 35244961713Sgirish if (portn < 4) { 35344961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 35444961713Sgirish PCS_DATAPATH_MODE_MII); 35544961713Sgirish } 35644961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 35744961713Sgirish goto fail; 35844961713Sgirish 35944961713Sgirish } else { 36044961713Sgirish goto fail; 36144961713Sgirish } 36244961713Sgirish pass: 36344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 36444961713Sgirish return (NXGE_OK); 36544961713Sgirish fail: 36644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36744961713Sgirish "nxge_pcs_init: Failed to initialize PCS port<%d>", 36844961713Sgirish portn)); 36944961713Sgirish return (NXGE_ERROR | rs); 37044961713Sgirish } 37144961713Sgirish 37244961713Sgirish /* Initialize the Internal Serdes */ 37344961713Sgirish 37444961713Sgirish nxge_status_t 37544961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 37644961713Sgirish { 37744961713Sgirish p_nxge_stats_t statsp; 37844961713Sgirish #ifdef NXGE_DEBUG 37944961713Sgirish uint8_t portn; 38044961713Sgirish #endif 38144961713Sgirish nxge_status_t status = NXGE_OK; 38244961713Sgirish 38344961713Sgirish #ifdef NXGE_DEBUG 38444961713Sgirish portn = nxgep->mac.portnum; 38544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38644961713Sgirish "==> nxge_serdes_init port<%d>", portn)); 38744961713Sgirish #endif 38844961713Sgirish 38944961713Sgirish statsp = nxgep->statsp; 39044961713Sgirish 39144961713Sgirish if (nxgep->niu_type == N2_NIU) { 39244961713Sgirish if (nxge_n2_serdes_init(nxgep) != NXGE_OK) 39344961713Sgirish goto fail; 39444961713Sgirish } else if ((nxgep->niu_type == NEPTUNE) || 39544961713Sgirish (nxgep->niu_type == NEPTUNE_2)) { 39644961713Sgirish if ((status = nxge_neptune_serdes_init(nxgep)) 39744961713Sgirish != NXGE_OK) 39844961713Sgirish goto fail; 39944961713Sgirish } else { 40044961713Sgirish goto fail; 40144961713Sgirish } 40244961713Sgirish 40344961713Sgirish statsp->mac_stats.serdes_inits++; 40444961713Sgirish 40544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 40644961713Sgirish portn)); 40744961713Sgirish 40844961713Sgirish return (NXGE_OK); 40944961713Sgirish 41044961713Sgirish fail: 41144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 41244961713Sgirish "nxge_serdes_init: Failed to initialize serdes for port<%d>", 41344961713Sgirish portn)); 41444961713Sgirish 41544961713Sgirish return (status); 41644961713Sgirish } 41744961713Sgirish 41844961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 41944961713Sgirish 42044961713Sgirish nxge_status_t 42144961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 42244961713Sgirish { 42344961713Sgirish uint8_t portn; 42444961713Sgirish int chan; 42544961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 42644961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 42744961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 42844961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 42944961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 43044961713Sgirish esr_ti_testcfg_t test_cfg; 43144961713Sgirish nxge_status_t status = NXGE_OK; 43244961713Sgirish 43344961713Sgirish portn = nxgep->mac.portnum; 43444961713Sgirish 43544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 43644961713Sgirish portn)); 43744961713Sgirish 43844961713Sgirish tx_cfg_l.value = 0; 43944961713Sgirish tx_cfg_h.value = 0; 44044961713Sgirish rx_cfg_l.value = 0; 44144961713Sgirish rx_cfg_h.value = 0; 44244961713Sgirish pll_cfg_l.value = 0; 44344961713Sgirish test_cfg.value = 0; 44444961713Sgirish 44544961713Sgirish if (nxgep->mac.portmode == PORT_10G_FIBER) { 44644961713Sgirish /* 0x0E01 */ 44744961713Sgirish tx_cfg_l.bits.entx = 1; 44844961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 44944961713Sgirish 45044961713Sgirish /* 0x9101 */ 45144961713Sgirish rx_cfg_l.bits.enrx = 1; 45244961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 45344961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 45444961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 45544961713Sgirish 45644961713Sgirish /* 0x0008 */ 45744961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 45844961713Sgirish 45944961713Sgirish /* Set loopback mode if necessary */ 46044961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 46144961713Sgirish tx_cfg_l.bits.entest = 1; 46244961713Sgirish rx_cfg_l.bits.entest = 1; 46344961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 46444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 46544961713Sgirish ESR_N2_DEV_ADDR, 46644961713Sgirish ESR_N2_TEST_CFG_REG, test_cfg.value)) 46744961713Sgirish != NXGE_OK) 46844961713Sgirish goto fail; 46944961713Sgirish } 47044961713Sgirish 47144961713Sgirish /* Use default PLL value */ 47244961713Sgirish 47344961713Sgirish } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 47444961713Sgirish 47544961713Sgirish /* 0x0E21 */ 47644961713Sgirish tx_cfg_l.bits.entx = 1; 47744961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 47844961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 47944961713Sgirish 48044961713Sgirish /* 0x9121 */ 48144961713Sgirish rx_cfg_l.bits.enrx = 1; 48244961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 48344961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 48444961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 48544961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 48644961713Sgirish 48744961713Sgirish /* 0x8 */ 48844961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 48944961713Sgirish 49044961713Sgirish /* MPY = 0x100 */ 49144961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 49244961713Sgirish 49344961713Sgirish /* Set PLL */ 49444961713Sgirish pll_cfg_l.bits.enpll = 1; 49544961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 49644961713Sgirish ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 49744961713Sgirish != NXGE_OK) 49844961713Sgirish goto fail; 49944961713Sgirish } else { 50044961713Sgirish goto fail; 50144961713Sgirish } 50244961713Sgirish 50344961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 50444961713Sgirish 50544961713Sgirish NXGE_DELAY(20); 50644961713Sgirish 50744961713Sgirish /* init TX channels */ 50844961713Sgirish for (chan = 0; chan < 4; chan++) { 50944961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 51044961713Sgirish ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 51144961713Sgirish != NXGE_OK) 51244961713Sgirish goto fail; 51344961713Sgirish 51444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 51544961713Sgirish ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 51644961713Sgirish != NXGE_OK) 51744961713Sgirish goto fail; 51844961713Sgirish } 51944961713Sgirish 52044961713Sgirish /* init RX channels */ 52144961713Sgirish for (chan = 0; chan < 4; chan++) { 52244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 52344961713Sgirish ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 52444961713Sgirish != NXGE_OK) 52544961713Sgirish goto fail; 52644961713Sgirish 52744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 52844961713Sgirish ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 52944961713Sgirish != NXGE_OK) 53044961713Sgirish goto fail; 53144961713Sgirish } 53244961713Sgirish 53344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 53444961713Sgirish portn)); 53544961713Sgirish 53644961713Sgirish return (NXGE_OK); 53744961713Sgirish fail: 53844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53944961713Sgirish "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 54044961713Sgirish portn)); 54144961713Sgirish 54244961713Sgirish return (status); 54344961713Sgirish } 54444961713Sgirish 54544961713Sgirish /* Initialize Neptune Internal Serdes (Neptune only) */ 54644961713Sgirish 54744961713Sgirish nxge_status_t 54844961713Sgirish nxge_neptune_serdes_init(p_nxge_t nxgep) 54944961713Sgirish { 55044961713Sgirish npi_handle_t handle; 55144961713Sgirish uint8_t portn; 55244961713Sgirish nxge_port_mode_t portmode; 55344961713Sgirish int chan; 55444961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 55544961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 55644961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 55744961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 55844961713Sgirish uint64_t val; 55944961713Sgirish uint16_t val16l; 56044961713Sgirish uint16_t val16h; 56144961713Sgirish nxge_status_t status = NXGE_OK; 56244961713Sgirish 56344961713Sgirish portn = nxgep->mac.portnum; 56444961713Sgirish 56544961713Sgirish if ((portn != 0) && (portn != 1)) 56644961713Sgirish return (NXGE_OK); 56744961713Sgirish 56844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>", 56944961713Sgirish portn)); 57044961713Sgirish 57144961713Sgirish handle = nxgep->npi_handle; 57244961713Sgirish portmode = nxgep->mac.portmode; 57344961713Sgirish 57444961713Sgirish if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) { 57544961713Sgirish 57644961713Sgirish switch (portn) { 57744961713Sgirish case 0: 57844961713Sgirish ESR_REG_WR(handle, ESR_0_CONTROL_REG, 57944961713Sgirish ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 58044961713Sgirish ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 58144961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 58244961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 58344961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 58444961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 58544961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 58644961713Sgirish (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 58744961713Sgirish (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 58844961713Sgirish (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 58944961713Sgirish (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 59044961713Sgirish 59144961713Sgirish /* Set Serdes0 Internal Loopback if necessary */ 59244961713Sgirish if (nxgep->statsp->port_stats.lb_mode == 59344961713Sgirish nxge_lb_serdes10g) { 59444961713Sgirish ESR_REG_WR(handle, 59544961713Sgirish ESR_0_TEST_CONFIG_REG, 59644961713Sgirish ESR_PAD_LOOPBACK_CH3 | 59744961713Sgirish ESR_PAD_LOOPBACK_CH2 | 59844961713Sgirish ESR_PAD_LOOPBACK_CH1 | 59944961713Sgirish ESR_PAD_LOOPBACK_CH0); 60044961713Sgirish } else { 60144961713Sgirish ESR_REG_WR(handle, 60244961713Sgirish ESR_0_TEST_CONFIG_REG, 0); 60344961713Sgirish } 60444961713Sgirish break; 60544961713Sgirish case 1: 60644961713Sgirish ESR_REG_WR(handle, ESR_1_CONTROL_REG, 60744961713Sgirish ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 60844961713Sgirish ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 60944961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 61044961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 61144961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 61244961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 61344961713Sgirish (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 61444961713Sgirish (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 61544961713Sgirish (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 61644961713Sgirish (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 61744961713Sgirish (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 61844961713Sgirish 61944961713Sgirish /* Set Serdes1 Internal Loopback if necessary */ 62044961713Sgirish if (nxgep->statsp->port_stats.lb_mode == 62144961713Sgirish nxge_lb_serdes10g) { 62244961713Sgirish ESR_REG_WR(handle, 62344961713Sgirish ESR_1_TEST_CONFIG_REG, 62444961713Sgirish ESR_PAD_LOOPBACK_CH3 | 62544961713Sgirish ESR_PAD_LOOPBACK_CH2 | 62644961713Sgirish ESR_PAD_LOOPBACK_CH1 | 62744961713Sgirish ESR_PAD_LOOPBACK_CH0); 62844961713Sgirish } else { 62944961713Sgirish ESR_REG_WR(handle, 63044961713Sgirish ESR_1_TEST_CONFIG_REG, 0); 63144961713Sgirish } 63244961713Sgirish break; 63344961713Sgirish default: 63444961713Sgirish /* Nothing to do here */ 63544961713Sgirish goto done; 63644961713Sgirish } 63744961713Sgirish 63844961713Sgirish /* init TX RX channels */ 63944961713Sgirish for (chan = 0; chan < 4; chan++) { 64044961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 64144961713Sgirish ESR_NEPTUNE_DEV_ADDR, 64244961713Sgirish ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 64344961713Sgirish &rx_tx_ctrl_l.value)) != NXGE_OK) 64444961713Sgirish goto fail; 64544961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 64644961713Sgirish ESR_NEPTUNE_DEV_ADDR, 64744961713Sgirish ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 64844961713Sgirish &rx_tx_ctrl_h.value)) != NXGE_OK) 64944961713Sgirish goto fail; 65044961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 65144961713Sgirish ESR_NEPTUNE_DEV_ADDR, 65244961713Sgirish ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 65344961713Sgirish &glue_ctrl0_l.value)) != NXGE_OK) 65444961713Sgirish goto fail; 65544961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 65644961713Sgirish ESR_NEPTUNE_DEV_ADDR, 65744961713Sgirish ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 65844961713Sgirish &glue_ctrl0_h.value)) != NXGE_OK) 65944961713Sgirish goto fail; 66044961713Sgirish rx_tx_ctrl_l.bits.enstretch = 1; 66144961713Sgirish rx_tx_ctrl_h.bits.vmuxlo = 2; 66244961713Sgirish rx_tx_ctrl_h.bits.vpulselo = 2; 66344961713Sgirish glue_ctrl0_l.bits.rxlosenable = 1; 66444961713Sgirish glue_ctrl0_l.bits.samplerate = 0xF; 66544961713Sgirish glue_ctrl0_l.bits.thresholdcount = 0xFF; 66644961713Sgirish glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 66744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 66844961713Sgirish ESR_NEPTUNE_DEV_ADDR, 66944961713Sgirish ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 67044961713Sgirish rx_tx_ctrl_l.value)) != NXGE_OK) 67144961713Sgirish goto fail; 67244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 67344961713Sgirish ESR_NEPTUNE_DEV_ADDR, 67444961713Sgirish ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 67544961713Sgirish rx_tx_ctrl_h.value)) != NXGE_OK) 67644961713Sgirish goto fail; 67744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 67844961713Sgirish ESR_NEPTUNE_DEV_ADDR, 67944961713Sgirish ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 68044961713Sgirish glue_ctrl0_l.value)) != NXGE_OK) 68144961713Sgirish goto fail; 68244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 68344961713Sgirish ESR_NEPTUNE_DEV_ADDR, 68444961713Sgirish ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 68544961713Sgirish glue_ctrl0_h.value)) != NXGE_OK) 68644961713Sgirish goto fail; 68744961713Sgirish } 68844961713Sgirish 68944961713Sgirish /* Apply Tx core reset */ 69044961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 69144961713Sgirish ESR_NEPTUNE_DEV_ADDR, 69244961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 69344961713Sgirish (uint16_t)0)) != NXGE_OK) 69444961713Sgirish goto fail; 69544961713Sgirish 69644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 69744961713Sgirish ESR_NEPTUNE_DEV_ADDR, 69844961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 69944961713Sgirish (uint16_t)0xffff)) != NXGE_OK) 70044961713Sgirish goto fail; 70144961713Sgirish 70244961713Sgirish NXGE_DELAY(200); 70344961713Sgirish 70444961713Sgirish /* Apply Rx core reset */ 70544961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 70644961713Sgirish ESR_NEPTUNE_DEV_ADDR, 70744961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 70844961713Sgirish (uint16_t)0xffff)) != NXGE_OK) 70944961713Sgirish goto fail; 71044961713Sgirish 71144961713Sgirish NXGE_DELAY(200); 71244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 71344961713Sgirish ESR_NEPTUNE_DEV_ADDR, 71444961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 71544961713Sgirish (uint16_t)0)) != NXGE_OK) 71644961713Sgirish goto fail; 71744961713Sgirish 71844961713Sgirish NXGE_DELAY(200); 71944961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 72044961713Sgirish ESR_NEPTUNE_DEV_ADDR, 72144961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 72244961713Sgirish &val16l)) != NXGE_OK) 72344961713Sgirish goto fail; 72444961713Sgirish if ((status = nxge_mdio_read(nxgep, portn, 72544961713Sgirish ESR_NEPTUNE_DEV_ADDR, 72644961713Sgirish ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 72744961713Sgirish &val16h)) != NXGE_OK) 72844961713Sgirish goto fail; 72944961713Sgirish if ((val16l != 0) || (val16h != 0)) { 73044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 73144961713Sgirish "Failed to reset port<%d> XAUI Serdes", 73244961713Sgirish portn)); 73344961713Sgirish } 73444961713Sgirish 73544961713Sgirish ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 73644961713Sgirish 73744961713Sgirish if (portn == 0) { 73844961713Sgirish if ((val & ESR_SIG_P0_BITS_MASK) != 73944961713Sgirish (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 74044961713Sgirish ESR_SIG_XSERDES_RDY_P0 | 74144961713Sgirish ESR_SIG_XDETECT_P0_CH3 | 74244961713Sgirish ESR_SIG_XDETECT_P0_CH2 | 74344961713Sgirish ESR_SIG_XDETECT_P0_CH1 | 74444961713Sgirish ESR_SIG_XDETECT_P0_CH0)) { 74544961713Sgirish goto fail; 74644961713Sgirish } 74744961713Sgirish } else if (portn == 1) { 74844961713Sgirish if ((val & ESR_SIG_P1_BITS_MASK) != 74944961713Sgirish (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 75044961713Sgirish ESR_SIG_XSERDES_RDY_P1 | 75144961713Sgirish ESR_SIG_XDETECT_P1_CH3 | 75244961713Sgirish ESR_SIG_XDETECT_P1_CH2 | 75344961713Sgirish ESR_SIG_XDETECT_P1_CH1 | 75444961713Sgirish ESR_SIG_XDETECT_P1_CH0)) { 75544961713Sgirish goto fail; 75644961713Sgirish } 75744961713Sgirish } 75844961713Sgirish 75944961713Sgirish } else if (portmode == PORT_1G_FIBER) { 76044961713Sgirish ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val) 76144961713Sgirish val &= ~ESR_PLL_CFG_FBDIV_2; 76244961713Sgirish switch (portn) { 76344961713Sgirish case 0: 76444961713Sgirish val |= ESR_PLL_CFG_HALF_RATE_0; 76544961713Sgirish break; 76644961713Sgirish case 1: 76744961713Sgirish val |= ESR_PLL_CFG_HALF_RATE_1; 76844961713Sgirish break; 76944961713Sgirish case 2: 77044961713Sgirish val |= ESR_PLL_CFG_HALF_RATE_2; 77144961713Sgirish break; 77244961713Sgirish case 3: 77344961713Sgirish val |= ESR_PLL_CFG_HALF_RATE_3; 77444961713Sgirish break; 77544961713Sgirish default: 77644961713Sgirish goto fail; 77744961713Sgirish } 77844961713Sgirish 77944961713Sgirish ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 78044961713Sgirish } 78144961713Sgirish 78244961713Sgirish done: 78344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>", 78444961713Sgirish portn)); 78544961713Sgirish return (NXGE_OK); 78644961713Sgirish fail: 78744961713Sgirish NXGE_DEBUG_MSG((nxgep, TX_CTL, 78844961713Sgirish "nxge_neptune_serdes_init: " 78944961713Sgirish "Failed to initialize Neptune serdes for port<%d>", 79044961713Sgirish portn)); 79144961713Sgirish 79244961713Sgirish return (status); 79344961713Sgirish } 79444961713Sgirish 79544961713Sgirish /* Look for transceiver type */ 79644961713Sgirish 79744961713Sgirish nxge_status_t 79844961713Sgirish nxge_xcvr_find(p_nxge_t nxgep) 79944961713Sgirish { 80044961713Sgirish uint8_t portn; 80144961713Sgirish 80244961713Sgirish portn = nxgep->mac.portnum; 80344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn)); 80444961713Sgirish 80544961713Sgirish if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 80644961713Sgirish return (NXGE_ERROR); 80744961713Sgirish 80844961713Sgirish nxgep->mac.linkchkmode = LINKCHK_TIMER; 80944961713Sgirish if (nxgep->mac.portmode == PORT_10G_FIBER) { 81044961713Sgirish nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 81144961713Sgirish if ((nxgep->niu_type == NEPTUNE) || 81244961713Sgirish (nxgep->niu_type == NEPTUNE_2)) { 81344961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 81444961713Sgirish BCM8704_NEPTUNE_PORT_ADDR_BASE + portn; 81544961713Sgirish } else if (nxgep->niu_type == N2_NIU) { 81644961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 81744961713Sgirish BCM8704_N2_PORT_ADDR_BASE + portn; 81844961713Sgirish } else 81944961713Sgirish return (NXGE_ERROR); 82044961713Sgirish } else if (nxgep->mac.portmode == PORT_1G_COPPER) { 82144961713Sgirish nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 82244961713Sgirish /* 82344961713Sgirish * For Altas, Xcvr port numbers are swapped with ethernet 82444961713Sgirish * port number. This is designed for better signal 82544961713Sgirish * integrity in routing. 82644961713Sgirish */ 82744961713Sgirish 82844961713Sgirish switch (portn) { 82944961713Sgirish case 0: 83044961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 83144961713Sgirish BCM5464_NEPTUNE_PORT_ADDR_BASE + 3; 83244961713Sgirish break; 83344961713Sgirish case 1: 83444961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 83544961713Sgirish BCM5464_NEPTUNE_PORT_ADDR_BASE + 2; 83644961713Sgirish break; 83744961713Sgirish case 2: 83844961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 83944961713Sgirish BCM5464_NEPTUNE_PORT_ADDR_BASE + 1; 84044961713Sgirish break; 84144961713Sgirish case 3: 84244961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = 84344961713Sgirish BCM5464_NEPTUNE_PORT_ADDR_BASE; 84444961713Sgirish break; 84544961713Sgirish default: 84644961713Sgirish return (NXGE_ERROR); 84744961713Sgirish } 84844961713Sgirish } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 84944961713Sgirish nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 85044961713Sgirish nxgep->statsp->mac_stats.xcvr_portn = portn; 85144961713Sgirish } else { 85244961713Sgirish return (NXGE_ERROR); 85344961713Sgirish } 85444961713Sgirish 85544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 85644961713Sgirish nxgep->statsp->mac_stats.xcvr_inuse)); 85744961713Sgirish return (NXGE_OK); 85844961713Sgirish } 85944961713Sgirish 86044961713Sgirish /* Initialize transceiver */ 86144961713Sgirish 86244961713Sgirish nxge_status_t 86344961713Sgirish nxge_xcvr_init(p_nxge_t nxgep) 86444961713Sgirish { 86544961713Sgirish p_nxge_param_t param_arr; 86644961713Sgirish p_nxge_stats_t statsp; 86744961713Sgirish uint16_t val; 86844961713Sgirish #ifdef NXGE_DEBUG 86914ea4bb7Ssd uint8_t portn; 87044961713Sgirish uint16_t val1; 87144961713Sgirish #endif 87244961713Sgirish uint8_t phy_port_addr; 87344961713Sgirish pmd_tx_control_t tx_ctl; 87444961713Sgirish control_t ctl; 87544961713Sgirish phyxs_control_t phyxs_ctl; 87644961713Sgirish pcs_control_t pcs_ctl; 87744961713Sgirish uint32_t delay = 0; 87844961713Sgirish optics_dcntr_t op_ctr; 87944961713Sgirish nxge_status_t status = NXGE_OK; 88014ea4bb7Ssd #ifdef NXGE_DEBUG 88144961713Sgirish portn = nxgep->mac.portnum; 88214ea4bb7Ssd #endif 88344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 88444961713Sgirish 88544961713Sgirish param_arr = nxgep->param_arr; 88644961713Sgirish statsp = nxgep->statsp; 88744961713Sgirish 88844961713Sgirish /* 88958324dfcSspeer * Initialize the xcvr statistics. 89044961713Sgirish */ 89144961713Sgirish statsp->mac_stats.cap_autoneg = 0; 89244961713Sgirish statsp->mac_stats.cap_100T4 = 0; 89344961713Sgirish statsp->mac_stats.cap_100fdx = 0; 89444961713Sgirish statsp->mac_stats.cap_100hdx = 0; 89544961713Sgirish statsp->mac_stats.cap_10fdx = 0; 89644961713Sgirish statsp->mac_stats.cap_10hdx = 0; 89744961713Sgirish statsp->mac_stats.cap_asmpause = 0; 89844961713Sgirish statsp->mac_stats.cap_pause = 0; 89944961713Sgirish statsp->mac_stats.cap_1000fdx = 0; 90044961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 90144961713Sgirish statsp->mac_stats.cap_10gfdx = 0; 90244961713Sgirish statsp->mac_stats.cap_10ghdx = 0; 90344961713Sgirish 90444961713Sgirish /* 90544961713Sgirish * Initialize the link statistics. 90644961713Sgirish */ 90744961713Sgirish statsp->mac_stats.link_T4 = 0; 90844961713Sgirish statsp->mac_stats.link_asmpause = 0; 90944961713Sgirish statsp->mac_stats.link_pause = 0; 91044961713Sgirish 91144961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 91244961713Sgirish 91344961713Sgirish switch (nxgep->mac.portmode) { 91444961713Sgirish case PORT_10G_FIBER: 91544961713Sgirish /* Disable Link LEDs */ 91644961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 91744961713Sgirish goto fail; 91844961713Sgirish 91944961713Sgirish /* Set Clause 45 */ 92044961713Sgirish npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 92144961713Sgirish 92244961713Sgirish /* Reset the transceiver */ 92344961713Sgirish if ((status = nxge_mdio_read(nxgep, 92444961713Sgirish phy_port_addr, 92544961713Sgirish BCM8704_PHYXS_ADDR, 92644961713Sgirish BCM8704_PHYXS_CONTROL_REG, 92744961713Sgirish &phyxs_ctl.value)) != NXGE_OK) 92844961713Sgirish goto fail; 92944961713Sgirish 93044961713Sgirish phyxs_ctl.bits.reset = 1; 93144961713Sgirish if ((status = nxge_mdio_write(nxgep, 93244961713Sgirish phy_port_addr, 93344961713Sgirish BCM8704_PHYXS_ADDR, 93444961713Sgirish BCM8704_PHYXS_CONTROL_REG, 93544961713Sgirish phyxs_ctl.value)) != NXGE_OK) 93644961713Sgirish goto fail; 93744961713Sgirish 93844961713Sgirish do { 93944961713Sgirish drv_usecwait(500); 94044961713Sgirish if ((status = nxge_mdio_read(nxgep, 94144961713Sgirish phy_port_addr, 94244961713Sgirish BCM8704_PHYXS_ADDR, 94344961713Sgirish BCM8704_PHYXS_CONTROL_REG, 94444961713Sgirish &phyxs_ctl.value)) != NXGE_OK) 94544961713Sgirish goto fail; 94644961713Sgirish delay++; 94744961713Sgirish } while ((phyxs_ctl.bits.reset) && (delay < 100)); 94844961713Sgirish if (delay == 100) { 94944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 95044961713Sgirish "nxge_xcvr_init: " 95144961713Sgirish "failed to reset Transceiver on port<%d>", 95244961713Sgirish portn)); 95344961713Sgirish status = NXGE_ERROR; 95444961713Sgirish goto fail; 95544961713Sgirish } 95644961713Sgirish 95744961713Sgirish /* Set to 0x7FBF */ 95844961713Sgirish ctl.value = 0; 95944961713Sgirish ctl.bits.res1 = 0x3F; 96044961713Sgirish ctl.bits.optxon_lvl = 1; 96144961713Sgirish ctl.bits.oprxflt_lvl = 1; 96244961713Sgirish ctl.bits.optrxlos_lvl = 1; 96344961713Sgirish ctl.bits.optxflt_lvl = 1; 96444961713Sgirish ctl.bits.opprflt_lvl = 1; 96544961713Sgirish ctl.bits.obtmpflt_lvl = 1; 96644961713Sgirish ctl.bits.opbiasflt_lvl = 1; 96744961713Sgirish ctl.bits.optxrst_lvl = 1; 96844961713Sgirish if ((status = nxge_mdio_write(nxgep, 96944961713Sgirish phy_port_addr, 97044961713Sgirish BCM8704_USER_DEV3_ADDR, 97144961713Sgirish BCM8704_USER_CONTROL_REG, ctl.value)) 97244961713Sgirish != NXGE_OK) 97344961713Sgirish goto fail; 97444961713Sgirish 97544961713Sgirish /* Set to 0x164 */ 97644961713Sgirish tx_ctl.value = 0; 97744961713Sgirish tx_ctl.bits.tsck_lpwren = 1; 97844961713Sgirish tx_ctl.bits.tx_dac_txck = 0x2; 97944961713Sgirish tx_ctl.bits.tx_dac_txd = 0x1; 98044961713Sgirish tx_ctl.bits.xfp_clken = 1; 98144961713Sgirish if ((status = nxge_mdio_write(nxgep, 98244961713Sgirish phy_port_addr, 98344961713Sgirish BCM8704_USER_DEV3_ADDR, 98444961713Sgirish BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value)) 98544961713Sgirish != NXGE_OK) 98644961713Sgirish goto fail; 98744961713Sgirish /* 98844961713Sgirish * According to Broadcom's instruction, SW needs to read 98944961713Sgirish * back these registers twice after written. 99044961713Sgirish */ 99144961713Sgirish if ((status = nxge_mdio_read(nxgep, 99244961713Sgirish phy_port_addr, 99344961713Sgirish BCM8704_USER_DEV3_ADDR, 99444961713Sgirish BCM8704_USER_CONTROL_REG, &val)) 99544961713Sgirish != NXGE_OK) 99644961713Sgirish goto fail; 99744961713Sgirish 99844961713Sgirish if ((status = nxge_mdio_read(nxgep, 99944961713Sgirish phy_port_addr, 100044961713Sgirish BCM8704_USER_DEV3_ADDR, 100144961713Sgirish BCM8704_USER_CONTROL_REG, &val)) 100244961713Sgirish != NXGE_OK) 100344961713Sgirish goto fail; 100444961713Sgirish 100544961713Sgirish if ((status = nxge_mdio_read(nxgep, 100644961713Sgirish phy_port_addr, 100744961713Sgirish BCM8704_USER_DEV3_ADDR, 100844961713Sgirish BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 100944961713Sgirish != NXGE_OK) 101044961713Sgirish goto fail; 101144961713Sgirish 101244961713Sgirish if ((status = nxge_mdio_read(nxgep, 101344961713Sgirish phy_port_addr, 101444961713Sgirish BCM8704_USER_DEV3_ADDR, 101544961713Sgirish BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 101644961713Sgirish != NXGE_OK) 101744961713Sgirish goto fail; 101844961713Sgirish 101944961713Sgirish 102044961713Sgirish /* Enable Tx and Rx LEDs to be driven by traffic */ 102144961713Sgirish if ((status = nxge_mdio_read(nxgep, 102244961713Sgirish phy_port_addr, 102344961713Sgirish BCM8704_USER_DEV3_ADDR, 102444961713Sgirish BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 102544961713Sgirish &op_ctr.value)) != NXGE_OK) 102644961713Sgirish goto fail; 102744961713Sgirish op_ctr.bits.gpio_sel = 0x3; 102844961713Sgirish if ((status = nxge_mdio_write(nxgep, 102944961713Sgirish phy_port_addr, 103044961713Sgirish BCM8704_USER_DEV3_ADDR, 103144961713Sgirish BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 103244961713Sgirish op_ctr.value)) != NXGE_OK) 103344961713Sgirish goto fail; 103444961713Sgirish 103544961713Sgirish NXGE_DELAY(1000000); 103644961713Sgirish 103744961713Sgirish /* Set BCM8704 Internal Loopback mode if necessary */ 103844961713Sgirish if ((status = nxge_mdio_read(nxgep, 103944961713Sgirish phy_port_addr, 104044961713Sgirish BCM8704_PCS_DEV_ADDR, 104144961713Sgirish BCM8704_PCS_CONTROL_REG, 104244961713Sgirish &pcs_ctl.value)) != NXGE_OK) 104344961713Sgirish goto fail; 104444961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 104544961713Sgirish pcs_ctl.bits.loopback = 1; 104644961713Sgirish else 104744961713Sgirish pcs_ctl.bits.loopback = 0; 104844961713Sgirish if ((status = nxge_mdio_write(nxgep, 104944961713Sgirish phy_port_addr, 105044961713Sgirish BCM8704_PCS_DEV_ADDR, 105144961713Sgirish BCM8704_PCS_CONTROL_REG, 105244961713Sgirish pcs_ctl.value)) != NXGE_OK) 105344961713Sgirish goto fail; 105444961713Sgirish 105544961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 105644961713Sgirish 0x1, 0xA, &val); 105744961713Sgirish if (status != NXGE_OK) 105844961713Sgirish goto fail; 105944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 106044961713Sgirish "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", 106144961713Sgirish portn, val)); 106244961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 106344961713Sgirish if (status != NXGE_OK) 106444961713Sgirish goto fail; 106544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 106644961713Sgirish "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", 106744961713Sgirish portn, val)); 106844961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 106944961713Sgirish if (status != NXGE_OK) 107044961713Sgirish goto fail; 107144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 107244961713Sgirish "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", 107344961713Sgirish portn, val)); 107444961713Sgirish 107544961713Sgirish #ifdef NXGE_DEBUG 107644961713Sgirish /* Diagnose link issue if link is not up */ 107744961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 107844961713Sgirish BCM8704_USER_DEV3_ADDR, 107944961713Sgirish BCM8704_USER_ANALOG_STATUS0_REG, 108044961713Sgirish &val); 108144961713Sgirish if (status != NXGE_OK) 108244961713Sgirish goto fail; 108344961713Sgirish 108444961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 108544961713Sgirish BCM8704_USER_DEV3_ADDR, 108644961713Sgirish BCM8704_USER_ANALOG_STATUS0_REG, 108744961713Sgirish &val); 108844961713Sgirish if (status != NXGE_OK) 108944961713Sgirish goto fail; 109044961713Sgirish 109144961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 109244961713Sgirish BCM8704_USER_DEV3_ADDR, 109344961713Sgirish BCM8704_USER_TX_ALARM_STATUS_REG, 109444961713Sgirish &val1); 109544961713Sgirish if (status != NXGE_OK) 109644961713Sgirish goto fail; 109744961713Sgirish 109844961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 109944961713Sgirish BCM8704_USER_DEV3_ADDR, 110044961713Sgirish BCM8704_USER_TX_ALARM_STATUS_REG, 110144961713Sgirish &val1); 110244961713Sgirish if (status != NXGE_OK) 110344961713Sgirish goto fail; 110444961713Sgirish 110544961713Sgirish if (val != 0x3FC) { 110644961713Sgirish if ((val == 0x43BC) && (val1 != 0)) { 110744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 110844961713Sgirish "Cable not connected to peer or bad" 110944961713Sgirish " cable on port<%d>\n", portn)); 111044961713Sgirish } else if (val == 0x639C) { 111144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 111244961713Sgirish "Optical module (XFP) is bad or absence" 111344961713Sgirish " on port<%d>\n", portn)); 111444961713Sgirish } 111544961713Sgirish } 111644961713Sgirish #endif 111744961713Sgirish 111844961713Sgirish statsp->mac_stats.cap_10gfdx = 1; 111944961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 1; 112044961713Sgirish break; 112144961713Sgirish case PORT_10G_COPPER: 112244961713Sgirish break; 112344961713Sgirish case PORT_1G_FIBER: 112444961713Sgirish case PORT_1G_COPPER: 112544961713Sgirish /* Set Clause 22 */ 112644961713Sgirish npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 112744961713Sgirish 112844961713Sgirish /* Set capability flags */ 112944961713Sgirish statsp->mac_stats.cap_1000fdx = 113044961713Sgirish param_arr[param_anar_1000fdx].value; 113144961713Sgirish statsp->mac_stats.cap_100fdx = 113244961713Sgirish param_arr[param_anar_100fdx].value; 113344961713Sgirish statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value; 113444961713Sgirish 113544961713Sgirish if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK) 113644961713Sgirish goto fail; 113744961713Sgirish break; 113844961713Sgirish default: 113944961713Sgirish goto fail; 114044961713Sgirish } 114144961713Sgirish 114244961713Sgirish statsp->mac_stats.xcvr_inits++; 114344961713Sgirish 114444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 114544961713Sgirish return (NXGE_OK); 114644961713Sgirish 114744961713Sgirish fail: 114844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 114944961713Sgirish "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 115044961713Sgirish portn)); 115144961713Sgirish return (status); 115244961713Sgirish } 115344961713Sgirish 115444961713Sgirish 115544961713Sgirish /* Initialize the TxMAC sub-block */ 115644961713Sgirish 115744961713Sgirish nxge_status_t 115844961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 115944961713Sgirish { 116044961713Sgirish npi_attr_t ap; 116144961713Sgirish uint8_t portn; 116244961713Sgirish nxge_port_mode_t portmode; 116344961713Sgirish nxge_port_t portt; 116444961713Sgirish npi_handle_t handle; 116544961713Sgirish npi_status_t rs = NPI_SUCCESS; 116644961713Sgirish 116744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 116844961713Sgirish portt = nxgep->mac.porttype; 116944961713Sgirish handle = nxgep->npi_handle; 117044961713Sgirish portmode = nxgep->mac.portmode; 117144961713Sgirish 117244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 117344961713Sgirish portn)); 117444961713Sgirish 117544961713Sgirish /* Set Max and Min Frame Size */ 117614ea4bb7Ssd if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 117744961713Sgirish SET_MAC_ATTR2(handle, ap, portn, 117844961713Sgirish MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 117944961713Sgirish } else { 118044961713Sgirish SET_MAC_ATTR2(handle, ap, portn, 118144961713Sgirish MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 118244961713Sgirish } 118344961713Sgirish 118444961713Sgirish if (rs != NPI_SUCCESS) 118544961713Sgirish goto fail; 118614ea4bb7Ssd if (nxgep->param_arr[param_accept_jumbo].value || 118714ea4bb7Ssd nxgep->mac.is_jumbo == B_TRUE) 118844961713Sgirish nxgep->mac.maxframesize = 0x2400; 118944961713Sgirish else 119044961713Sgirish nxgep->mac.maxframesize = 0x5EE + 4; 119144961713Sgirish nxgep->mac.minframesize = 64; 119244961713Sgirish 119344961713Sgirish if (portt == PORT_TYPE_XMAC) { 119444961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 119544961713Sgirish 0)) != NPI_SUCCESS) 119644961713Sgirish goto fail; 119744961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 119844961713Sgirish if ((portmode == PORT_10G_FIBER) || 119944961713Sgirish (portmode == PORT_10G_COPPER)) { 120044961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 120144961713Sgirish XGMII_IPG_12_15, rs); 120244961713Sgirish if (rs != NPI_SUCCESS) 120344961713Sgirish goto fail; 120444961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 120544961713Sgirish } else { 120644961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 120744961713Sgirish MII_GMII_IPG_12, rs); 120844961713Sgirish if (rs != NPI_SUCCESS) 120944961713Sgirish goto fail; 121044961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 121144961713Sgirish } 121244961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 121344961713Sgirish CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 121444961713Sgirish goto fail; 121544961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 121644961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 121744961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 121844961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 121944961713Sgirish 122044961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 122144961713Sgirish != NPI_SUCCESS) 122244961713Sgirish goto fail; 122344961713Sgirish 122444961713Sgirish } else { 122544961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 122644961713Sgirish 0)) != NPI_SUCCESS) 122744961713Sgirish goto fail; 122844961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 122944961713Sgirish 123044961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 123144961713Sgirish rs); 123244961713Sgirish if (rs != NPI_SUCCESS) 123344961713Sgirish goto fail; 123444961713Sgirish nxgep->mac.ctrltype = 0x8808; 123544961713Sgirish 123644961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 123744961713Sgirish if (rs != NPI_SUCCESS) 123844961713Sgirish goto fail; 123944961713Sgirish nxgep->mac.pa_size = 0x7; 124044961713Sgirish 124144961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 124244961713Sgirish CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 124344961713Sgirish goto fail; 124444961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 124544961713Sgirish } 124644961713Sgirish 124744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 124844961713Sgirish portn)); 124944961713Sgirish 125044961713Sgirish return (NXGE_OK); 125144961713Sgirish fail: 125244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 125344961713Sgirish "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 125444961713Sgirish portn)); 125544961713Sgirish 125644961713Sgirish return (NXGE_ERROR | rs); 125744961713Sgirish } 125844961713Sgirish 125944961713Sgirish /* Initialize the RxMAC sub-block */ 126044961713Sgirish 126144961713Sgirish nxge_status_t 126244961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 126344961713Sgirish { 126444961713Sgirish npi_attr_t ap; 126544961713Sgirish uint32_t i; 126644961713Sgirish uint16_t hashtab_e; 126744961713Sgirish p_hash_filter_t hash_filter; 126844961713Sgirish nxge_port_t portt; 126944961713Sgirish uint8_t portn; 127044961713Sgirish npi_handle_t handle; 127144961713Sgirish npi_status_t rs = NPI_SUCCESS; 127244961713Sgirish uint16_t *addr16p; 127344961713Sgirish uint16_t addr0, addr1, addr2; 127444961713Sgirish xmac_rx_config_t xconfig; 127544961713Sgirish bmac_rx_config_t bconfig; 127644961713Sgirish 127744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 127844961713Sgirish 127944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 128044961713Sgirish portn)); 128144961713Sgirish handle = nxgep->npi_handle; 128244961713Sgirish portt = nxgep->mac.porttype; 128344961713Sgirish 128444961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 128544961713Sgirish addr0 = ntohs(addr16p[2]); 128644961713Sgirish addr1 = ntohs(addr16p[1]); 128744961713Sgirish addr2 = ntohs(addr16p[0]); 128844961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 128944961713Sgirish rs); 129044961713Sgirish 129144961713Sgirish if (rs != NPI_SUCCESS) 129244961713Sgirish goto fail; 129344961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 129444961713Sgirish if (rs != NPI_SUCCESS) 129544961713Sgirish goto fail; 129644961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 129744961713Sgirish if (rs != NPI_SUCCESS) 129844961713Sgirish goto fail; 129944961713Sgirish 130044961713Sgirish /* 130144961713Sgirish * Load the multicast hash filter bits. 130244961713Sgirish */ 130344961713Sgirish hash_filter = nxgep->hash_filter; 130444961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 130544961713Sgirish if (hash_filter != NULL) { 130644961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 130744961713Sgirish (NMCFILTER_REGS - 1) - i]; 130844961713Sgirish } else { 130944961713Sgirish hashtab_e = 0; 131044961713Sgirish } 131144961713Sgirish 131244961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 131344961713Sgirish (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 131444961713Sgirish goto fail; 131544961713Sgirish } 131644961713Sgirish 131744961713Sgirish if (portt == PORT_TYPE_XMAC) { 131844961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 131944961713Sgirish 0)) != NPI_SUCCESS) 132044961713Sgirish goto fail; 132144961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 132244961713Sgirish 132344961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 132444961713Sgirish 132544961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 1326a3c5bd6dSspeer CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 1327a3c5bd6dSspeer ~CFG_XMAC_RX_STRIP_CRC; 132844961713Sgirish 132944961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 133044961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 133144961713Sgirish 133244961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 133344961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 133444961713Sgirish 133544961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 133644961713Sgirish 133744961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 133844961713Sgirish xconfig)) != NPI_SUCCESS) 133944961713Sgirish goto fail; 134044961713Sgirish nxgep->mac.rx_config = xconfig; 134144961713Sgirish 134244961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 134344961713Sgirish 134444961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 134544961713Sgirish != NPI_SUCCESS) 134644961713Sgirish goto fail; 134744961713Sgirish } else { 134844961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 134944961713Sgirish 135044961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 135144961713Sgirish 0) != NPI_SUCCESS) 135244961713Sgirish goto fail; 135344961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 135444961713Sgirish 1355a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 1356a3c5bd6dSspeer ~CFG_BMAC_RX_STRIP_CRC; 135744961713Sgirish 135844961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 135944961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 136044961713Sgirish 136144961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 136244961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 136344961713Sgirish 136444961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 136544961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 136644961713Sgirish bconfig)) != NPI_SUCCESS) 136744961713Sgirish goto fail; 136844961713Sgirish nxgep->mac.rx_config = bconfig; 136944961713Sgirish 137044961713Sgirish /* Always enable comparison of mac unique address */ 137144961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 137244961713Sgirish != NPI_SUCCESS) 137344961713Sgirish goto fail; 137444961713Sgirish } 137544961713Sgirish 137644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 137744961713Sgirish portn)); 137844961713Sgirish 137944961713Sgirish return (NXGE_OK); 138044961713Sgirish 138144961713Sgirish fail: 138244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 138344961713Sgirish "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 138444961713Sgirish portn)); 138544961713Sgirish 138644961713Sgirish return (NXGE_ERROR | rs); 138744961713Sgirish } 138844961713Sgirish 138944961713Sgirish /* Enable TXMAC */ 139044961713Sgirish 139144961713Sgirish nxge_status_t 139244961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 139344961713Sgirish { 139444961713Sgirish npi_handle_t handle; 139544961713Sgirish npi_status_t rs = NPI_SUCCESS; 139644961713Sgirish nxge_status_t status = NXGE_OK; 139744961713Sgirish 139844961713Sgirish handle = nxgep->npi_handle; 139944961713Sgirish 140044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 140144961713Sgirish nxgep->mac.portnum)); 140244961713Sgirish 140344961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 140444961713Sgirish goto fail; 140544961713Sgirish 140644961713Sgirish /* based on speed */ 140744961713Sgirish nxgep->msg_min = ETHERMIN; 140844961713Sgirish 140944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 141044961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 141144961713Sgirish CFG_XMAC_TX)) != NPI_SUCCESS) 141244961713Sgirish goto fail; 141344961713Sgirish } else { 141444961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 141544961713Sgirish CFG_BMAC_TX)) != NPI_SUCCESS) 141644961713Sgirish goto fail; 141744961713Sgirish } 141844961713Sgirish 141944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 142044961713Sgirish nxgep->mac.portnum)); 142144961713Sgirish 142244961713Sgirish return (NXGE_OK); 142344961713Sgirish fail: 142444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 142544961713Sgirish "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 142644961713Sgirish nxgep->mac.portnum)); 142744961713Sgirish if (rs != NPI_SUCCESS) 142844961713Sgirish return (NXGE_ERROR | rs); 142944961713Sgirish else 143044961713Sgirish return (status); 143144961713Sgirish } 143244961713Sgirish 143344961713Sgirish /* Disable TXMAC */ 143444961713Sgirish 143544961713Sgirish nxge_status_t 143644961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 143744961713Sgirish { 143844961713Sgirish npi_handle_t handle; 143944961713Sgirish npi_status_t rs = NPI_SUCCESS; 144044961713Sgirish 144144961713Sgirish handle = nxgep->npi_handle; 144244961713Sgirish 144344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 144444961713Sgirish nxgep->mac.portnum)); 144544961713Sgirish 144644961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 144744961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 144844961713Sgirish nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 144944961713Sgirish goto fail; 145044961713Sgirish } else { 145144961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 145244961713Sgirish nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 145344961713Sgirish goto fail; 145444961713Sgirish } 145544961713Sgirish 145644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 145744961713Sgirish nxgep->mac.portnum)); 145844961713Sgirish return (NXGE_OK); 145944961713Sgirish fail: 146044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 146144961713Sgirish "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 146244961713Sgirish nxgep->mac.portnum)); 146344961713Sgirish return (NXGE_ERROR | rs); 146444961713Sgirish } 146544961713Sgirish 146644961713Sgirish /* Enable RXMAC */ 146744961713Sgirish 146844961713Sgirish nxge_status_t 146944961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 147044961713Sgirish { 147144961713Sgirish npi_handle_t handle; 147244961713Sgirish uint8_t portn; 147344961713Sgirish npi_status_t rs = NPI_SUCCESS; 147444961713Sgirish nxge_status_t status = NXGE_OK; 147544961713Sgirish 147644961713Sgirish handle = nxgep->npi_handle; 147744961713Sgirish portn = nxgep->mac.portnum; 147844961713Sgirish 147944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 148044961713Sgirish portn)); 148144961713Sgirish 148244961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 148344961713Sgirish goto fail; 148444961713Sgirish 148544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 148644961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 148744961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 148844961713Sgirish goto fail; 148944961713Sgirish } else { 149044961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 149144961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 149244961713Sgirish goto fail; 149344961713Sgirish } 149444961713Sgirish 149544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 149644961713Sgirish portn)); 149744961713Sgirish 149844961713Sgirish return (NXGE_OK); 149944961713Sgirish fail: 150044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 150144961713Sgirish "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 150244961713Sgirish portn)); 150344961713Sgirish 150444961713Sgirish if (rs != NPI_SUCCESS) 150544961713Sgirish return (NXGE_ERROR | rs); 150644961713Sgirish else 150744961713Sgirish return (status); 150844961713Sgirish } 150944961713Sgirish 151044961713Sgirish /* Disable RXMAC */ 151144961713Sgirish 151244961713Sgirish nxge_status_t 151344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 151444961713Sgirish { 151544961713Sgirish npi_handle_t handle; 151644961713Sgirish uint8_t portn; 151744961713Sgirish npi_status_t rs = NPI_SUCCESS; 151844961713Sgirish 151944961713Sgirish handle = nxgep->npi_handle; 152044961713Sgirish portn = nxgep->mac.portnum; 152144961713Sgirish 152244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 152344961713Sgirish portn)); 152444961713Sgirish 152544961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 152644961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 152744961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 152844961713Sgirish goto fail; 152944961713Sgirish } else { 153044961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 153144961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 153244961713Sgirish goto fail; 153344961713Sgirish } 153444961713Sgirish 153544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 153644961713Sgirish portn)); 153744961713Sgirish return (NXGE_OK); 153844961713Sgirish fail: 153944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 154044961713Sgirish "nxgep_rx_mac_disable: ", 154144961713Sgirish "Failed to disable port<%d> RxMAC", 154244961713Sgirish portn)); 154344961713Sgirish 154444961713Sgirish return (NXGE_ERROR | rs); 154544961713Sgirish } 154644961713Sgirish 154744961713Sgirish /* Reset TXMAC */ 154844961713Sgirish 154944961713Sgirish nxge_status_t 155044961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 155144961713Sgirish { 155244961713Sgirish npi_handle_t handle; 155344961713Sgirish uint8_t portn; 155444961713Sgirish npi_status_t rs = NPI_SUCCESS; 155544961713Sgirish 155644961713Sgirish handle = nxgep->npi_handle; 155744961713Sgirish portn = nxgep->mac.portnum; 155844961713Sgirish 155944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 156044961713Sgirish portn)); 156144961713Sgirish 156244961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 156344961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 156444961713Sgirish != NPI_SUCCESS) 156544961713Sgirish goto fail; 156644961713Sgirish } else { 156744961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 156844961713Sgirish != NPI_SUCCESS) 156944961713Sgirish goto fail; 157044961713Sgirish } 157144961713Sgirish 157244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 157344961713Sgirish portn)); 157444961713Sgirish 157544961713Sgirish return (NXGE_OK); 157644961713Sgirish fail: 157744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 157844961713Sgirish "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 157944961713Sgirish portn)); 158044961713Sgirish 158144961713Sgirish return (NXGE_ERROR | rs); 158244961713Sgirish } 158344961713Sgirish 158444961713Sgirish /* Reset RXMAC */ 158544961713Sgirish 158644961713Sgirish nxge_status_t 158744961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 158844961713Sgirish { 158944961713Sgirish npi_handle_t handle; 159044961713Sgirish uint8_t portn; 159144961713Sgirish npi_status_t rs = NPI_SUCCESS; 159244961713Sgirish 159344961713Sgirish handle = nxgep->npi_handle; 159444961713Sgirish portn = nxgep->mac.portnum; 159544961713Sgirish 159644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 159744961713Sgirish portn)); 159844961713Sgirish 159944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 160044961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 160144961713Sgirish != NPI_SUCCESS) 160244961713Sgirish goto fail; 160344961713Sgirish } else { 160444961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 160544961713Sgirish != NPI_SUCCESS) 160644961713Sgirish goto fail; 160744961713Sgirish } 160844961713Sgirish 160944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 161044961713Sgirish portn)); 161144961713Sgirish 161244961713Sgirish return (NXGE_OK); 161344961713Sgirish fail: 161444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 161544961713Sgirish "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 161644961713Sgirish portn)); 161744961713Sgirish return (NXGE_ERROR | rs); 161844961713Sgirish } 161944961713Sgirish 162044961713Sgirish 162144961713Sgirish /* Enable/Disable MII Link Status change interrupt */ 162244961713Sgirish 162344961713Sgirish nxge_status_t 162444961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 162544961713Sgirish { 162644961713Sgirish uint8_t portn; 162744961713Sgirish nxge_port_mode_t portmode; 162844961713Sgirish npi_status_t rs = NPI_SUCCESS; 162944961713Sgirish 163044961713Sgirish portn = nxgep->mac.portnum; 163144961713Sgirish portmode = nxgep->mac.portmode; 163244961713Sgirish 163344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 163444961713Sgirish 163544961713Sgirish if (enable == LINK_INTR_START) { 163644961713Sgirish if (portmode == PORT_10G_FIBER) { 163744961713Sgirish if ((rs = npi_xmac_xpcs_link_intr_enable( 163844961713Sgirish nxgep->npi_handle, 163944961713Sgirish portn)) != NPI_SUCCESS) 164044961713Sgirish goto fail; 164144961713Sgirish } else if (portmode == PORT_1G_FIBER) { 164244961713Sgirish if ((rs = npi_mac_pcs_link_intr_enable( 164344961713Sgirish nxgep->npi_handle, 164444961713Sgirish portn)) != NPI_SUCCESS) 164544961713Sgirish goto fail; 164644961713Sgirish } else if (portmode == PORT_1G_COPPER) { 164744961713Sgirish if ((rs = npi_mac_mif_link_intr_enable( 164844961713Sgirish nxgep->npi_handle, 164944961713Sgirish portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS) 165044961713Sgirish goto fail; 165144961713Sgirish } else 165244961713Sgirish goto fail; 165344961713Sgirish } else if (enable == LINK_INTR_STOP) { 165444961713Sgirish if (portmode == PORT_10G_FIBER) { 165544961713Sgirish if ((rs = npi_xmac_xpcs_link_intr_disable( 165644961713Sgirish nxgep->npi_handle, 165744961713Sgirish portn)) != NPI_SUCCESS) 165844961713Sgirish goto fail; 165944961713Sgirish } else if (portmode == PORT_1G_FIBER) { 166044961713Sgirish if ((rs = npi_mac_pcs_link_intr_disable( 166144961713Sgirish nxgep->npi_handle, 166244961713Sgirish portn)) != NPI_SUCCESS) 166344961713Sgirish goto fail; 166444961713Sgirish } else if (portmode == PORT_1G_COPPER) { 166544961713Sgirish if ((rs = npi_mac_mif_link_intr_disable( 166644961713Sgirish nxgep->npi_handle, 166744961713Sgirish portn)) != NPI_SUCCESS) 166844961713Sgirish goto fail; 166944961713Sgirish } else 167044961713Sgirish goto fail; 167144961713Sgirish } 167244961713Sgirish 167344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 167444961713Sgirish 167544961713Sgirish return (NXGE_OK); 167644961713Sgirish fail: 167744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 167844961713Sgirish "nxge_link_intr: Failed to set port<%d> mif intr mode", 167944961713Sgirish portn)); 168044961713Sgirish 168144961713Sgirish return (NXGE_ERROR | rs); 168244961713Sgirish } 168344961713Sgirish 168444961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 168544961713Sgirish 168644961713Sgirish nxge_status_t 168744961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 168844961713Sgirish { 168944961713Sgirish p_nxge_param_t param_arr; 169044961713Sgirish p_nxge_stats_t statsp; 169144961713Sgirish uint8_t xcvr_portn; 169244961713Sgirish p_mii_regs_t mii_regs; 169344961713Sgirish mii_bmcr_t bmcr; 169444961713Sgirish mii_bmsr_t bmsr; 169544961713Sgirish mii_anar_t anar; 169644961713Sgirish mii_gcr_t gcr; 169744961713Sgirish mii_esr_t esr; 169844961713Sgirish mii_aux_ctl_t bcm5464r_aux; 169944961713Sgirish int status = NXGE_OK; 170044961713Sgirish 170144961713Sgirish uint_t delay; 170244961713Sgirish 170344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 170444961713Sgirish 170544961713Sgirish param_arr = nxgep->param_arr; 170644961713Sgirish statsp = nxgep->statsp; 170744961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 170844961713Sgirish 170944961713Sgirish mii_regs = NULL; 171044961713Sgirish 171144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 171244961713Sgirish "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 171344961713Sgirish 171444961713Sgirish /* 171544961713Sgirish * Reset the transceiver. 171644961713Sgirish */ 171744961713Sgirish delay = 0; 171844961713Sgirish bmcr.value = 0; 171944961713Sgirish bmcr.bits.reset = 1; 172044961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 172144961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 172244961713Sgirish goto fail; 172344961713Sgirish do { 172444961713Sgirish drv_usecwait(500); 172544961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 172644961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 172744961713Sgirish != NXGE_OK) 172844961713Sgirish goto fail; 172944961713Sgirish delay++; 173044961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 173144961713Sgirish if (delay == 1000) { 173244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 173344961713Sgirish goto fail; 173444961713Sgirish } 173544961713Sgirish 173644961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 173744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 173844961713Sgirish &bmsr.value)) != NXGE_OK) 173944961713Sgirish goto fail; 174044961713Sgirish 174144961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 174244961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 174344961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 174444961713Sgirish param_arr[param_anar_100hdx].value = 0; 174544961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 174644961713Sgirish param_arr[param_anar_10hdx].value = 0; 174744961713Sgirish 174844961713Sgirish /* 174958324dfcSspeer * Initialize the xcvr statistics. 175044961713Sgirish */ 175144961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 175244961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 175344961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 175444961713Sgirish statsp->mac_stats.cap_100hdx = 0; 175544961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 175644961713Sgirish statsp->mac_stats.cap_10hdx = 0; 175744961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 175844961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 175944961713Sgirish 176044961713Sgirish /* 176144961713Sgirish * Initialise the xcvr advertised capability statistics. 176244961713Sgirish */ 176344961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 176444961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 176544961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 176644961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 176744961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 176844961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 176944961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 177044961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 177144961713Sgirish statsp->mac_stats.adv_cap_asmpause = 177244961713Sgirish param_arr[param_anar_asmpause].value; 177344961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 177444961713Sgirish 177544961713Sgirish 177644961713Sgirish /* 177744961713Sgirish * Check for extended status just in case we're 177844961713Sgirish * running a Gigibit phy. 177944961713Sgirish */ 178044961713Sgirish if (bmsr.bits.extend_status) { 178144961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 178244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 178344961713Sgirish != NXGE_OK) 178444961713Sgirish goto fail; 178544961713Sgirish param_arr[param_anar_1000fdx].value &= 178644961713Sgirish esr.bits.link_1000fdx; 178744961713Sgirish param_arr[param_anar_1000hdx].value = 0; 178844961713Sgirish 178944961713Sgirish statsp->mac_stats.cap_1000fdx = 179044961713Sgirish (esr.bits.link_1000Xfdx || 179144961713Sgirish esr.bits.link_1000fdx); 179244961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 179344961713Sgirish } else { 179444961713Sgirish param_arr[param_anar_1000fdx].value = 0; 179544961713Sgirish param_arr[param_anar_1000hdx].value = 0; 179644961713Sgirish } 179744961713Sgirish 179844961713Sgirish /* 179944961713Sgirish * Initialize 1G Statistics once the capability is established. 180044961713Sgirish */ 180144961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 180244961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 180344961713Sgirish 180444961713Sgirish /* 180544961713Sgirish * Initialise the link statistics. 180644961713Sgirish */ 180744961713Sgirish statsp->mac_stats.link_T4 = 0; 180844961713Sgirish statsp->mac_stats.link_asmpause = 0; 180944961713Sgirish statsp->mac_stats.link_pause = 0; 181044961713Sgirish statsp->mac_stats.link_speed = 0; 181144961713Sgirish statsp->mac_stats.link_duplex = 0; 181244961713Sgirish statsp->mac_stats.link_up = 0; 181344961713Sgirish 181444961713Sgirish /* 181544961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 181644961713Sgirish */ 181744961713Sgirish bmcr.value = 0; 181844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 181944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 182044961713Sgirish goto fail; 182144961713Sgirish 182244961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 182344961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 182444961713Sgirish bmcr.bits.loopback = 1; 182544961713Sgirish bmcr.bits.enable_autoneg = 0; 182644961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 182744961713Sgirish bmcr.bits.speed_1000_sel = 1; 182844961713Sgirish bmcr.bits.duplex_mode = 1; 182944961713Sgirish param_arr[param_autoneg].value = 0; 183044961713Sgirish } else { 183144961713Sgirish bmcr.bits.loopback = 0; 183244961713Sgirish } 183344961713Sgirish 183444961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 183544961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 183644961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 183744961713Sgirish param_arr[param_autoneg].value = 0; 183844961713Sgirish bcm5464r_aux.value = 0; 183944961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 184044961713Sgirish bcm5464r_aux.bits.write_1 = 1; 184144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 184244961713Sgirish BCM5464R_AUX_CTL, bcm5464r_aux.value)) 184344961713Sgirish != NXGE_OK) 184444961713Sgirish goto fail; 184544961713Sgirish } 184644961713Sgirish 184744961713Sgirish if (param_arr[param_autoneg].value) { 184844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 184944961713Sgirish "Restarting Auto-negotiation.")); 185044961713Sgirish /* 185144961713Sgirish * Setup our Auto-negotiation advertisement register. 185244961713Sgirish */ 185344961713Sgirish anar.value = 0; 185444961713Sgirish anar.bits.selector = 1; 185544961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 185644961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 185744961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 185844961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 185944961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 186044961713Sgirish anar.bits.cap_asmpause = 0; 186144961713Sgirish anar.bits.cap_pause = 0; 186244961713Sgirish if (param_arr[param_anar_1000fdx].value || 186344961713Sgirish param_arr[param_anar_100fdx].value || 186444961713Sgirish param_arr[param_anar_10fdx].value) { 186544961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 186644961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 186744961713Sgirish } 186844961713Sgirish 186944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 187044961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 187144961713Sgirish != NXGE_OK) 187244961713Sgirish goto fail; 187344961713Sgirish if (bmsr.bits.extend_status) { 187444961713Sgirish gcr.value = 0; 187544961713Sgirish gcr.bits.ms_mode_en = 187644961713Sgirish param_arr[param_master_cfg_enable].value; 187744961713Sgirish gcr.bits.master = 187844961713Sgirish param_arr[param_master_cfg_value].value; 187944961713Sgirish gcr.bits.link_1000fdx = 188044961713Sgirish param_arr[param_anar_1000fdx].value; 188144961713Sgirish gcr.bits.link_1000hdx = 188244961713Sgirish param_arr[param_anar_1000hdx].value; 188344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 188444961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 188544961713Sgirish != NXGE_OK) 188644961713Sgirish goto fail; 188744961713Sgirish } 188844961713Sgirish 188944961713Sgirish bmcr.bits.enable_autoneg = 1; 189044961713Sgirish bmcr.bits.restart_autoneg = 1; 189144961713Sgirish 189244961713Sgirish } else { 189344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 189444961713Sgirish bmcr.bits.speed_1000_sel = 189544961713Sgirish param_arr[param_anar_1000fdx].value | 189644961713Sgirish param_arr[param_anar_1000hdx].value; 189744961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 189844961713Sgirish (param_arr[param_anar_100fdx].value | 189944961713Sgirish param_arr[param_anar_100hdx].value); 190044961713Sgirish if (bmcr.bits.speed_1000_sel) { 190144961713Sgirish statsp->mac_stats.link_speed = 1000; 190244961713Sgirish gcr.value = 0; 190344961713Sgirish gcr.bits.ms_mode_en = 190444961713Sgirish param_arr[param_master_cfg_enable].value; 190544961713Sgirish gcr.bits.master = 190644961713Sgirish param_arr[param_master_cfg_value].value; 190744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 190844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 190944961713Sgirish gcr.value)) 191044961713Sgirish != NXGE_OK) 191144961713Sgirish goto fail; 191244961713Sgirish if (param_arr[param_anar_1000fdx].value) { 191344961713Sgirish bmcr.bits.duplex_mode = 1; 191444961713Sgirish statsp->mac_stats.link_duplex = 2; 191544961713Sgirish } else 191644961713Sgirish statsp->mac_stats.link_duplex = 1; 191744961713Sgirish } else if (bmcr.bits.speed_sel) { 191844961713Sgirish statsp->mac_stats.link_speed = 100; 191944961713Sgirish if (param_arr[param_anar_100fdx].value) { 192044961713Sgirish bmcr.bits.duplex_mode = 1; 192144961713Sgirish statsp->mac_stats.link_duplex = 2; 192244961713Sgirish } else 192344961713Sgirish statsp->mac_stats.link_duplex = 1; 192444961713Sgirish } else { 192544961713Sgirish statsp->mac_stats.link_speed = 10; 192644961713Sgirish if (param_arr[param_anar_10fdx].value) { 192744961713Sgirish bmcr.bits.duplex_mode = 1; 192844961713Sgirish statsp->mac_stats.link_duplex = 2; 192944961713Sgirish } else 193044961713Sgirish statsp->mac_stats.link_duplex = 1; 193144961713Sgirish } 193244961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 193344961713Sgirish statsp->mac_stats.link_asmpause = 193444961713Sgirish statsp->mac_stats.cap_asmpause; 193544961713Sgirish statsp->mac_stats.link_pause = 193644961713Sgirish statsp->mac_stats.cap_pause; 193744961713Sgirish } 193844961713Sgirish 193944961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 194044961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 194144961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 194244961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 194344961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 194444961713Sgirish gcr.value = 0; 194544961713Sgirish gcr.bits.ms_mode_en = 1; 194644961713Sgirish gcr.bits.master = 1; 194744961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 194844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 194944961713Sgirish gcr.value)) 195044961713Sgirish != NXGE_OK) 195144961713Sgirish goto fail; 195244961713Sgirish bmcr.value = 0; 195344961713Sgirish bmcr.bits.speed_1000_sel = 1; 195444961713Sgirish statsp->mac_stats.link_speed = 1000; 195544961713Sgirish } else if (statsp->port_stats.lb_mode 195644961713Sgirish == nxge_lb_ext100) { 195744961713Sgirish /* BCM5464R 100mbps external loopback mode */ 195844961713Sgirish bmcr.value = 0; 195944961713Sgirish bmcr.bits.speed_sel = 1; 196044961713Sgirish bmcr.bits.duplex_mode = 1; 196144961713Sgirish statsp->mac_stats.link_speed = 100; 196244961713Sgirish } else if (statsp->port_stats.lb_mode 196344961713Sgirish == nxge_lb_ext10) { 196444961713Sgirish /* BCM5464R 10mbps external loopback mode */ 196544961713Sgirish bmcr.value = 0; 196644961713Sgirish bmcr.bits.duplex_mode = 1; 196744961713Sgirish statsp->mac_stats.link_speed = 10; 196844961713Sgirish } 196944961713Sgirish } 197044961713Sgirish } 197144961713Sgirish 197244961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 197344961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), 197444961713Sgirish bmcr.value)) != NXGE_OK) 197544961713Sgirish goto fail; 197644961713Sgirish 197744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 197844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 197944961713Sgirish goto fail; 198044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 198144961713Sgirish 198244961713Sgirish /* 198344961713Sgirish * Initialize the xcvr status kept in the context structure. 198444961713Sgirish */ 198544961713Sgirish nxgep->soft_bmsr.value = 0; 198644961713Sgirish 198744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 198844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 198944961713Sgirish &nxgep->bmsr.value)) != NXGE_OK) 199044961713Sgirish goto fail; 199144961713Sgirish 199244961713Sgirish statsp->mac_stats.xcvr_inits++; 199344961713Sgirish nxgep->bmsr.value = 0; 199444961713Sgirish 199544961713Sgirish fail: 199644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 199744961713Sgirish "<== nxge_mii_xcvr_init status 0x%x", status)); 199844961713Sgirish return (status); 199944961713Sgirish } 200044961713Sgirish 200144961713Sgirish /* Read from a MII compliant register */ 200244961713Sgirish 200344961713Sgirish nxge_status_t 200444961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 200544961713Sgirish uint16_t *value) 200644961713Sgirish { 200744961713Sgirish npi_status_t rs = NPI_SUCCESS; 200844961713Sgirish 200944961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 201044961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 201144961713Sgirish 201244961713Sgirish MUTEX_ENTER(&nxge_mii_lock); 201344961713Sgirish 201444961713Sgirish if (nxgep->mac.portmode == PORT_1G_COPPER) { 201544961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 201644961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 201744961713Sgirish goto fail; 201844961713Sgirish } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 201944961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 202044961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 202144961713Sgirish goto fail; 202244961713Sgirish } else 202344961713Sgirish goto fail; 202444961713Sgirish 202544961713Sgirish MUTEX_EXIT(&nxge_mii_lock); 202644961713Sgirish 202744961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 202844961713Sgirish "xcvr_reg<%d> value=0x%x", 202944961713Sgirish xcvr_portn, xcvr_reg, *value)); 203044961713Sgirish return (NXGE_OK); 203144961713Sgirish fail: 203244961713Sgirish MUTEX_EXIT(&nxge_mii_lock); 203344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 203444961713Sgirish "nxge_mii_read: Failed to read mii on xcvr %d", 203544961713Sgirish xcvr_portn)); 203644961713Sgirish 203744961713Sgirish return (NXGE_ERROR | rs); 203844961713Sgirish } 203944961713Sgirish 204044961713Sgirish /* Write to a MII compliant Register */ 204144961713Sgirish 204244961713Sgirish nxge_status_t 204344961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 204444961713Sgirish uint16_t value) 204544961713Sgirish { 204644961713Sgirish npi_status_t rs = NPI_SUCCESS; 204744961713Sgirish 204844961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 204944961713Sgirish "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 205044961713Sgirish value)); 205144961713Sgirish 205244961713Sgirish MUTEX_ENTER(&nxge_mii_lock); 205344961713Sgirish 205444961713Sgirish if (nxgep->mac.portmode == PORT_1G_COPPER) { 205544961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 205644961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 205744961713Sgirish goto fail; 205844961713Sgirish } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 205944961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 206044961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 206144961713Sgirish goto fail; 206244961713Sgirish } else 206344961713Sgirish goto fail; 206444961713Sgirish 206544961713Sgirish MUTEX_EXIT(&nxge_mii_lock); 206644961713Sgirish 206744961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 206844961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 206944961713Sgirish return (NXGE_OK); 207044961713Sgirish fail: 207144961713Sgirish MUTEX_EXIT(&nxge_mii_lock); 207244961713Sgirish 207344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 207444961713Sgirish "nxge_mii_write: Failed to write mii on xcvr %d", 207544961713Sgirish xcvr_portn)); 207644961713Sgirish 207744961713Sgirish return (NXGE_ERROR | rs); 207844961713Sgirish } 207944961713Sgirish 208044961713Sgirish /* Perform read from Clause45 serdes / transceiver device */ 208144961713Sgirish 208244961713Sgirish nxge_status_t 208344961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 208444961713Sgirish uint16_t xcvr_reg, uint16_t *value) 208544961713Sgirish { 208644961713Sgirish npi_status_t rs = NPI_SUCCESS; 208744961713Sgirish 208844961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 208944961713Sgirish xcvr_portn)); 209044961713Sgirish 209144961713Sgirish MUTEX_ENTER(&nxge_mdio_lock); 209244961713Sgirish 209344961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 209444961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 209544961713Sgirish goto fail; 209644961713Sgirish 209744961713Sgirish MUTEX_EXIT(&nxge_mdio_lock); 209844961713Sgirish 209944961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 210044961713Sgirish xcvr_portn)); 210144961713Sgirish return (NXGE_OK); 210244961713Sgirish fail: 210344961713Sgirish MUTEX_EXIT(&nxge_mdio_lock); 210444961713Sgirish 210544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 210644961713Sgirish "nxge_mdio_read: Failed to read mdio on xcvr %d", 210744961713Sgirish xcvr_portn)); 210844961713Sgirish 210944961713Sgirish return (NXGE_ERROR | rs); 211044961713Sgirish } 211144961713Sgirish 211244961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 211344961713Sgirish 211444961713Sgirish nxge_status_t 211544961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 211644961713Sgirish uint16_t xcvr_reg, uint16_t value) 211744961713Sgirish { 211844961713Sgirish npi_status_t rs = NPI_SUCCESS; 211944961713Sgirish 212044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 212144961713Sgirish xcvr_portn)); 212244961713Sgirish 212344961713Sgirish MUTEX_ENTER(&nxge_mdio_lock); 212444961713Sgirish 212544961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 212644961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 212744961713Sgirish goto fail; 212844961713Sgirish 212944961713Sgirish MUTEX_EXIT(&nxge_mdio_lock); 213044961713Sgirish 213144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 213244961713Sgirish xcvr_portn)); 213344961713Sgirish return (NXGE_OK); 213444961713Sgirish fail: 213544961713Sgirish MUTEX_EXIT(&nxge_mdio_lock); 213644961713Sgirish 213744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 213844961713Sgirish "nxge_mdio_write: Failed to write mdio on xcvr %d", 213944961713Sgirish xcvr_portn)); 214044961713Sgirish 214144961713Sgirish return (NXGE_ERROR | rs); 214244961713Sgirish } 214344961713Sgirish 214444961713Sgirish 214544961713Sgirish /* Check MII to see if there is any link status change */ 214644961713Sgirish 214744961713Sgirish nxge_status_t 2148a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 2149a3c5bd6dSspeer nxge_link_state_t *link_up) 215044961713Sgirish { 215144961713Sgirish p_nxge_param_t param_arr; 215244961713Sgirish p_nxge_stats_t statsp; 215344961713Sgirish p_mii_regs_t mii_regs; 215444961713Sgirish p_mii_bmsr_t soft_bmsr; 215544961713Sgirish mii_anar_t anar; 215644961713Sgirish mii_anlpar_t anlpar; 215744961713Sgirish mii_anar_t an_common; 215844961713Sgirish mii_aner_t aner; 215944961713Sgirish mii_gsr_t gsr; 216044961713Sgirish nxge_status_t status = NXGE_OK; 216144961713Sgirish 216244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 216344961713Sgirish 216444961713Sgirish mii_regs = NULL; 216544961713Sgirish param_arr = nxgep->param_arr; 216644961713Sgirish statsp = nxgep->statsp; 216744961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 2168a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 216944961713Sgirish 217044961713Sgirish if (bmsr_ints.bits.link_status) { 217144961713Sgirish if (bmsr.bits.link_status) { 217244961713Sgirish soft_bmsr->bits.link_status = 1; 217344961713Sgirish } else { 217444961713Sgirish statsp->mac_stats.link_up = 0; 217544961713Sgirish soft_bmsr->bits.link_status = 0; 217644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 217744961713Sgirish "Link down cable problem")); 2178a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 217944961713Sgirish } 218044961713Sgirish } 218144961713Sgirish 218244961713Sgirish if (param_arr[param_autoneg].value) { 218344961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 218444961713Sgirish if (bmsr.bits.auto_neg_complete) 218544961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 218644961713Sgirish else 218744961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 218844961713Sgirish } 218944961713Sgirish if (soft_bmsr->bits.link_status == 0) { 219044961713Sgirish statsp->mac_stats.link_T4 = 0; 219144961713Sgirish statsp->mac_stats.link_speed = 0; 219244961713Sgirish statsp->mac_stats.link_duplex = 0; 219344961713Sgirish statsp->mac_stats.link_asmpause = 0; 219444961713Sgirish statsp->mac_stats.link_pause = 0; 219544961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 219644961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 219744961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 219844961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 219944961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 220044961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 220144961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 220244961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 220344961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 220444961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 220544961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 220644961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 220744961713Sgirish } 220844961713Sgirish } else 220944961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 221044961713Sgirish 221144961713Sgirish if ((bmsr_ints.bits.link_status || 221244961713Sgirish bmsr_ints.bits.auto_neg_complete) && 221344961713Sgirish soft_bmsr->bits.link_status && 221444961713Sgirish soft_bmsr->bits.auto_neg_complete) { 221544961713Sgirish statsp->mac_stats.link_up = 1; 221644961713Sgirish if (param_arr[param_autoneg].value) { 221744961713Sgirish if ((status = nxge_mii_read(nxgep, 221844961713Sgirish statsp->mac_stats.xcvr_portn, 221944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), 222044961713Sgirish &anar.value)) != NXGE_OK) 222144961713Sgirish goto fail; 222244961713Sgirish if ((status = nxge_mii_read(nxgep, 222344961713Sgirish statsp->mac_stats.xcvr_portn, 222444961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anlpar), 222544961713Sgirish &anlpar.value)) != NXGE_OK) 222644961713Sgirish goto fail; 222744961713Sgirish if ((status = nxge_mii_read(nxgep, 222844961713Sgirish statsp->mac_stats.xcvr_portn, 222944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->aner), 223044961713Sgirish &aner.value)) != NXGE_OK) 223144961713Sgirish goto fail; 223244961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 223344961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 223444961713Sgirish statsp->mac_stats.lp_cap_100fdx = 223544961713Sgirish anlpar.bits.cap_100fdx; 223644961713Sgirish statsp->mac_stats.lp_cap_100hdx = 223744961713Sgirish anlpar.bits.cap_100hdx; 223844961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 223944961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 224044961713Sgirish statsp->mac_stats.lp_cap_asmpause = 224144961713Sgirish anlpar.bits.cap_asmpause; 224244961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 224344961713Sgirish an_common.value = anar.value & anlpar.value; 224444961713Sgirish if (param_arr[param_anar_1000fdx].value || 224544961713Sgirish param_arr[param_anar_1000hdx].value) { 224644961713Sgirish if ((status = nxge_mii_read(nxgep, 224744961713Sgirish statsp->mac_stats.xcvr_portn, 224844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gsr), 224944961713Sgirish &gsr.value)) 225044961713Sgirish != NXGE_OK) 225144961713Sgirish goto fail; 225244961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 225344961713Sgirish gsr.bits.link_1000fdx; 225444961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 225544961713Sgirish gsr.bits.link_1000hdx; 225644961713Sgirish if (param_arr[param_anar_1000fdx].value && 225744961713Sgirish gsr.bits.link_1000fdx) { 225844961713Sgirish statsp->mac_stats.link_speed = 1000; 225944961713Sgirish statsp->mac_stats.link_duplex = 2; 226044961713Sgirish } else if ( 226144961713Sgirish param_arr[param_anar_1000hdx].value && 226244961713Sgirish gsr.bits.link_1000hdx) { 226344961713Sgirish statsp->mac_stats.link_speed = 1000; 226444961713Sgirish statsp->mac_stats.link_duplex = 1; 226544961713Sgirish } 226644961713Sgirish } 226744961713Sgirish if ((an_common.value != 0) && 226844961713Sgirish !(statsp->mac_stats.link_speed)) { 226944961713Sgirish if (an_common.bits.cap_100T4) { 227044961713Sgirish statsp->mac_stats.link_T4 = 1; 227144961713Sgirish statsp->mac_stats.link_speed = 100; 227244961713Sgirish statsp->mac_stats.link_duplex = 1; 227344961713Sgirish } else if (an_common.bits.cap_100fdx) { 227444961713Sgirish statsp->mac_stats.link_speed = 100; 227544961713Sgirish statsp->mac_stats.link_duplex = 2; 227644961713Sgirish } else if (an_common.bits.cap_100hdx) { 227744961713Sgirish statsp->mac_stats.link_speed = 100; 227844961713Sgirish statsp->mac_stats.link_duplex = 1; 227944961713Sgirish } else if (an_common.bits.cap_10fdx) { 228044961713Sgirish statsp->mac_stats.link_speed = 10; 228144961713Sgirish statsp->mac_stats.link_duplex = 2; 228244961713Sgirish } else if (an_common.bits.cap_10hdx) { 228344961713Sgirish statsp->mac_stats.link_speed = 10; 228444961713Sgirish statsp->mac_stats.link_duplex = 1; 228544961713Sgirish } else { 228644961713Sgirish goto fail; 228744961713Sgirish } 228844961713Sgirish } 228944961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 229044961713Sgirish statsp->mac_stats.link_asmpause = 229144961713Sgirish an_common.bits.cap_asmpause; 229244961713Sgirish if (statsp->mac_stats.link_asmpause) 229344961713Sgirish if ((statsp->mac_stats.cap_pause == 0) && 229444961713Sgirish (statsp->mac_stats.lp_cap_pause 229544961713Sgirish == 1)) 229644961713Sgirish statsp->mac_stats.link_pause 229744961713Sgirish = 0; 229844961713Sgirish else 229944961713Sgirish statsp->mac_stats.link_pause 230044961713Sgirish = 1; 230144961713Sgirish else 230244961713Sgirish statsp->mac_stats.link_pause = 230344961713Sgirish an_common.bits.cap_pause; 230444961713Sgirish } 230544961713Sgirish } 2306a3c5bd6dSspeer *link_up = LINK_IS_UP; 2307a3c5bd6dSspeer } 2308a3c5bd6dSspeer 2309a3c5bd6dSspeer if (nxgep->link_notify) { 2310a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 2311a3c5bd6dSspeer LINK_IS_DOWN); 2312a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 231344961713Sgirish } 231444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 231544961713Sgirish return (NXGE_OK); 231644961713Sgirish fail: 231744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 231844961713Sgirish "nxge_mii_check: Unable to check MII")); 231944961713Sgirish return (status); 232044961713Sgirish } 232144961713Sgirish 232244961713Sgirish /* Add a multicast address entry into the HW hash table */ 232344961713Sgirish 232444961713Sgirish nxge_status_t 232544961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 232644961713Sgirish { 232744961713Sgirish uint32_t mchash; 232844961713Sgirish p_hash_filter_t hash_filter; 232944961713Sgirish uint16_t hash_bit; 233044961713Sgirish boolean_t rx_init = B_FALSE; 233144961713Sgirish uint_t j; 233244961713Sgirish nxge_status_t status = NXGE_OK; 233344961713Sgirish 233444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 233544961713Sgirish 233644961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 233744961713Sgirish mchash = crc32_mchash(addrp); 233844961713Sgirish if (nxgep->hash_filter == NULL) { 233944961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 234044961713Sgirish "Allocating hash filter storage.")); 234144961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 234244961713Sgirish KM_SLEEP); 234344961713Sgirish } 234444961713Sgirish hash_filter = nxgep->hash_filter; 234544961713Sgirish j = mchash / HASH_REG_WIDTH; 234644961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 234744961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 234844961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 234944961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 235044961713Sgirish hash_filter->hash_ref_cnt++; 235144961713Sgirish rx_init = B_TRUE; 235244961713Sgirish } 235344961713Sgirish if (rx_init) { 235444961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 235544961713Sgirish goto fail; 235644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 235744961713Sgirish goto fail; 235844961713Sgirish } 235944961713Sgirish 236044961713Sgirish RW_EXIT(&nxgep->filter_lock); 236144961713Sgirish 236244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 236344961713Sgirish 236444961713Sgirish return (NXGE_OK); 236544961713Sgirish fail: 236644961713Sgirish RW_EXIT(&nxgep->filter_lock); 236744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 236844961713Sgirish "Unable to add multicast address")); 236944961713Sgirish return (status); 237044961713Sgirish } 237144961713Sgirish 237244961713Sgirish /* Remove a multicast address entry from the HW hash table */ 237344961713Sgirish 237444961713Sgirish nxge_status_t 237544961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 237644961713Sgirish { 237744961713Sgirish uint32_t mchash; 237844961713Sgirish p_hash_filter_t hash_filter; 237944961713Sgirish uint16_t hash_bit; 238044961713Sgirish boolean_t rx_init = B_FALSE; 238144961713Sgirish uint_t j; 238244961713Sgirish nxge_status_t status = NXGE_OK; 238344961713Sgirish 238444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 238544961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 238644961713Sgirish mchash = crc32_mchash(addrp); 238744961713Sgirish if (nxgep->hash_filter == NULL) { 238844961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 238944961713Sgirish "Hash filter already de_allocated.")); 239044961713Sgirish RW_EXIT(&nxgep->filter_lock); 239144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 239244961713Sgirish return (NXGE_OK); 239344961713Sgirish } 239444961713Sgirish hash_filter = nxgep->hash_filter; 239544961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 239644961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 239744961713Sgirish j = mchash / HASH_REG_WIDTH; 239844961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 239944961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 240044961713Sgirish hash_filter->hash_ref_cnt--; 240144961713Sgirish rx_init = B_TRUE; 240244961713Sgirish } 240344961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 240444961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 240544961713Sgirish "De-allocating hash filter storage.")); 240644961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 240744961713Sgirish nxgep->hash_filter = NULL; 240844961713Sgirish } 240944961713Sgirish 241044961713Sgirish if (rx_init) { 241144961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 241244961713Sgirish goto fail; 241344961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 241444961713Sgirish goto fail; 241544961713Sgirish } 241644961713Sgirish RW_EXIT(&nxgep->filter_lock); 241744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 241844961713Sgirish 241944961713Sgirish return (NXGE_OK); 242044961713Sgirish fail: 242144961713Sgirish RW_EXIT(&nxgep->filter_lock); 242244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 242344961713Sgirish "Unable to remove multicast address")); 242444961713Sgirish 242544961713Sgirish return (status); 242644961713Sgirish } 242744961713Sgirish 242844961713Sgirish /* Set MAC address into MAC address HW registers */ 242944961713Sgirish 243044961713Sgirish nxge_status_t 243144961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 243244961713Sgirish { 243344961713Sgirish nxge_status_t status = NXGE_OK; 243444961713Sgirish 243544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 243644961713Sgirish 243744961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 243844961713Sgirish /* 243944961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 244044961713Sgirish */ 244144961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 244244961713Sgirish (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 244344961713Sgirish (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 244444961713Sgirish goto nxge_set_mac_addr_exit; 244544961713Sgirish } 244644961713Sgirish nxgep->ouraddr = *addrp; 244744961713Sgirish /* 244844961713Sgirish * Set new interface local address and re-init device. 244944961713Sgirish * This is destructive to any other streams attached 245044961713Sgirish * to this device. 245144961713Sgirish */ 245244961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 245344961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 245444961713Sgirish goto fail; 245544961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 245644961713Sgirish goto fail; 245744961713Sgirish 245844961713Sgirish RW_EXIT(&nxgep->filter_lock); 245944961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 246044961713Sgirish goto nxge_set_mac_addr_end; 246144961713Sgirish nxge_set_mac_addr_exit: 246244961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 246344961713Sgirish nxge_set_mac_addr_end: 246444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 246544961713Sgirish 246644961713Sgirish return (NXGE_OK); 246744961713Sgirish fail: 246844961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 246944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 247044961713Sgirish "Unable to set mac address")); 247144961713Sgirish return (status); 247244961713Sgirish } 247344961713Sgirish 2474*98ecde52Stm static 2475*98ecde52Stm check_link_state_t 2476*98ecde52Stm nxge_check_link_stop( 2477*98ecde52Stm nxge_t *nxge) 2478*98ecde52Stm { 2479*98ecde52Stm /* If the poll has been cancelled, return STOP. */ 2480*98ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 2481*98ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 2482*98ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 2483*98ecde52Stm nxge->nxge_link_poll_timerid = 0; 2484*98ecde52Stm cv_broadcast(&nxge->poll_cv); 2485*98ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 2486*98ecde52Stm 2487*98ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 2488*98ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 2489*98ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 2490*98ecde52Stm nxge->mac.portnum)); 2491*98ecde52Stm return (CHECK_LINK_STOP); 2492*98ecde52Stm } 2493*98ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 2494*98ecde52Stm 2495*98ecde52Stm return (CHECK_LINK_RESCHEDULE); 2496*98ecde52Stm } 2497*98ecde52Stm 249844961713Sgirish /* Check status of MII (MIF or PCS) link */ 249944961713Sgirish 250044961713Sgirish nxge_status_t 250144961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 250244961713Sgirish { 250344961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 250444961713Sgirish mii_anlpar_t anlpar; 250544961713Sgirish mii_gsr_t gsr; 250644961713Sgirish p_mii_regs_t mii_regs; 250744961713Sgirish nxge_status_t status = NXGE_OK; 250844961713Sgirish uint8_t portn; 2509a3c5bd6dSspeer nxge_link_state_t link_up; 251044961713Sgirish 2511*98ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 2512*98ecde52Stm return (NXGE_ERROR); 2513*98ecde52Stm 2514*98ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2515*98ecde52Stm return (NXGE_OK); 2516*98ecde52Stm 251744961713Sgirish portn = nxgep->mac.portnum; 251844961713Sgirish 251944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 2520*98ecde52Stm portn)); 252144961713Sgirish 252244961713Sgirish mii_regs = NULL; 252344961713Sgirish 252444961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 252544961713Sgirish 252644961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 252744961713Sgirish goto nxge_check_mii_link_exit; 252844961713Sgirish 252944961713Sgirish if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 253044961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 253144961713Sgirish &bmsr_data.value)) != NXGE_OK) 253244961713Sgirish goto fail; 253344961713Sgirish 253444961713Sgirish if (nxgep->param_arr[param_autoneg].value) { 253544961713Sgirish if ((status = nxge_mii_read(nxgep, 253644961713Sgirish nxgep->statsp->mac_stats.xcvr_portn, 253744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gsr), 253844961713Sgirish &gsr.value)) != NXGE_OK) 253944961713Sgirish goto fail; 254044961713Sgirish if ((status = nxge_mii_read(nxgep, 254144961713Sgirish nxgep->statsp->mac_stats.xcvr_portn, 254244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anlpar), 254344961713Sgirish &anlpar.value)) != NXGE_OK) 254444961713Sgirish goto fail; 254544961713Sgirish if (nxgep->statsp->mac_stats.link_up && 254644961713Sgirish ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 254744961713Sgirish gsr.bits.link_1000fdx) || 254844961713Sgirish (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 254944961713Sgirish gsr.bits.link_1000hdx) || 255044961713Sgirish (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 255144961713Sgirish anlpar.bits.cap_100T4) || 255244961713Sgirish (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 255344961713Sgirish anlpar.bits.cap_100fdx) || 255444961713Sgirish (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 255544961713Sgirish anlpar.bits.cap_100hdx) || 255644961713Sgirish (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 255744961713Sgirish anlpar.bits.cap_10fdx) || 255844961713Sgirish (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 255944961713Sgirish anlpar.bits.cap_10hdx))) { 256044961713Sgirish bmsr_data.bits.link_status = 0; 256144961713Sgirish } 256244961713Sgirish } 256344961713Sgirish 256444961713Sgirish /* Workaround for link down issue */ 256544961713Sgirish if (bmsr_data.value == 0) { 256644961713Sgirish cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 256744961713Sgirish goto nxge_check_mii_link_exit; 256844961713Sgirish } 256944961713Sgirish 257044961713Sgirish bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 257144961713Sgirish nxgep->bmsr.value = bmsr_data.value; 2572a3c5bd6dSspeer if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up)) 2573*98ecde52Stm != NXGE_OK) 257444961713Sgirish goto fail; 257544961713Sgirish 257644961713Sgirish nxge_check_mii_link_exit: 257744961713Sgirish RW_EXIT(&nxgep->filter_lock); 2578a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 2579a3c5bd6dSspeer nxge_link_is_up(nxgep); 2580a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 2581a3c5bd6dSspeer nxge_link_is_down(nxgep); 2582a3c5bd6dSspeer } 258344961713Sgirish 258444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 258544961713Sgirish 258644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 2587*98ecde52Stm portn)); 258844961713Sgirish return (NXGE_OK); 258944961713Sgirish 259044961713Sgirish fail: 259144961713Sgirish RW_EXIT(&nxgep->filter_lock); 259244961713Sgirish 259344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 259444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2595*98ecde52Stm "nxge_check_mii_link: Failed to check link port<%d>", 2596*98ecde52Stm portn)); 259744961713Sgirish return (status); 259844961713Sgirish } 259944961713Sgirish 260044961713Sgirish 260144961713Sgirish /*ARGSUSED*/ 260244961713Sgirish nxge_status_t 260344961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 260444961713Sgirish { 260544961713Sgirish uint8_t portn; 260614ea4bb7Ssd 260744961713Sgirish nxge_status_t status = NXGE_OK; 260844961713Sgirish boolean_t link_up; 260944961713Sgirish 2610*98ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 2611*98ecde52Stm return (NXGE_ERROR); 2612*98ecde52Stm 2613*98ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2614*98ecde52Stm return (NXGE_OK); 2615*98ecde52Stm 261644961713Sgirish portn = nxgep->mac.portnum; 261744961713Sgirish 261844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 2619*98ecde52Stm portn)); 262044961713Sgirish 262144961713Sgirish status = nxge_check_bcm8704_link(nxgep, &link_up); 262244961713Sgirish 262344961713Sgirish if (status != NXGE_OK) 262444961713Sgirish goto fail; 262544961713Sgirish 262644961713Sgirish if (link_up) { 2627a3c5bd6dSspeer if (nxgep->link_notify || 2628a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 0) { 262944961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 263044961713Sgirish goto fail; 263144961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 263244961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 263344961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 263444961713Sgirish 263544961713Sgirish nxge_link_is_up(nxgep); 2636a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 263744961713Sgirish } 263844961713Sgirish } else { 2639a3c5bd6dSspeer if (nxgep->link_notify || 2640a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 1) { 264144961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 264244961713Sgirish goto fail; 264344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 264444961713Sgirish "Link down cable problem")); 264544961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 264644961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 264744961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 264844961713Sgirish 264944961713Sgirish nxge_link_is_down(nxgep); 2650a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 265144961713Sgirish } 265244961713Sgirish } 265344961713Sgirish 265444961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 265544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 2656*98ecde52Stm portn)); 265744961713Sgirish return (NXGE_OK); 265844961713Sgirish 265944961713Sgirish fail: 2660*98ecde52Stm (void) nxge_check_link_stop(nxgep); 2661*98ecde52Stm 266244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2663*98ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 2664*98ecde52Stm portn)); 266544961713Sgirish return (status); 266644961713Sgirish } 266744961713Sgirish 266844961713Sgirish 266944961713Sgirish /* Declare link down */ 267044961713Sgirish 267144961713Sgirish void 267244961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 267344961713Sgirish { 267444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 267544961713Sgirish 267644961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 267744961713Sgirish 267844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 267944961713Sgirish } 268044961713Sgirish 268144961713Sgirish /* Declare link up */ 268244961713Sgirish 268344961713Sgirish void 268444961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 268544961713Sgirish { 268644961713Sgirish uint32_t val; 268744961713Sgirish 268844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 268944961713Sgirish 269044961713Sgirish (void) nxge_xif_init(nxgep); 269144961713Sgirish 269244961713Sgirish /* Clean up symbol errors incurred during link transition */ 269344961713Sgirish if (nxgep->mac.portmode == PORT_10G_FIBER) { 269444961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 269544961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 269644961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 269744961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 269844961713Sgirish } 269944961713Sgirish 270044961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 270144961713Sgirish 270244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 270344961713Sgirish } 270444961713Sgirish 270544961713Sgirish /* 270644961713Sgirish * Calculate the bit in the multicast address filter 270744961713Sgirish * that selects the given * address. 270844961713Sgirish * Note: For GEM, the last 8-bits are used. 270944961713Sgirish */ 271044961713Sgirish uint32_t 271144961713Sgirish crc32_mchash(p_ether_addr_t addr) 271244961713Sgirish { 271344961713Sgirish uint8_t *cp; 271444961713Sgirish uint32_t crc; 271544961713Sgirish uint32_t c; 271644961713Sgirish int byte; 271744961713Sgirish int bit; 271844961713Sgirish 271944961713Sgirish cp = (uint8_t *)addr; 272044961713Sgirish crc = (uint32_t)0xffffffff; 272144961713Sgirish for (byte = 0; byte < 6; byte++) { 272244961713Sgirish c = (uint32_t)cp[byte]; 272344961713Sgirish for (bit = 0; bit < 8; bit++) { 272444961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 272544961713Sgirish crc = (crc >> 1)^0xedb88320; 272644961713Sgirish else 272744961713Sgirish crc = (crc >> 1); 272844961713Sgirish c >>= 1; 272944961713Sgirish } 273044961713Sgirish } 273144961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 273244961713Sgirish } 273344961713Sgirish 273444961713Sgirish /* Reset serdes */ 273544961713Sgirish 273644961713Sgirish nxge_status_t 273744961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 273844961713Sgirish { 273944961713Sgirish npi_handle_t handle; 274044961713Sgirish 274144961713Sgirish handle = nxgep->npi_handle; 274244961713Sgirish 274344961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 274444961713Sgirish drv_usecwait(500); 274544961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 274644961713Sgirish 274744961713Sgirish return (NXGE_OK); 274844961713Sgirish } 274944961713Sgirish 275044961713Sgirish /* Monitor link status using interrupt or polling */ 275144961713Sgirish 275244961713Sgirish nxge_status_t 275344961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 275444961713Sgirish { 275544961713Sgirish nxge_status_t status = NXGE_OK; 275644961713Sgirish 275744961713Sgirish /* 2758*98ecde52Stm * Return immediately if this is an imaginary XMAC port. 2759*98ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 276044961713Sgirish */ 276144961713Sgirish if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1)) 276244961713Sgirish return (NXGE_OK); 276344961713Sgirish 276444961713Sgirish if (nxgep->statsp == NULL) { 276544961713Sgirish /* stats has not been allocated. */ 276644961713Sgirish return (NXGE_OK); 276744961713Sgirish } 276844961713Sgirish /* Don't check link if we're not in internal loopback mode */ 276944961713Sgirish if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 277044961713Sgirish return (NXGE_OK); 277144961713Sgirish 277244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2773*98ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 2774*98ecde52Stm nxgep->mac.portnum, enable)); 277544961713Sgirish if (enable == LINK_MONITOR_START) { 277644961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 277744961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 2778*98ecde52Stm != NXGE_OK) 277944961713Sgirish goto fail; 278044961713Sgirish } else { 2781*98ecde52Stm timeout_id_t timerid; 2782*98ecde52Stm 2783*98ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2784*98ecde52Stm return (NXGE_OK); 2785*98ecde52Stm 278644961713Sgirish switch (nxgep->mac.portmode) { 278744961713Sgirish case PORT_10G_FIBER: 2788*98ecde52Stm timerid = timeout((fptrv_t)nxge_check_10g_link, 2789*98ecde52Stm nxgep, 2790*98ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 2791*98ecde52Stm break; 279244961713Sgirish 279344961713Sgirish case PORT_1G_COPPER: 279444961713Sgirish case PORT_1G_FIBER: 2795*98ecde52Stm timerid = timeout((fptrv_t)nxge_check_mii_link, 2796*98ecde52Stm nxgep, 2797*98ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 2798*98ecde52Stm break; 279944961713Sgirish default: 2800*98ecde52Stm return (NXGE_ERROR); 280144961713Sgirish } 2802*98ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 2803*98ecde52Stm nxgep->nxge_link_poll_timerid = timerid; 2804*98ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 280544961713Sgirish } 280644961713Sgirish } else { 280744961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 280844961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 2809*98ecde52Stm != NXGE_OK) 281044961713Sgirish goto fail; 281144961713Sgirish } else { 2812*98ecde52Stm clock_t rv; 2813*98ecde52Stm 2814*98ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 2815*98ecde52Stm 2816*98ecde52Stm /* If <timerid> == 0, the link monitor has */ 2817*98ecde52Stm /* never been started, or just now stopped. */ 2818*98ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 2819*98ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 2820*98ecde52Stm return (NXGE_OK); 2821*98ecde52Stm } 2822*98ecde52Stm 2823*98ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 2824*98ecde52Stm rv = cv_timedwait(&nxgep->poll_cv, 2825*98ecde52Stm &nxgep->poll_lock, 2826*98ecde52Stm ddi_get_lbolt() + 2827*98ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 2828*98ecde52Stm LINK_MONITOR_PERIOD)); 2829*98ecde52Stm if (rv == -1) { 2830*98ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2831*98ecde52Stm "==> stopping port %d: " 2832*98ecde52Stm "cv_timedwait(%d) timed out", 2833*98ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 2834*98ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 283544961713Sgirish nxgep->nxge_link_poll_timerid = 0; 283644961713Sgirish } 2837*98ecde52Stm 2838*98ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 283944961713Sgirish } 284044961713Sgirish } 284144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2842*98ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 2843*98ecde52Stm nxgep->mac.portnum, enable)); 284444961713Sgirish return (NXGE_OK); 284544961713Sgirish fail: 284644961713Sgirish return (status); 284744961713Sgirish } 284844961713Sgirish 284944961713Sgirish /* Set promiscous mode */ 285044961713Sgirish 285144961713Sgirish nxge_status_t 285244961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 285344961713Sgirish { 285444961713Sgirish nxge_status_t status = NXGE_OK; 285544961713Sgirish 285644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 285744961713Sgirish "==> nxge_set_promisc: on %d", on)); 285844961713Sgirish 285944961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 286044961713Sgirish 286144961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 286244961713Sgirish 286344961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 286444961713Sgirish goto fail; 286544961713Sgirish } 286644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 286744961713Sgirish goto fail; 286844961713Sgirish } 286944961713Sgirish 287044961713Sgirish RW_EXIT(&nxgep->filter_lock); 287144961713Sgirish 287244961713Sgirish if (on) 287344961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 287444961713Sgirish else 287544961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 287644961713Sgirish 287744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 287844961713Sgirish 287944961713Sgirish return (NXGE_OK); 288044961713Sgirish fail: 288144961713Sgirish RW_EXIT(&nxgep->filter_lock); 288244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 288344961713Sgirish "Unable to set promisc (%d)", on)); 288444961713Sgirish 288544961713Sgirish return (status); 288644961713Sgirish } 288744961713Sgirish 288844961713Sgirish /*ARGSUSED*/ 288944961713Sgirish uint_t 289044961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 289144961713Sgirish { 289244961713Sgirish #ifdef NXGE_DEBUG 289344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 289444961713Sgirish #endif 289544961713Sgirish #if NXGE_MIF 289644961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 289744961713Sgirish uint32_t status; 289844961713Sgirish npi_handle_t handle; 289944961713Sgirish uint8_t portn; 290044961713Sgirish p_nxge_stats_t statsp; 290144961713Sgirish #endif 290244961713Sgirish 290344961713Sgirish #ifdef NXGE_MIF 290444961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 290544961713Sgirish nxgep = ldvp->nxgep; 290644961713Sgirish } 290744961713Sgirish nxgep = ldvp->nxgep; 290844961713Sgirish #endif 290944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 291044961713Sgirish 291144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 291244961713Sgirish return (DDI_INTR_CLAIMED); 291344961713Sgirish 291444961713Sgirish mif_intr_fail: 291544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 291644961713Sgirish return (DDI_INTR_UNCLAIMED); 291744961713Sgirish } 291844961713Sgirish 291944961713Sgirish /*ARGSUSED*/ 292044961713Sgirish uint_t 292144961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 292244961713Sgirish { 292344961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 292444961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 292544961713Sgirish p_nxge_ldg_t ldgp; 292644961713Sgirish uint32_t status; 292744961713Sgirish npi_handle_t handle; 292844961713Sgirish uint8_t portn; 292944961713Sgirish p_nxge_stats_t statsp; 293044961713Sgirish npi_status_t rs = NPI_SUCCESS; 293144961713Sgirish 293244961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 293344961713Sgirish nxgep = ldvp->nxgep; 293444961713Sgirish } 293544961713Sgirish 293644961713Sgirish ldgp = ldvp->ldgp; 293744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 293844961713Sgirish "group %d", ldgp->ldg)); 293944961713Sgirish 294044961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 294144961713Sgirish /* 294244961713Sgirish * This interrupt handler is for a specific 294344961713Sgirish * mac port. 294444961713Sgirish */ 294544961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 294644961713Sgirish portn = nxgep->mac.portnum; 294744961713Sgirish 294844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 294944961713Sgirish "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 295044961713Sgirish 295144961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 295244961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 295344961713Sgirish (xmac_tx_iconfig_t *)&status); 295444961713Sgirish if (rs != NPI_SUCCESS) 295544961713Sgirish goto npi_fail; 295644961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 295744961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 295844961713Sgirish statsp->xmac_stats.tx_underflow_err++; 295944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 296044961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 296144961713Sgirish } 296244961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 296344961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 296444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 296544961713Sgirish NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 296644961713Sgirish } 296744961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 296844961713Sgirish statsp->xmac_stats.tx_overflow_err++; 296944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 297044961713Sgirish NXGE_FM_EREPORT_TXMAC_OVERFLOW); 297144961713Sgirish } 297244961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 297344961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 297444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 297544961713Sgirish NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 297644961713Sgirish } 297744961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 297844961713Sgirish statsp->xmac_stats.tx_byte_cnt += 297944961713Sgirish XTXMAC_BYTE_CNT_MASK; 298044961713Sgirish } 298144961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 298244961713Sgirish statsp->xmac_stats.tx_frame_cnt += 298344961713Sgirish XTXMAC_FRM_CNT_MASK; 298444961713Sgirish } 298544961713Sgirish } 298644961713Sgirish 298744961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 298844961713Sgirish (xmac_rx_iconfig_t *)&status); 298944961713Sgirish if (rs != NPI_SUCCESS) 299044961713Sgirish goto npi_fail; 299144961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 299244961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 299344961713Sgirish statsp->xmac_stats.rx_overflow_err++; 299444961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 299544961713Sgirish statsp->xmac_stats.rx_underflow_err++; 299644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 299744961713Sgirish NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 299844961713Sgirish } 299944961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 300044961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 300144961713Sgirish XRXMAC_CRC_ER_CNT_MASK; 300244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 300344961713Sgirish NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 300444961713Sgirish } 300544961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 300644961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 300744961713Sgirish MAC_LEN_ER_CNT_MASK; 300844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 300944961713Sgirish NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 301044961713Sgirish } 301144961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 301244961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 301344961713Sgirish XRXMAC_CD_VIO_CNT_MASK; 301444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 301544961713Sgirish NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 301644961713Sgirish } 301744961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 301844961713Sgirish statsp->xmac_stats.rx_byte_cnt += 301944961713Sgirish XRXMAC_BT_CNT_MASK; 302044961713Sgirish } 302144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 302244961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 302344961713Sgirish XRXMAC_HIST_CNT1_MASK; 302444961713Sgirish } 302544961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 302644961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 302744961713Sgirish XRXMAC_HIST_CNT2_MASK; 302844961713Sgirish } 302944961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 303044961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 303144961713Sgirish XRXMAC_HIST_CNT3_MASK; 303244961713Sgirish } 303344961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 303444961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 303544961713Sgirish XRXMAC_HIST_CNT4_MASK; 303644961713Sgirish } 303744961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 303844961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 303944961713Sgirish XRXMAC_HIST_CNT5_MASK; 304044961713Sgirish } 304144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 304244961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 304344961713Sgirish XRXMAC_HIST_CNT6_MASK; 304444961713Sgirish } 304544961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 304644961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 304744961713Sgirish XRXMAC_BC_FRM_CNT_MASK; 304844961713Sgirish } 304944961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 305044961713Sgirish statsp->xmac_stats.rx_mult_cnt += 305144961713Sgirish XRXMAC_MC_FRM_CNT_MASK; 305244961713Sgirish } 305344961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 305444961713Sgirish statsp->xmac_stats.rx_frag_cnt += 305544961713Sgirish XRXMAC_FRAG_CNT_MASK; 305644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 305744961713Sgirish NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 305844961713Sgirish } 305944961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 306044961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 306144961713Sgirish XRXMAC_AL_ER_CNT_MASK; 306244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 306344961713Sgirish NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 306444961713Sgirish } 306544961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 306644961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 306744961713Sgirish XMAC_LINK_FLT_CNT_MASK; 306844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 306944961713Sgirish NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 307044961713Sgirish } 307144961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 307244961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 307344961713Sgirish } 307444961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 307544961713Sgirish statsp->xmac_stats.rx_localfault_err++; 307644961713Sgirish } 307744961713Sgirish } 307844961713Sgirish 307944961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 308044961713Sgirish (xmac_ctl_iconfig_t *)&status); 308144961713Sgirish if (rs != NPI_SUCCESS) 308244961713Sgirish goto npi_fail; 308344961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 308444961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 308544961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 308644961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 308744961713Sgirish statsp->xmac_stats.tx_pause_state++; 308844961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 308944961713Sgirish statsp->xmac_stats.tx_nopause_state++; 309044961713Sgirish } 309144961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 309244961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 309344961713Sgirish (bmac_tx_iconfig_t *)&status); 309444961713Sgirish if (rs != NPI_SUCCESS) 309544961713Sgirish goto npi_fail; 309644961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 309744961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 309844961713Sgirish statsp->bmac_stats.tx_underrun_err++; 309944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 310044961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 310144961713Sgirish } 310244961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 310344961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 310444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 310544961713Sgirish NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 310644961713Sgirish } 310744961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 310844961713Sgirish statsp->bmac_stats.tx_byte_cnt += 310944961713Sgirish BTXMAC_BYTE_CNT_MASK; 311044961713Sgirish } 311144961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 311244961713Sgirish statsp->bmac_stats.tx_frame_cnt += 311344961713Sgirish BTXMAC_FRM_CNT_MASK; 311444961713Sgirish } 311544961713Sgirish } 311644961713Sgirish 311744961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 311844961713Sgirish (bmac_rx_iconfig_t *)&status); 311944961713Sgirish if (rs != NPI_SUCCESS) 312044961713Sgirish goto npi_fail; 312144961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 312244961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 312344961713Sgirish statsp->bmac_stats.rx_overflow_err++; 312444961713Sgirish } 312544961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 312644961713Sgirish statsp->bmac_stats.rx_frame_cnt += 312744961713Sgirish RXMAC_FRM_CNT_MASK; 312844961713Sgirish } 312944961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 313044961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 313144961713Sgirish BMAC_CRC_ER_CNT_MASK; 313244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 313344961713Sgirish NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 313444961713Sgirish } 313544961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 313644961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 313744961713Sgirish MAC_LEN_ER_CNT_MASK; 313844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 313944961713Sgirish NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 314044961713Sgirish } 314144961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 314244961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 314344961713Sgirish BMAC_CD_VIO_CNT_MASK; 314444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 314544961713Sgirish NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 314644961713Sgirish } 314744961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 314844961713Sgirish statsp->bmac_stats.rx_byte_cnt += 314944961713Sgirish BRXMAC_BYTE_CNT_MASK; 315044961713Sgirish } 315144961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 315244961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 315344961713Sgirish BMAC_AL_ER_CNT_MASK; 315444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 315544961713Sgirish NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 315644961713Sgirish } 315744961713Sgirish 315844961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 315944961713Sgirish (bmac_ctl_iconfig_t *)&status); 316044961713Sgirish if (rs != NPI_SUCCESS) 316144961713Sgirish goto npi_fail; 316244961713Sgirish 316344961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 316444961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 316544961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 316644961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 316744961713Sgirish statsp->bmac_stats.tx_pause_state++; 316844961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 316944961713Sgirish statsp->bmac_stats.tx_nopause_state++; 317044961713Sgirish } 317144961713Sgirish } 317244961713Sgirish 317344961713Sgirish if (ldgp->nldvs == 1) { 317444961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 317544961713Sgirish B_TRUE, ldgp->ldg_timer); 317644961713Sgirish } 317744961713Sgirish 317844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 317944961713Sgirish return (DDI_INTR_CLAIMED); 318044961713Sgirish 318144961713Sgirish npi_fail: 318244961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 318344961713Sgirish return (DDI_INTR_UNCLAIMED); 318444961713Sgirish } 318544961713Sgirish 318644961713Sgirish nxge_status_t 318744961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 318844961713Sgirish { 318944961713Sgirish uint8_t phy_port_addr; 319044961713Sgirish nxge_status_t status = NXGE_OK; 319144961713Sgirish boolean_t rx_sig_ok; 319244961713Sgirish boolean_t pcs_blk_lock; 319344961713Sgirish boolean_t link_align; 319444961713Sgirish uint16_t val1, val2, val3; 319544961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 319644961713Sgirish uint16_t val_debug; 319744961713Sgirish uint16_t val; 319844961713Sgirish #endif 319944961713Sgirish 320044961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 320144961713Sgirish 320244961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 320344961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 320444961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 320544961713Sgirish if ((val_debug & ~0x200) != 0) { 320644961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 320744961713Sgirish nxgep->mac.portnum, val_debug); 320844961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 320944961713Sgirish &val_debug); 321044961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 321144961713Sgirish nxgep->mac.portnum, val_debug); 321244961713Sgirish } 321344961713Sgirish 321444961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 321544961713Sgirish XPCS_REG_DESCWERR_COUNTER, &val); 321644961713Sgirish if (val != 0) 321744961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 321844961713Sgirish 321944961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 322044961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 322144961713Sgirish if (val != 0) 322244961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 322344961713Sgirish 322444961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 322544961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 322644961713Sgirish if (val != 0) 322744961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 322844961713Sgirish #endif 322944961713Sgirish 323044961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 323144961713Sgirish 323244961713Sgirish /* Check Device 1 Register 0xA bit0 */ 323344961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 323444961713Sgirish BCM8704_PMA_PMD_DEV_ADDR, 323544961713Sgirish BCM8704_PMD_RECEIVE_SIG_DETECT, 323644961713Sgirish &val1); 323744961713Sgirish if (status != NXGE_OK) 323844961713Sgirish goto fail; 323944961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 324044961713Sgirish 324144961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 324244961713Sgirish if ((status = nxge_mdio_read(nxgep, phy_port_addr, 324344961713Sgirish BCM8704_PCS_DEV_ADDR, 324444961713Sgirish BCM8704_10GBASE_R_PCS_STATUS_REG, 324544961713Sgirish &val2)) != NPI_SUCCESS) 324644961713Sgirish goto fail; 324744961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 324844961713Sgirish 324944961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 325044961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 325144961713Sgirish BCM8704_PHYXS_ADDR, 325244961713Sgirish BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 325344961713Sgirish &val3); 325444961713Sgirish if (status != NXGE_OK) 325544961713Sgirish goto fail; 325644961713Sgirish link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 325744961713Sgirish XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 325844961713Sgirish XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 325944961713Sgirish 326044961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 326144961713Sgirish /* Temp workaround for link down issue */ 326244961713Sgirish if (pcs_blk_lock == B_FALSE) { 326344961713Sgirish if (val2 != 0x4) { 326444961713Sgirish pcs_blk_lock = B_TRUE; 326544961713Sgirish cmn_err(CE_NOTE, 326644961713Sgirish "!LINK DEBUG: port%d PHY Dev3 " 326744961713Sgirish "Reg 0x20 = 0x%x\n", 326844961713Sgirish nxgep->mac.portnum, val2); 326944961713Sgirish } 327044961713Sgirish } 327144961713Sgirish 327244961713Sgirish if (link_align == B_FALSE) { 327344961713Sgirish if (val3 != 0x140f) { 327444961713Sgirish link_align = B_TRUE; 327544961713Sgirish cmn_err(CE_NOTE, 327644961713Sgirish "!LINK DEBUG: port%d PHY Dev4 " 327744961713Sgirish "Reg 0x18 = 0x%x\n", 327844961713Sgirish nxgep->mac.portnum, val3); 327944961713Sgirish } 328044961713Sgirish } 328144961713Sgirish 328244961713Sgirish if (rx_sig_ok == B_FALSE) { 328344961713Sgirish if ((val2 == 0) || (val3 == 0)) { 328444961713Sgirish rx_sig_ok = B_TRUE; 328544961713Sgirish cmn_err(CE_NOTE, 328644961713Sgirish "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 328744961713Sgirish nxgep->mac.portnum); 328844961713Sgirish } 328944961713Sgirish } 329044961713Sgirish #endif 329144961713Sgirish 329244961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 329344961713Sgirish (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 329444961713Sgirish 329544961713Sgirish return (NXGE_OK); 329644961713Sgirish fail: 329744961713Sgirish return (status); 329844961713Sgirish } 329944961713Sgirish 330044961713Sgirish 330144961713Sgirish nxge_status_t 330244961713Sgirish nxge_get_xcvr_type(p_nxge_t nxgep) 330344961713Sgirish { 330444961713Sgirish nxge_status_t status = NXGE_OK; 330556d930aeSspeer char *phy_type; 330644961713Sgirish char *prop_val; 330744961713Sgirish 330856d930aeSspeer if (nxgep->niu_type == N2_NIU) { 330956d930aeSspeer if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 331056d930aeSspeer "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 331156d930aeSspeer if (strcmp("xgf", prop_val) == 0) { 331256d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = 331356d930aeSspeer XPCS_XCVR; 331456d930aeSspeer nxgep->mac.portmode = PORT_10G_FIBER; 331556d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 331656d930aeSspeer "10G Fiber Xcvr")); 331756d930aeSspeer } else if (strcmp("mif", prop_val) == 0) { 331856d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = 331956d930aeSspeer INT_MII_XCVR; 332056d930aeSspeer nxgep->mac.portmode = PORT_1G_COPPER; 332156d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 332256d930aeSspeer "1G Copper Xcvr")); 332356d930aeSspeer } else if (strcmp("pcs", prop_val) == 0) { 332456d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 332556d930aeSspeer nxgep->mac.portmode = PORT_1G_FIBER; 332656d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 332756d930aeSspeer "1G Fiber Xcvr")); 332856d930aeSspeer } else if (strcmp("xgc", prop_val) == 0) { 332956d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = 333056d930aeSspeer XPCS_XCVR; 333156d930aeSspeer nxgep->mac.portmode = PORT_10G_COPPER; 333256d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 333356d930aeSspeer "10G Copper Xcvr")); 333456d930aeSspeer } else { 333556d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 333656d930aeSspeer "Unknown phy-type: %s", prop_val)); 333756d930aeSspeer ddi_prop_free(prop_val); 333856d930aeSspeer return (NXGE_ERROR); 333956d930aeSspeer } 334056d930aeSspeer status = NXGE_OK; 334156d930aeSspeer (void) ddi_prop_update_string(DDI_DEV_T_NONE, 334256d930aeSspeer nxgep->dip, "phy-type", prop_val); 334356d930aeSspeer ddi_prop_free(prop_val); 334456d930aeSspeer return (status); 334544961713Sgirish } else { 334644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 334756d930aeSspeer "Exiting...phy-type property not found")); 334844961713Sgirish return (NXGE_ERROR); 334944961713Sgirish } 335056d930aeSspeer } 335156d930aeSspeer 335256d930aeSspeer if (!nxgep->vpd_info.ver_valid) { 335356d930aeSspeer /* 335456d930aeSspeer * read the phy type from the SEEPROM - NCR registers 335556d930aeSspeer */ 335656d930aeSspeer status = nxge_espc_phy_type_get(nxgep); 335756d930aeSspeer if (status != NXGE_OK) 335856d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 335956d930aeSspeer "[%s] invalid...please update", 336056d930aeSspeer nxgep->vpd_info.ver)); 336156d930aeSspeer return (status); 336256d930aeSspeer } 336356d930aeSspeer 336456d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 336556d930aeSspeer "Reading phy type from expansion ROM")); 336656d930aeSspeer /* 336756d930aeSspeer * Try to read the phy type from the vpd data read off the 336856d930aeSspeer * expansion ROM. 336956d930aeSspeer */ 337056d930aeSspeer phy_type = nxgep->vpd_info.phy_type; 337156d930aeSspeer if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') { 337256d930aeSspeer nxgep->mac.portmode = PORT_1G_COPPER; 337356d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 337456d930aeSspeer } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 337556d930aeSspeer phy_type[2] == 'f') { 337656d930aeSspeer nxgep->mac.portmode = PORT_10G_FIBER; 337756d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 337856d930aeSspeer } else if (phy_type[0] == 'p' && phy_type[1] == 'c' && 337956d930aeSspeer phy_type[2] == 's') { 338056d930aeSspeer nxgep->mac.portmode = PORT_1G_FIBER; 338156d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 338256d930aeSspeer } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 338356d930aeSspeer phy_type[2] == 'c') { 338456d930aeSspeer nxgep->mac.portmode = PORT_10G_COPPER; 338556d930aeSspeer nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 338644961713Sgirish } else { 338756d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 338856d930aeSspeer "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 338956d930aeSspeer phy_type[0], phy_type[1], phy_type[2])); 339044961713Sgirish /* 339156d930aeSspeer * read the phy type from the SEEPROM - NCR registers 339244961713Sgirish */ 339356d930aeSspeer status = nxge_espc_phy_type_get(nxgep); 339456d930aeSspeer if (status != NXGE_OK) 339556d930aeSspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 339656d930aeSspeer "[%s] invalid...please update", 339756d930aeSspeer nxgep->vpd_info.ver)); 339844961713Sgirish } 339944961713Sgirish 340044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 340144961713Sgirish return (status); 340244961713Sgirish } 340344961713Sgirish 340444961713Sgirish nxge_status_t 340544961713Sgirish nxge_10g_link_led_on(p_nxge_t nxgep) 340644961713Sgirish { 340744961713Sgirish if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 340844961713Sgirish != NPI_SUCCESS) 340944961713Sgirish return (NXGE_ERROR); 341044961713Sgirish else 341144961713Sgirish return (NXGE_OK); 341244961713Sgirish } 341344961713Sgirish 341444961713Sgirish nxge_status_t 341544961713Sgirish nxge_10g_link_led_off(p_nxge_t nxgep) 341644961713Sgirish { 341744961713Sgirish if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 341844961713Sgirish != NPI_SUCCESS) 341944961713Sgirish return (NXGE_ERROR); 342044961713Sgirish else 342144961713Sgirish return (NXGE_OK); 342244961713Sgirish } 342356d930aeSspeer 342456d930aeSspeer boolean_t 342556d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 342656d930aeSspeer { 342756d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 342856d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 342956d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 343056d930aeSspeer return (B_FALSE); 343156d930aeSspeer else 343256d930aeSspeer return (B_TRUE); 343356d930aeSspeer } 3434