13859Sml29623 /* 23859Sml29623 * CDDL HEADER START 33859Sml29623 * 43859Sml29623 * The contents of this file are subject to the terms of the 53859Sml29623 * Common Development and Distribution License (the "License"). 63859Sml29623 * You may not use this file except in compliance with the License. 73859Sml29623 * 83859Sml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93859Sml29623 * or http://www.opensolaris.org/os/licensing. 103859Sml29623 * See the License for the specific language governing permissions 113859Sml29623 * and limitations under the License. 123859Sml29623 * 133859Sml29623 * When distributing Covered Code, include this CDDL HEADER in each 143859Sml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153859Sml29623 * If applicable, add the following below this CDDL HEADER, with the 163859Sml29623 * fields enclosed by brackets "[]" replaced with your own identifying 173859Sml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 183859Sml29623 * 193859Sml29623 * CDDL HEADER END 203859Sml29623 */ 213859Sml29623 /* 223859Sml29623 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233859Sml29623 * Use is subject to license terms. 243859Sml29623 */ 253859Sml29623 263859Sml29623 #pragma ident "%Z%%M% %I% %E% SMI" 273859Sml29623 283859Sml29623 #include <sys/nxge/nxge_impl.h> 293859Sml29623 #include <sys/nxge/nxge_mac.h> 303859Sml29623 314693Stm144005 #define LINK_MONITOR_PERIOD (1000 * 1000) 324693Stm144005 #define LM_WAIT_MULTIPLIER 8 334693Stm144005 343859Sml29623 extern uint32_t nxge_no_link_notify; 354732Sdavemq extern boolean_t nxge_no_msg; 363859Sml29623 extern uint32_t nxge_lb_dbg; 373859Sml29623 extern nxge_os_mutex_t nxge_mdio_lock; 383859Sml29623 extern nxge_os_mutex_t nxge_mii_lock; 393859Sml29623 extern boolean_t nxge_jumbo_enable; 403859Sml29623 414693Stm144005 typedef enum { 424693Stm144005 CHECK_LINK_RESCHEDULE, 434693Stm144005 CHECK_LINK_STOP 444693Stm144005 } check_link_state_t; 454693Stm144005 464693Stm144005 static check_link_state_t nxge_check_link_stop(nxge_t *); 474693Stm144005 483859Sml29623 /* 493859Sml29623 * Ethernet broadcast address definition. 503859Sml29623 */ 513859Sml29623 static ether_addr_st etherbroadcastaddr = 523859Sml29623 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 534732Sdavemq /* 544732Sdavemq * Ethernet zero address definition. 554732Sdavemq */ 564185Sspeer static ether_addr_st etherzeroaddr = 574185Sspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 584732Sdavemq /* 594732Sdavemq * Supported chip types 604732Sdavemq */ 614732Sdavemq static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID}; 624732Sdavemq static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 634732Sdavemq 644732Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 654732Sdavemq sizeof (uint32_t)) 664732Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 674732Sdavemq sizeof (uint32_t)) 684732Sdavemq /* 694732Sdavemq * static functions 704732Sdavemq */ 714732Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 724732Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 734732Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 744732Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 754732Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 764732Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 774732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 784732Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 794732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 804732Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 814732Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 824732Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 834732Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 844732Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 854732Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 864732Sdavemq 874732Sdavemq /* 884732Sdavemq * xcvr tables for supported transceivers 894732Sdavemq */ 904732Sdavemq 914732Sdavemq static nxge_xcvr_table_t nxge_n2_table = { 924732Sdavemq nxge_n2_serdes_init, 934732Sdavemq nxge_10G_xcvr_init, 944732Sdavemq nxge_10G_link_intr_stop, 954732Sdavemq nxge_10G_link_intr_start, 964732Sdavemq nxge_check_10g_link, 974732Sdavemq BCM8704_DEV_ID, 984732Sdavemq PCS_XCVR, 994732Sdavemq BCM8704_N2_PORT_ADDR_BASE 1004732Sdavemq }; 1014732Sdavemq 1024732Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 1034732Sdavemq nxge_neptune_10G_serdes_init, 1044732Sdavemq nxge_10G_xcvr_init, 1054732Sdavemq nxge_10G_link_intr_stop, 1064732Sdavemq nxge_10G_link_intr_start, 1074732Sdavemq nxge_check_10g_link, 1084732Sdavemq BCM8704_DEV_ID, 1094732Sdavemq PCS_XCVR, 1104732Sdavemq BCM8704_NEPTUNE_PORT_ADDR_BASE 1114732Sdavemq }; 1124732Sdavemq 1134732Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 1144732Sdavemq NULL, 1154732Sdavemq nxge_1G_xcvr_init, 1164732Sdavemq nxge_1G_copper_link_intr_stop, 1174732Sdavemq nxge_1G_copper_link_intr_start, 1184732Sdavemq nxge_check_mii_link, 1194732Sdavemq BCM5464R_PHY_ID, 1204732Sdavemq INT_MII_XCVR, 1214732Sdavemq BCM5464_NEPTUNE_PORT_ADDR_BASE 1224732Sdavemq }; 1234732Sdavemq 1244732Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 1254732Sdavemq nxge_1G_serdes_init, 1264732Sdavemq nxge_1G_xcvr_init, 1274732Sdavemq nxge_1G_fiber_link_intr_stop, 1284732Sdavemq nxge_1G_fiber_link_intr_start, 1294732Sdavemq nxge_check_mii_link, 1304732Sdavemq 0, 1314732Sdavemq PCS_XCVR, 1324732Sdavemq 0 1334732Sdavemq }; 1344732Sdavemq 1354732Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 1364732Sdavemq nxge_neptune_10G_serdes_init, 1374732Sdavemq NULL, 1384732Sdavemq NULL, 1394732Sdavemq NULL, 1404732Sdavemq 0, 1414732Sdavemq PCS_XCVR, 1424732Sdavemq 0 1434732Sdavemq }; 1443859Sml29623 1453859Sml29623 nxge_status_t nxge_mac_init(p_nxge_t); 1463859Sml29623 1474732Sdavemq /* Set up the PHY specific values. */ 1484732Sdavemq 1494732Sdavemq nxge_status_t 1504732Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 1514732Sdavemq { 1524732Sdavemq nxge_status_t status = NXGE_OK; 1534732Sdavemq uint32_t port_type; 1544732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1554732Sdavemq 1564732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 1574732Sdavemq portn)); 1584732Sdavemq 1594732Sdavemq if (nxgep->niu_type == N2_NIU) { 1604732Sdavemq nxgep->mac.portmode = PORT_10G_FIBER; 1614732Sdavemq nxgep->xcvr = nxge_n2_table; 1624732Sdavemq nxgep->xcvr.xcvr_addr += portn; 1634732Sdavemq } else { 1644732Sdavemq port_type = nxgep->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn); 1654732Sdavemq port_type = port_type & (NXGE_PORT_TYPE_MASK); 1664732Sdavemq switch (port_type) { 1674732Sdavemq case NXGE_PORT_1G_COPPER: 1684732Sdavemq nxgep->mac.portmode = PORT_1G_COPPER; 1694732Sdavemq nxgep->xcvr = nxge_1G_copper_table; 1704732Sdavemq if (nxgep->nxge_hw_p->platform_type == 1714732Sdavemq P_NEPTUNE_MARAMBA_P1) { 1724732Sdavemq nxgep->xcvr.xcvr_addr = 1734732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 1744732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == 1754732Sdavemq P_NEPTUNE_MARAMBA_P0) { 1764732Sdavemq nxgep->xcvr.xcvr_addr = 1774732Sdavemq BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 1784732Sdavemq } 1794732Sdavemq /* 1804732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 1814732Sdavemq * swapped with ethernet port number. This is 1824732Sdavemq * designed for better signal integrity in routing. 1834732Sdavemq */ 1844732Sdavemq switch (portn) { 1854732Sdavemq case 0: 1864732Sdavemq nxgep->xcvr.xcvr_addr += 3; 1874732Sdavemq break; 1884732Sdavemq case 1: 1894732Sdavemq nxgep->xcvr.xcvr_addr += 2; 1904732Sdavemq break; 1914732Sdavemq case 2: 1924732Sdavemq nxgep->xcvr.xcvr_addr += 1; 1934732Sdavemq break; 1944732Sdavemq case 3: 1954732Sdavemq break; 1964732Sdavemq default: 1974732Sdavemq return (NXGE_ERROR); 1984732Sdavemq } 1994732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 2004732Sdavemq break; 2014732Sdavemq case NXGE_PORT_10G_COPPER: 2024732Sdavemq nxgep->mac.portmode = PORT_10G_COPPER; 2034732Sdavemq nxgep->xcvr = nxge_10G_copper_table; 2044732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 2054732Sdavemq break; 2064732Sdavemq case NXGE_PORT_1G_FIBRE: 2074732Sdavemq nxgep->mac.portmode = PORT_1G_FIBER; 2084732Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 2094732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Fiber Xcvr")); 2104732Sdavemq break; 2114732Sdavemq case NXGE_PORT_10G_FIBRE: 2124732Sdavemq nxgep->mac.portmode = PORT_10G_FIBER; 2134732Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 2144732Sdavemq if ((nxgep->nxge_hw_p->platform_type == 2154732Sdavemq P_NEPTUNE_MARAMBA_P0) || 2164732Sdavemq (nxgep->nxge_hw_p->platform_type == 2174732Sdavemq P_NEPTUNE_MARAMBA_P1)) { 2184732Sdavemq nxgep->xcvr.xcvr_addr = 2194732Sdavemq BCM8704_MARAMBA_PORT_ADDR_BASE; 2204732Sdavemq /* 2214732Sdavemq * Switch off LED for corresponding copper 2224732Sdavemq * port 2234732Sdavemq */ 2244732Sdavemq nxge_bcm5464_link_led_off(nxgep); 2254732Sdavemq } 2264732Sdavemq nxgep->xcvr.xcvr_addr += portn; 2274732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr")); 2284732Sdavemq break; 2294732Sdavemq default: 2304732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2314732Sdavemq "Unknown port-type: 0x%x", port_type)); 2324732Sdavemq return (NXGE_ERROR); 2334732Sdavemq } 2344732Sdavemq } 2354732Sdavemq 2364732Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 2374732Sdavemq nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr; 2384732Sdavemq nxgep->statsp->mac_stats.xcvr_id = nxgep->xcvr.device_id; 2394732Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 2404732Sdavemq 2414732Sdavemq return (status); 2424732Sdavemq } 2434732Sdavemq 2443859Sml29623 /* Initialize the entire MAC and physical layer */ 2453859Sml29623 2463859Sml29623 nxge_status_t 2473859Sml29623 nxge_mac_init(p_nxge_t nxgep) 2483859Sml29623 { 2493859Sml29623 uint8_t portn; 2503859Sml29623 nxge_status_t status = NXGE_OK; 2513859Sml29623 2523859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2533859Sml29623 2543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 2553859Sml29623 2563859Sml29623 nxgep->mac.portnum = portn; 2573859Sml29623 nxgep->mac.porttype = PORT_TYPE_XMAC; 2583859Sml29623 2593859Sml29623 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 2603859Sml29623 nxgep->mac.porttype = PORT_TYPE_BMAC; 2613859Sml29623 2623859Sml29623 /* Initialize XIF to configure a network mode */ 2633859Sml29623 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 2643859Sml29623 goto fail; 2653859Sml29623 } 2663859Sml29623 2673859Sml29623 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 2683859Sml29623 goto fail; 2693859Sml29623 } 2703859Sml29623 2713859Sml29623 /* Initialize TX and RX MACs */ 2723859Sml29623 /* 2733859Sml29623 * Always perform XIF init first, before TX and RX MAC init 2743859Sml29623 */ 2753859Sml29623 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 2763859Sml29623 goto fail; 2773859Sml29623 2783859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 2793859Sml29623 goto fail; 2803859Sml29623 2813859Sml29623 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 2823859Sml29623 goto fail; 2833859Sml29623 2843859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 2853859Sml29623 goto fail; 2863859Sml29623 2873859Sml29623 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 2883859Sml29623 goto fail; 2893859Sml29623 2903859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 2913859Sml29623 goto fail; 2923859Sml29623 2933859Sml29623 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 2943859Sml29623 2953859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 2963859Sml29623 2973859Sml29623 return (NXGE_OK); 2983859Sml29623 fail: 2993859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3003859Sml29623 "nxge_mac_init: failed to initialize MAC port<%d>", 3013859Sml29623 portn)); 3023859Sml29623 return (status); 3033859Sml29623 } 3043859Sml29623 3053859Sml29623 /* Initialize the Ethernet Link */ 3063859Sml29623 3073859Sml29623 nxge_status_t 3083859Sml29623 nxge_link_init(p_nxge_t nxgep) 3093859Sml29623 { 3103859Sml29623 nxge_status_t status = NXGE_OK; 3113859Sml29623 #ifdef NXGE_DEBUG 3123859Sml29623 uint8_t portn; 3133859Sml29623 3143859Sml29623 portn = nxgep->mac.portnum; 3153859Sml29623 3163859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 3173859Sml29623 #endif 3183859Sml29623 3193859Sml29623 if (nxgep->niu_type == N2_NIU) { 3203859Sml29623 /* Workaround to get link up in both NIU ports */ 3213859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 3223859Sml29623 goto fail; 3233859Sml29623 } 3243859Sml29623 NXGE_DELAY(200000); 3253859Sml29623 /* Initialize internal serdes */ 3263859Sml29623 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 3273859Sml29623 goto fail; 3283859Sml29623 NXGE_DELAY(200000); 3293859Sml29623 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 3303859Sml29623 goto fail; 3313859Sml29623 3323859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 3333859Sml29623 3343859Sml29623 return (NXGE_OK); 3353859Sml29623 3363859Sml29623 fail: 3373859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3383859Sml29623 "nxge_link_init: ", 3393859Sml29623 "failed to initialize Ethernet link on port<%d>", 3403859Sml29623 portn)); 3413859Sml29623 3423859Sml29623 return (status); 3433859Sml29623 } 3443859Sml29623 3453859Sml29623 3463859Sml29623 /* Initialize the XIF sub-block within the MAC */ 3473859Sml29623 3483859Sml29623 nxge_status_t 3493859Sml29623 nxge_xif_init(p_nxge_t nxgep) 3503859Sml29623 { 3513859Sml29623 uint32_t xif_cfg = 0; 3523859Sml29623 npi_attr_t ap; 3533859Sml29623 uint8_t portn; 3543859Sml29623 nxge_port_t portt; 3553859Sml29623 nxge_port_mode_t portmode; 3563859Sml29623 p_nxge_stats_t statsp; 3573859Sml29623 npi_status_t rs = NPI_SUCCESS; 3583859Sml29623 npi_handle_t handle; 3593859Sml29623 3603859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3613859Sml29623 3623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 3633859Sml29623 3643859Sml29623 handle = nxgep->npi_handle; 3653859Sml29623 portmode = nxgep->mac.portmode; 3663859Sml29623 portt = nxgep->mac.porttype; 3673859Sml29623 statsp = nxgep->statsp; 3683859Sml29623 3693859Sml29623 if (portt == PORT_TYPE_XMAC) { 3703859Sml29623 3713859Sml29623 /* Setup XIF Configuration for XMAC */ 3723859Sml29623 3733859Sml29623 if ((portmode == PORT_10G_FIBER) || 3743859Sml29623 (portmode == PORT_10G_COPPER)) 3753859Sml29623 xif_cfg |= CFG_XMAC_XIF_LFS; 3763859Sml29623 3773859Sml29623 if (portmode == PORT_1G_COPPER) { 3783859Sml29623 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 3793859Sml29623 } 3803859Sml29623 3813859Sml29623 /* Set MAC Internal Loopback if necessary */ 3823859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 3833859Sml29623 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 3843859Sml29623 3853859Sml29623 if (statsp->mac_stats.link_speed == 100) 3863859Sml29623 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 3873859Sml29623 3883859Sml29623 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 3893859Sml29623 3903859Sml29623 if (portmode == PORT_10G_FIBER) { 3913859Sml29623 if (statsp->mac_stats.link_up) { 3923859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 3933859Sml29623 } else { 3943859Sml29623 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 3953859Sml29623 } 3963859Sml29623 } 3973859Sml29623 3983859Sml29623 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 3993859Sml29623 if (rs != NPI_SUCCESS) 4003859Sml29623 goto fail; 4013859Sml29623 4023859Sml29623 nxgep->mac.xif_config = xif_cfg; 4033859Sml29623 4043859Sml29623 /* Set Port Mode */ 4053859Sml29623 if ((portmode == PORT_10G_FIBER) || 4063859Sml29623 (portmode == PORT_10G_COPPER)) { 4073859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4083859Sml29623 MAC_XGMII_MODE, rs); 4093859Sml29623 if (rs != NPI_SUCCESS) 4103859Sml29623 goto fail; 4113859Sml29623 if (statsp->mac_stats.link_up) { 4123859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 4133859Sml29623 goto fail; 4143859Sml29623 } else { 4153859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 4163859Sml29623 goto fail; 4173859Sml29623 } 4183859Sml29623 } else if ((portmode == PORT_1G_FIBER) || 4193859Sml29623 (portmode == PORT_1G_COPPER)) { 4203859Sml29623 if (statsp->mac_stats.link_speed == 1000) { 4213859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4223859Sml29623 MAC_GMII_MODE, rs); 4233859Sml29623 } else { 4243859Sml29623 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 4253859Sml29623 MAC_MII_MODE, rs); 4263859Sml29623 } 4273859Sml29623 if (rs != NPI_SUCCESS) 4283859Sml29623 goto fail; 4293859Sml29623 } else { 4303859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4313859Sml29623 "nxge_xif_init: Unknown port mode (%d)" 4323859Sml29623 " for port<%d>", portmode, portn)); 4333859Sml29623 goto fail; 4343859Sml29623 } 4353859Sml29623 4363859Sml29623 } else if (portt == PORT_TYPE_BMAC) { 4373859Sml29623 4383859Sml29623 /* Setup XIF Configuration for BMAC */ 4393859Sml29623 4403859Sml29623 if (portmode == PORT_1G_COPPER) { 4413859Sml29623 if (statsp->mac_stats.link_speed == 100) 4423859Sml29623 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 4433859Sml29623 } 4443859Sml29623 4453859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 4463859Sml29623 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 4473859Sml29623 4483859Sml29623 if (statsp->mac_stats.link_speed == 1000) 4493859Sml29623 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 4503859Sml29623 4513859Sml29623 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 4523859Sml29623 4533859Sml29623 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 4543859Sml29623 if (rs != NPI_SUCCESS) 4553859Sml29623 goto fail; 4563859Sml29623 nxgep->mac.xif_config = xif_cfg; 4573859Sml29623 } 4583859Sml29623 4593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 4603859Sml29623 return (NXGE_OK); 4613859Sml29623 fail: 4623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4633859Sml29623 "nxge_xif_init: Failed to initialize XIF port<%d>", 4643859Sml29623 portn)); 4653859Sml29623 return (NXGE_ERROR | rs); 4663859Sml29623 } 4673859Sml29623 4683859Sml29623 /* Initialize the PCS sub-block in the MAC */ 4693859Sml29623 4703859Sml29623 nxge_status_t 4713859Sml29623 nxge_pcs_init(p_nxge_t nxgep) 4723859Sml29623 { 4733859Sml29623 pcs_cfg_t pcs_cfg; 4743859Sml29623 uint32_t val; 4753859Sml29623 uint8_t portn; 4763859Sml29623 nxge_port_mode_t portmode; 4773859Sml29623 npi_handle_t handle; 4783859Sml29623 p_nxge_stats_t statsp; 4793859Sml29623 npi_status_t rs = NPI_SUCCESS; 4803859Sml29623 4813859Sml29623 handle = nxgep->npi_handle; 4823859Sml29623 portmode = nxgep->mac.portmode; 4833859Sml29623 portn = nxgep->mac.portnum; 4843859Sml29623 statsp = nxgep->statsp; 4853859Sml29623 4863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 4873859Sml29623 4883859Sml29623 if (portmode == PORT_1G_FIBER) { 4893859Sml29623 /* Initialize port's PCS */ 4903859Sml29623 pcs_cfg.value = 0; 4913859Sml29623 pcs_cfg.bits.w0.enable = 1; 4923859Sml29623 pcs_cfg.bits.w0.mask = 1; 4933859Sml29623 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 4943859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 4953859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 4963859Sml29623 goto fail; 4973859Sml29623 4983859Sml29623 } else if ((portmode == PORT_10G_FIBER) || 4993859Sml29623 (portmode == PORT_10G_COPPER)) { 5003859Sml29623 /* Use internal XPCS, bypass 1G PCS */ 5013859Sml29623 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 5023859Sml29623 val &= ~XMAC_XIF_XPCS_BYPASS; 5033859Sml29623 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 5043859Sml29623 5053859Sml29623 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 5063859Sml29623 goto fail; 5073859Sml29623 5083859Sml29623 /* Set XPCS Internal Loopback if necessary */ 5093859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5103859Sml29623 XPCS_REG_CONTROL1, &val)) 5113859Sml29623 != NPI_SUCCESS) 5123859Sml29623 goto fail; 5133859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 5143859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 5153859Sml29623 val |= XPCS_CTRL1_LOOPBK; 5163859Sml29623 else 5173859Sml29623 val &= ~XPCS_CTRL1_LOOPBK; 5183859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 5193859Sml29623 XPCS_REG_CONTROL1, val)) 5203859Sml29623 != NPI_SUCCESS) 5213859Sml29623 goto fail; 5223859Sml29623 5233859Sml29623 /* Clear descw errors */ 5243859Sml29623 if ((rs = npi_xmac_xpcs_write(handle, portn, 5253859Sml29623 XPCS_REG_DESCWERR_COUNTER, 0)) 5263859Sml29623 != NPI_SUCCESS) 5273859Sml29623 goto fail; 5283859Sml29623 /* Clear symbol errors */ 5293859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5303859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 5313859Sml29623 != NPI_SUCCESS) 5323859Sml29623 goto fail; 5333859Sml29623 if ((rs = npi_xmac_xpcs_read(handle, portn, 5343859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 5353859Sml29623 != NPI_SUCCESS) 5363859Sml29623 goto fail; 5373859Sml29623 5383859Sml29623 } else if (portmode == PORT_1G_COPPER) { 5393859Sml29623 if (portn < 4) { 5403859Sml29623 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 5413859Sml29623 PCS_DATAPATH_MODE_MII); 5423859Sml29623 } 5433859Sml29623 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 5443859Sml29623 goto fail; 5453859Sml29623 5463859Sml29623 } else { 5473859Sml29623 goto fail; 5483859Sml29623 } 5493859Sml29623 pass: 5503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 5513859Sml29623 return (NXGE_OK); 5523859Sml29623 fail: 5533859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5543859Sml29623 "nxge_pcs_init: Failed to initialize PCS port<%d>", 5553859Sml29623 portn)); 5563859Sml29623 return (NXGE_ERROR | rs); 5573859Sml29623 } 5583859Sml29623 5593859Sml29623 /* Initialize the Internal Serdes */ 5603859Sml29623 5613859Sml29623 nxge_status_t 5623859Sml29623 nxge_serdes_init(p_nxge_t nxgep) 5633859Sml29623 { 5643859Sml29623 p_nxge_stats_t statsp; 5653859Sml29623 #ifdef NXGE_DEBUG 5663859Sml29623 uint8_t portn; 5673859Sml29623 #endif 5683859Sml29623 nxge_status_t status = NXGE_OK; 5693859Sml29623 5703859Sml29623 #ifdef NXGE_DEBUG 5713859Sml29623 portn = nxgep->mac.portnum; 5723859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5734732Sdavemq "==> nxge_serdes_init port<%d>", portn)); 5743859Sml29623 #endif 5753859Sml29623 5764732Sdavemq if (nxgep->xcvr.serdes_init) { 5774732Sdavemq statsp = nxgep->statsp; 5784732Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 5794732Sdavemq if (status != NXGE_OK) 5803859Sml29623 goto fail; 5814732Sdavemq statsp->mac_stats.serdes_inits++; 5823859Sml29623 } 5833859Sml29623 5843859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 5854732Sdavemq portn)); 5863859Sml29623 5873859Sml29623 return (NXGE_OK); 5883859Sml29623 5893859Sml29623 fail: 5903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5914732Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 5924732Sdavemq portn)); 5933859Sml29623 5943859Sml29623 return (status); 5953859Sml29623 } 5963859Sml29623 5973859Sml29623 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 5983859Sml29623 5994732Sdavemq static nxge_status_t 6003859Sml29623 nxge_n2_serdes_init(p_nxge_t nxgep) 6013859Sml29623 { 6023859Sml29623 uint8_t portn; 6033859Sml29623 int chan; 6043859Sml29623 esr_ti_cfgpll_l_t pll_cfg_l; 6053859Sml29623 esr_ti_cfgrx_l_t rx_cfg_l; 6063859Sml29623 esr_ti_cfgrx_h_t rx_cfg_h; 6073859Sml29623 esr_ti_cfgtx_l_t tx_cfg_l; 6083859Sml29623 esr_ti_cfgtx_h_t tx_cfg_h; 6093859Sml29623 esr_ti_testcfg_t test_cfg; 6103859Sml29623 nxge_status_t status = NXGE_OK; 6113859Sml29623 6123859Sml29623 portn = nxgep->mac.portnum; 6133859Sml29623 6143859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 6153859Sml29623 portn)); 6163859Sml29623 6173859Sml29623 tx_cfg_l.value = 0; 6183859Sml29623 tx_cfg_h.value = 0; 6193859Sml29623 rx_cfg_l.value = 0; 6203859Sml29623 rx_cfg_h.value = 0; 6213859Sml29623 pll_cfg_l.value = 0; 6223859Sml29623 test_cfg.value = 0; 6233859Sml29623 6243859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 6253859Sml29623 /* 0x0E01 */ 6263859Sml29623 tx_cfg_l.bits.entx = 1; 6273859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 6283859Sml29623 6293859Sml29623 /* 0x9101 */ 6303859Sml29623 rx_cfg_l.bits.enrx = 1; 6313859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 6323859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 6333859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 6343859Sml29623 6353859Sml29623 /* 0x0008 */ 6363859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 6373859Sml29623 6383859Sml29623 /* Set loopback mode if necessary */ 6393859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 6403859Sml29623 tx_cfg_l.bits.entest = 1; 6413859Sml29623 rx_cfg_l.bits.entest = 1; 6423859Sml29623 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 6433859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, 6443859Sml29623 ESR_N2_DEV_ADDR, 6453859Sml29623 ESR_N2_TEST_CFG_REG, test_cfg.value)) 6463859Sml29623 != NXGE_OK) 6473859Sml29623 goto fail; 6483859Sml29623 } 6493859Sml29623 6503859Sml29623 /* Use default PLL value */ 6513859Sml29623 6523859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 6533859Sml29623 6543859Sml29623 /* 0x0E21 */ 6553859Sml29623 tx_cfg_l.bits.entx = 1; 6563859Sml29623 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 6573859Sml29623 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 6583859Sml29623 6593859Sml29623 /* 0x9121 */ 6603859Sml29623 rx_cfg_l.bits.enrx = 1; 6613859Sml29623 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 6623859Sml29623 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 6633859Sml29623 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 6643859Sml29623 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 6653859Sml29623 6663859Sml29623 /* 0x8 */ 6673859Sml29623 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 6683859Sml29623 6693859Sml29623 /* MPY = 0x100 */ 6703859Sml29623 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 6713859Sml29623 6723859Sml29623 /* Set PLL */ 6733859Sml29623 pll_cfg_l.bits.enpll = 1; 6743859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6753859Sml29623 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 6763859Sml29623 != NXGE_OK) 6773859Sml29623 goto fail; 6783859Sml29623 } else { 6793859Sml29623 goto fail; 6803859Sml29623 } 6813859Sml29623 6823859Sml29623 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 6833859Sml29623 6843859Sml29623 NXGE_DELAY(20); 6853859Sml29623 6863859Sml29623 /* init TX channels */ 6873859Sml29623 for (chan = 0; chan < 4; chan++) { 6883859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6893859Sml29623 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 6903859Sml29623 != NXGE_OK) 6913859Sml29623 goto fail; 6923859Sml29623 6933859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 6943859Sml29623 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 6953859Sml29623 != NXGE_OK) 6963859Sml29623 goto fail; 6973859Sml29623 } 6983859Sml29623 6993859Sml29623 /* init RX channels */ 7003859Sml29623 for (chan = 0; chan < 4; chan++) { 7013859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 7023859Sml29623 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 7033859Sml29623 != NXGE_OK) 7043859Sml29623 goto fail; 7053859Sml29623 7063859Sml29623 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 7073859Sml29623 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 7083859Sml29623 != NXGE_OK) 7093859Sml29623 goto fail; 7103859Sml29623 } 7113859Sml29623 7123859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 7133859Sml29623 portn)); 7143859Sml29623 7153859Sml29623 return (NXGE_OK); 7163859Sml29623 fail: 7173859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7183859Sml29623 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 7193859Sml29623 portn)); 7203859Sml29623 7213859Sml29623 return (status); 7223859Sml29623 } 7233859Sml29623 7244732Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 7254732Sdavemq 7264732Sdavemq static nxge_status_t 7274732Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 7283859Sml29623 { 7293859Sml29623 npi_handle_t handle; 7303859Sml29623 uint8_t portn; 7313859Sml29623 int chan; 7323859Sml29623 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 7333859Sml29623 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 7343859Sml29623 sr_glue_ctrl0_l_t glue_ctrl0_l; 7353859Sml29623 sr_glue_ctrl0_h_t glue_ctrl0_h; 7363859Sml29623 uint64_t val; 7373859Sml29623 uint16_t val16l; 7383859Sml29623 uint16_t val16h; 7393859Sml29623 nxge_status_t status = NXGE_OK; 7403859Sml29623 7413859Sml29623 portn = nxgep->mac.portnum; 7423859Sml29623 7433859Sml29623 if ((portn != 0) && (portn != 1)) 7443859Sml29623 return (NXGE_OK); 7453859Sml29623 7464732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7474732Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 7483859Sml29623 7493859Sml29623 handle = nxgep->npi_handle; 7504732Sdavemq switch (portn) { 7514732Sdavemq case 0: 7524732Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 7534732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 7544732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 7554732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 7564732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 7574732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 7584732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 7594732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 7604732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 7614732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 7624732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 7634732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 7644732Sdavemq 7654732Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 7664732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 7674732Sdavemq ESR_REG_WR(handle, 7684732Sdavemq ESR_0_TEST_CONFIG_REG, 7694732Sdavemq ESR_PAD_LOOPBACK_CH3 | 7704732Sdavemq ESR_PAD_LOOPBACK_CH2 | 7714732Sdavemq ESR_PAD_LOOPBACK_CH1 | 7724732Sdavemq ESR_PAD_LOOPBACK_CH0); 7734732Sdavemq } else { 7744732Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 7753859Sml29623 } 7764732Sdavemq break; 7774732Sdavemq case 1: 7784732Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 7794732Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 7804732Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 7814732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 7824732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 7834732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 7844732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 7854732Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 7864732Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 7874732Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 7884732Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 7894732Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 7904732Sdavemq 7914732Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 7924732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 7934732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 7944732Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 7954732Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 7964732Sdavemq } else { 7974732Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 7983859Sml29623 } 7994732Sdavemq break; 8004732Sdavemq default: 8014732Sdavemq /* Nothing to do here */ 8024732Sdavemq goto done; 8034732Sdavemq } 8044732Sdavemq 8054732Sdavemq /* init TX RX channels */ 8064732Sdavemq for (chan = 0; chan < 4; chan++) { 8074732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 8084732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 8094732Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 8103859Sml29623 goto fail; 8114732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 8124732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 8134732Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 8143859Sml29623 goto fail; 8153859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 8164732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 8174732Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 8183859Sml29623 goto fail; 8193859Sml29623 if ((status = nxge_mdio_read(nxgep, portn, 8204732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 8214732Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 8224732Sdavemq goto fail; 8234732Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 8244732Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 8254732Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 8264732Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 8274732Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 8284732Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 8294732Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 8304732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 8314732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 8324732Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 8334732Sdavemq goto fail; 8344732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 8354732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 8364732Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 8374732Sdavemq goto fail; 8384732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 8394732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 8404732Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 8414732Sdavemq goto fail; 8424732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 8434732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 8444732Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 8453859Sml29623 goto fail; 8463859Sml29623 } 8473859Sml29623 8484732Sdavemq /* Apply Tx core reset */ 8494732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 8504732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 8514732Sdavemq (uint16_t)0)) != NXGE_OK) 8524732Sdavemq goto fail; 8534732Sdavemq 8544732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 8554732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 8564732Sdavemq NXGE_OK) 8574732Sdavemq goto fail; 8584732Sdavemq 8594732Sdavemq NXGE_DELAY(200); 8604732Sdavemq 8614732Sdavemq /* Apply Rx core reset */ 8624732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 8634732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 8644732Sdavemq NXGE_OK) 8654732Sdavemq goto fail; 8664732Sdavemq 8674732Sdavemq NXGE_DELAY(200); 8684732Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 8694732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 8704732Sdavemq goto fail; 8714732Sdavemq 8724732Sdavemq NXGE_DELAY(200); 8734732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 8744732Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 8754732Sdavemq &val16l)) != NXGE_OK) 8764732Sdavemq goto fail; 8774732Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 8784732Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 8794732Sdavemq goto fail; 8804732Sdavemq if ((val16l != 0) || (val16h != 0)) { 8814732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8824732Sdavemq "Failed to reset port<%d> XAUI Serdes", portn)); 8834732Sdavemq } 8844732Sdavemq 8854732Sdavemq ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 8864732Sdavemq 8874732Sdavemq if (portn == 0) { 8884732Sdavemq if ((val & ESR_SIG_P0_BITS_MASK) != 8893859Sml29623 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 8903859Sml29623 ESR_SIG_XSERDES_RDY_P0 | 8913859Sml29623 ESR_SIG_XDETECT_P0_CH3 | 8923859Sml29623 ESR_SIG_XDETECT_P0_CH2 | 8933859Sml29623 ESR_SIG_XDETECT_P0_CH1 | 8943859Sml29623 ESR_SIG_XDETECT_P0_CH0)) { 8954732Sdavemq goto fail; 8964732Sdavemq } 8974732Sdavemq } else if (portn == 1) { 8984732Sdavemq if ((val & ESR_SIG_P1_BITS_MASK) != 8993859Sml29623 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 9003859Sml29623 ESR_SIG_XSERDES_RDY_P1 | 9013859Sml29623 ESR_SIG_XDETECT_P1_CH3 | 9023859Sml29623 ESR_SIG_XDETECT_P1_CH2 | 9033859Sml29623 ESR_SIG_XDETECT_P1_CH1 | 9043859Sml29623 ESR_SIG_XDETECT_P1_CH0)) { 9053859Sml29623 goto fail; 9063859Sml29623 } 9073859Sml29623 } 9083859Sml29623 9093859Sml29623 done: 9104732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9114732Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 9124732Sdavemq 9133859Sml29623 return (NXGE_OK); 9143859Sml29623 fail: 9154732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9164732Sdavemq "nxge_neptune_10G_serdes_init: " 9174732Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 9183859Sml29623 9193859Sml29623 return (status); 9203859Sml29623 } 9213859Sml29623 9224732Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 9234732Sdavemq 9244732Sdavemq static nxge_status_t 9254732Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 9263859Sml29623 { 9274732Sdavemq npi_handle_t handle; 9284732Sdavemq uint8_t portn; 9294732Sdavemq uint64_t val; 9303859Sml29623 9313859Sml29623 portn = nxgep->mac.portnum; 9324732Sdavemq 9334732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9344732Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 9354732Sdavemq 9364732Sdavemq handle = nxgep->npi_handle; 9374732Sdavemq 9384732Sdavemq ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val); 9394732Sdavemq val &= ~ESR_PLL_CFG_FBDIV_2; 9404732Sdavemq switch (portn) { 9414732Sdavemq case 0: 9424732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_0; 9434732Sdavemq break; 9444732Sdavemq case 1: 9454732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_1; 9464732Sdavemq break; 9474732Sdavemq case 2: 9484732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_2; 9494732Sdavemq break; 9504732Sdavemq case 3: 9514732Sdavemq val |= ESR_PLL_CFG_HALF_RATE_3; 9524732Sdavemq break; 9534732Sdavemq default: 9544732Sdavemq goto fail; 9553859Sml29623 } 9563859Sml29623 9574732Sdavemq ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 9584732Sdavemq 9594732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 9604732Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 9613859Sml29623 return (NXGE_OK); 9624732Sdavemq fail: 9634732Sdavemq NXGE_DEBUG_MSG((nxgep, TX_CTL, 9644732Sdavemq "nxge_1G_serdes_init: " 9654732Sdavemq "Failed to initialize Neptune serdes for port<%d>", 9664732Sdavemq portn)); 9674732Sdavemq 9684732Sdavemq return (NXGE_ERROR); 9693859Sml29623 } 9703859Sml29623 9714732Sdavemq /* Initialize the 10G (BCM8704) Transceiver */ 9724732Sdavemq 9734732Sdavemq static nxge_status_t 9744732Sdavemq nxge_10G_xcvr_init(p_nxge_t nxgep) 9753859Sml29623 { 9763859Sml29623 p_nxge_stats_t statsp; 9773859Sml29623 uint16_t val; 9783859Sml29623 #ifdef NXGE_DEBUG 9793859Sml29623 uint8_t portn; 9803859Sml29623 uint16_t val1; 9813859Sml29623 #endif 9823859Sml29623 uint8_t phy_port_addr; 9833859Sml29623 pmd_tx_control_t tx_ctl; 9843859Sml29623 control_t ctl; 9853859Sml29623 phyxs_control_t phyxs_ctl; 9863859Sml29623 pcs_control_t pcs_ctl; 9873859Sml29623 uint32_t delay = 0; 9883859Sml29623 optics_dcntr_t op_ctr; 9893859Sml29623 nxge_status_t status = NXGE_OK; 9903859Sml29623 #ifdef NXGE_DEBUG 9913859Sml29623 portn = nxgep->mac.portnum; 9923859Sml29623 #endif 9934732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 9944732Sdavemq portn)); 9954732Sdavemq 9964732Sdavemq statsp = nxgep->statsp; 9974732Sdavemq 9984732Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 9994732Sdavemq 10004732Sdavemq /* Disable Link LEDs */ 10014732Sdavemq if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 10024732Sdavemq goto fail; 10034732Sdavemq 10044732Sdavemq /* Set Clause 45 */ 10054732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 10064732Sdavemq 10074732Sdavemq /* Reset the transceiver */ 10084732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 10094732Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 10104732Sdavemq goto fail; 10114732Sdavemq 10124732Sdavemq phyxs_ctl.bits.reset = 1; 10134732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 10144732Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 10154732Sdavemq goto fail; 10164732Sdavemq 10174732Sdavemq do { 10184732Sdavemq drv_usecwait(500); 10194732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10204732Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 10214732Sdavemq &phyxs_ctl.value)) != NXGE_OK) 10224732Sdavemq goto fail; 10234732Sdavemq delay++; 10244732Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 10254732Sdavemq if (delay == 100) { 10264732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 10274732Sdavemq "failed to reset Transceiver on port<%d>", portn)); 10284732Sdavemq status = NXGE_ERROR; 10294732Sdavemq goto fail; 10304732Sdavemq } 10314732Sdavemq 10324732Sdavemq /* Set to 0x7FBF */ 10334732Sdavemq ctl.value = 0; 10344732Sdavemq ctl.bits.res1 = 0x3F; 10354732Sdavemq ctl.bits.optxon_lvl = 1; 10364732Sdavemq ctl.bits.oprxflt_lvl = 1; 10374732Sdavemq ctl.bits.optrxlos_lvl = 1; 10384732Sdavemq ctl.bits.optxflt_lvl = 1; 10394732Sdavemq ctl.bits.opprflt_lvl = 1; 10404732Sdavemq ctl.bits.obtmpflt_lvl = 1; 10414732Sdavemq ctl.bits.opbiasflt_lvl = 1; 10424732Sdavemq ctl.bits.optxrst_lvl = 1; 10434732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 10444732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 10454732Sdavemq != NXGE_OK) 10464732Sdavemq goto fail; 10474732Sdavemq 10484732Sdavemq /* Set to 0x164 */ 10494732Sdavemq tx_ctl.value = 0; 10504732Sdavemq tx_ctl.bits.tsck_lpwren = 1; 10514732Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 10524732Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 10534732Sdavemq tx_ctl.bits.xfp_clken = 1; 10544732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 10554732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 10564732Sdavemq tx_ctl.value)) != NXGE_OK) 10574732Sdavemq goto fail; 10584732Sdavemq /* 10594732Sdavemq * According to Broadcom's instruction, SW needs to read 10604732Sdavemq * back these registers twice after written. 10614732Sdavemq */ 10624732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10634732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 10644732Sdavemq != NXGE_OK) 10654732Sdavemq goto fail; 10664732Sdavemq 10674732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10684732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 10694732Sdavemq != NXGE_OK) 10704732Sdavemq goto fail; 10714732Sdavemq 10724732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10734732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 10744732Sdavemq != NXGE_OK) 10754732Sdavemq goto fail; 10764732Sdavemq 10774732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10784732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 10794732Sdavemq != NXGE_OK) 10804732Sdavemq goto fail; 10814732Sdavemq 10824732Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 10834732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10844732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 10854732Sdavemq &op_ctr.value)) != NXGE_OK) 10864732Sdavemq goto fail; 10874732Sdavemq op_ctr.bits.gpio_sel = 0x3; 10884732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 10894732Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 10904732Sdavemq op_ctr.value)) != NXGE_OK) 10914732Sdavemq goto fail; 10924732Sdavemq 10934732Sdavemq NXGE_DELAY(1000000); 10944732Sdavemq 10954732Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 10964732Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 10974732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 10984732Sdavemq != NXGE_OK) 10994732Sdavemq goto fail; 11004732Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 11014732Sdavemq pcs_ctl.bits.loopback = 1; 11024732Sdavemq else 11034732Sdavemq pcs_ctl.bits.loopback = 0; 11044732Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 11054732Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 11064732Sdavemq != NXGE_OK) 11074732Sdavemq goto fail; 11084732Sdavemq 11094732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 11104732Sdavemq if (status != NXGE_OK) 11114732Sdavemq goto fail; 11124732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11134732Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 11144732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 11154732Sdavemq if (status != NXGE_OK) 11164732Sdavemq goto fail; 11174732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11184732Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 11194732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 11204732Sdavemq if (status != NXGE_OK) 11214732Sdavemq goto fail; 11224732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11234732Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 11244732Sdavemq 11254732Sdavemq #ifdef NXGE_DEBUG 11264732Sdavemq /* Diagnose link issue if link is not up */ 11274732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 11284732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 11294732Sdavemq &val); 11304732Sdavemq if (status != NXGE_OK) 11314732Sdavemq goto fail; 11324732Sdavemq 11334732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 11344732Sdavemq BCM8704_USER_DEV3_ADDR, 11354732Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 11364732Sdavemq &val); 11374732Sdavemq if (status != NXGE_OK) 11384732Sdavemq goto fail; 11394732Sdavemq 11404732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 11414732Sdavemq BCM8704_USER_DEV3_ADDR, 11424732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 11434732Sdavemq &val1); 11444732Sdavemq if (status != NXGE_OK) 11454732Sdavemq goto fail; 11464732Sdavemq 11474732Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 11484732Sdavemq BCM8704_USER_DEV3_ADDR, 11494732Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 11504732Sdavemq &val1); 11514732Sdavemq if (status != NXGE_OK) 11524732Sdavemq goto fail; 11534732Sdavemq 11544732Sdavemq if (val != 0x3FC) { 11554732Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 11564732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11574732Sdavemq "Cable not connected to peer or bad" 11584732Sdavemq " cable on port<%d>\n", portn)); 11594732Sdavemq } else if (val == 0x639C) { 11604732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11614732Sdavemq "Optical module (XFP) is bad or absent" 11624732Sdavemq " on port<%d>\n", portn)); 11634732Sdavemq } 11644732Sdavemq } 11654732Sdavemq #endif 11664732Sdavemq 11674732Sdavemq statsp->mac_stats.cap_10gfdx = 1; 11684732Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 11694732Sdavemq 11704732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 11714732Sdavemq portn)); 11724732Sdavemq return (NXGE_OK); 11734732Sdavemq 11744732Sdavemq fail: 11754732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 11764732Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 11774732Sdavemq "port<%d>", portn)); 11784732Sdavemq return (status); 11794732Sdavemq } 11804732Sdavemq 11814732Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 11824732Sdavemq 11834732Sdavemq static nxge_status_t 11844732Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 11854732Sdavemq { 11864732Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 11874732Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 11884732Sdavemq nxge_status_t status = NXGE_OK; 11894732Sdavemq 11904732Sdavemq /* Set Clause 22 */ 11914732Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 11924732Sdavemq 11934732Sdavemq /* Set capability flags */ 11944732Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 11954732Sdavemq statsp->mac_stats.cap_100fdx = param_arr[param_anar_100fdx].value; 11964732Sdavemq statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value; 11974732Sdavemq 11984732Sdavemq status = nxge_mii_xcvr_init(nxgep); 11994732Sdavemq 12004732Sdavemq return (status); 12014732Sdavemq } 12024732Sdavemq 12034732Sdavemq /* Initialize transceiver */ 12044732Sdavemq 12054732Sdavemq nxge_status_t 12064732Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 12074732Sdavemq { 12084732Sdavemq p_nxge_stats_t statsp; 12094732Sdavemq #ifdef NXGE_DEBUG 12104732Sdavemq uint8_t portn; 12114732Sdavemq #endif 12124732Sdavemq 12134732Sdavemq nxge_status_t status = NXGE_OK; 12144732Sdavemq #ifdef NXGE_DEBUG 12154732Sdavemq portn = nxgep->mac.portnum; 12164732Sdavemq #endif 12173859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 12183859Sml29623 statsp = nxgep->statsp; 12193859Sml29623 12203859Sml29623 /* 12213859Sml29623 * Initialize the xcvr statistics. 12223859Sml29623 */ 12233859Sml29623 statsp->mac_stats.cap_autoneg = 0; 12243859Sml29623 statsp->mac_stats.cap_100T4 = 0; 12253859Sml29623 statsp->mac_stats.cap_100fdx = 0; 12263859Sml29623 statsp->mac_stats.cap_100hdx = 0; 12273859Sml29623 statsp->mac_stats.cap_10fdx = 0; 12283859Sml29623 statsp->mac_stats.cap_10hdx = 0; 12293859Sml29623 statsp->mac_stats.cap_asmpause = 0; 12303859Sml29623 statsp->mac_stats.cap_pause = 0; 12313859Sml29623 statsp->mac_stats.cap_1000fdx = 0; 12323859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 12333859Sml29623 statsp->mac_stats.cap_10gfdx = 0; 12343859Sml29623 statsp->mac_stats.cap_10ghdx = 0; 12353859Sml29623 12363859Sml29623 /* 12373859Sml29623 * Initialize the link statistics. 12383859Sml29623 */ 12393859Sml29623 statsp->mac_stats.link_T4 = 0; 12403859Sml29623 statsp->mac_stats.link_asmpause = 0; 12413859Sml29623 statsp->mac_stats.link_pause = 0; 12423859Sml29623 12434732Sdavemq if (nxgep->xcvr.xcvr_init) { 12444732Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 12453859Sml29623 if (status != NXGE_OK) 12463859Sml29623 goto fail; 12474732Sdavemq statsp->mac_stats.xcvr_inits++; 12483859Sml29623 } 12493859Sml29623 12504732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 12514732Sdavemq portn)); 12523859Sml29623 return (NXGE_OK); 12533859Sml29623 12543859Sml29623 fail: 12553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12564732Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 12574732Sdavemq portn)); 12583859Sml29623 return (status); 12593859Sml29623 } 12603859Sml29623 12613859Sml29623 12623859Sml29623 /* Initialize the TxMAC sub-block */ 12633859Sml29623 12643859Sml29623 nxge_status_t 12653859Sml29623 nxge_tx_mac_init(p_nxge_t nxgep) 12663859Sml29623 { 12673859Sml29623 npi_attr_t ap; 12683859Sml29623 uint8_t portn; 12693859Sml29623 nxge_port_mode_t portmode; 12703859Sml29623 nxge_port_t portt; 12713859Sml29623 npi_handle_t handle; 12723859Sml29623 npi_status_t rs = NPI_SUCCESS; 12733859Sml29623 12743859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 12753859Sml29623 portt = nxgep->mac.porttype; 12763859Sml29623 handle = nxgep->npi_handle; 12773859Sml29623 portmode = nxgep->mac.portmode; 12783859Sml29623 12793859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 12803859Sml29623 portn)); 12813859Sml29623 12823859Sml29623 /* Set Max and Min Frame Size */ 12833859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 12843859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 12853859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 12863859Sml29623 } else { 12873859Sml29623 SET_MAC_ATTR2(handle, ap, portn, 12883859Sml29623 MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 12893859Sml29623 } 12903859Sml29623 12913859Sml29623 if (rs != NPI_SUCCESS) 12923859Sml29623 goto fail; 12933859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || 12943859Sml29623 nxgep->mac.is_jumbo == B_TRUE) 12953859Sml29623 nxgep->mac.maxframesize = 0x2400; 12963859Sml29623 else 12973859Sml29623 nxgep->mac.maxframesize = 0x5EE + 4; 12983859Sml29623 nxgep->mac.minframesize = 64; 12993859Sml29623 13003859Sml29623 if (portt == PORT_TYPE_XMAC) { 13013859Sml29623 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 13023859Sml29623 0)) != NPI_SUCCESS) 13033859Sml29623 goto fail; 13043859Sml29623 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 13053859Sml29623 if ((portmode == PORT_10G_FIBER) || 13063859Sml29623 (portmode == PORT_10G_COPPER)) { 13073859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 13083859Sml29623 XGMII_IPG_12_15, rs); 13093859Sml29623 if (rs != NPI_SUCCESS) 13103859Sml29623 goto fail; 13113859Sml29623 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 13123859Sml29623 } else { 13133859Sml29623 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 13143859Sml29623 MII_GMII_IPG_12, rs); 13153859Sml29623 if (rs != NPI_SUCCESS) 13163859Sml29623 goto fail; 13173859Sml29623 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 13183859Sml29623 } 13193859Sml29623 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 13203859Sml29623 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 13213859Sml29623 goto fail; 13223859Sml29623 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 13233859Sml29623 nxgep->mac.maxburstsize = 0; /* not programmable */ 13243859Sml29623 nxgep->mac.ctrltype = 0; /* not programmable */ 13253859Sml29623 nxgep->mac.pa_size = 0; /* not programmable */ 13263859Sml29623 13273859Sml29623 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 13283859Sml29623 != NPI_SUCCESS) 13293859Sml29623 goto fail; 13303859Sml29623 13313859Sml29623 } else { 13323859Sml29623 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 13333859Sml29623 0)) != NPI_SUCCESS) 13343859Sml29623 goto fail; 13353859Sml29623 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 13363859Sml29623 13373859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 13383859Sml29623 rs); 13393859Sml29623 if (rs != NPI_SUCCESS) 13403859Sml29623 goto fail; 13413859Sml29623 nxgep->mac.ctrltype = 0x8808; 13423859Sml29623 13433859Sml29623 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 13443859Sml29623 if (rs != NPI_SUCCESS) 13453859Sml29623 goto fail; 13463859Sml29623 nxgep->mac.pa_size = 0x7; 13473859Sml29623 13483859Sml29623 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 13493859Sml29623 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 13503859Sml29623 goto fail; 13513859Sml29623 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 13523859Sml29623 } 13533859Sml29623 13543859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 13553859Sml29623 portn)); 13563859Sml29623 13573859Sml29623 return (NXGE_OK); 13583859Sml29623 fail: 13593859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13603859Sml29623 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 13613859Sml29623 portn)); 13623859Sml29623 13633859Sml29623 return (NXGE_ERROR | rs); 13643859Sml29623 } 13653859Sml29623 13663859Sml29623 /* Initialize the RxMAC sub-block */ 13673859Sml29623 13683859Sml29623 nxge_status_t 13693859Sml29623 nxge_rx_mac_init(p_nxge_t nxgep) 13703859Sml29623 { 13713859Sml29623 npi_attr_t ap; 13723859Sml29623 uint32_t i; 13733859Sml29623 uint16_t hashtab_e; 13743859Sml29623 p_hash_filter_t hash_filter; 13753859Sml29623 nxge_port_t portt; 13763859Sml29623 uint8_t portn; 13773859Sml29623 npi_handle_t handle; 13783859Sml29623 npi_status_t rs = NPI_SUCCESS; 13793859Sml29623 uint16_t *addr16p; 13803859Sml29623 uint16_t addr0, addr1, addr2; 13813859Sml29623 xmac_rx_config_t xconfig; 13823859Sml29623 bmac_rx_config_t bconfig; 13833859Sml29623 13843859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 13853859Sml29623 13863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 13873859Sml29623 portn)); 13883859Sml29623 handle = nxgep->npi_handle; 13893859Sml29623 portt = nxgep->mac.porttype; 13903859Sml29623 13913859Sml29623 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 13923859Sml29623 addr0 = ntohs(addr16p[2]); 13933859Sml29623 addr1 = ntohs(addr16p[1]); 13943859Sml29623 addr2 = ntohs(addr16p[0]); 13953859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 13963859Sml29623 rs); 13973859Sml29623 13983859Sml29623 if (rs != NPI_SUCCESS) 13993859Sml29623 goto fail; 14003859Sml29623 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 14013859Sml29623 if (rs != NPI_SUCCESS) 14023859Sml29623 goto fail; 14033859Sml29623 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 14043859Sml29623 if (rs != NPI_SUCCESS) 14053859Sml29623 goto fail; 14063859Sml29623 14073859Sml29623 /* 14083859Sml29623 * Load the multicast hash filter bits. 14093859Sml29623 */ 14103859Sml29623 hash_filter = nxgep->hash_filter; 14113859Sml29623 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 14123859Sml29623 if (hash_filter != NULL) { 14133859Sml29623 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 14143859Sml29623 (NMCFILTER_REGS - 1) - i]; 14153859Sml29623 } else { 14163859Sml29623 hashtab_e = 0; 14173859Sml29623 } 14183859Sml29623 14193859Sml29623 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 14203859Sml29623 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 14213859Sml29623 goto fail; 14223859Sml29623 } 14233859Sml29623 14243859Sml29623 if (portt == PORT_TYPE_XMAC) { 14253859Sml29623 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 14263859Sml29623 0)) != NPI_SUCCESS) 14273859Sml29623 goto fail; 14283859Sml29623 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 14293859Sml29623 14303859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 14313859Sml29623 14323859Sml29623 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 14333859Sml29623 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 14343859Sml29623 ~CFG_XMAC_RX_STRIP_CRC; 14353859Sml29623 14363859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 14373859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 14383859Sml29623 14393859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 14403859Sml29623 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 14413859Sml29623 14423859Sml29623 xconfig |= CFG_XMAC_RX_HASH_FILTER; 14433859Sml29623 14443859Sml29623 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 14453859Sml29623 xconfig)) != NPI_SUCCESS) 14463859Sml29623 goto fail; 14473859Sml29623 nxgep->mac.rx_config = xconfig; 14483859Sml29623 14493859Sml29623 /* Comparison of mac unique address is always enabled on XMAC */ 14503859Sml29623 14513859Sml29623 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 14523859Sml29623 != NPI_SUCCESS) 14533859Sml29623 goto fail; 14543859Sml29623 } else { 14553859Sml29623 (void) nxge_fflp_init_hostinfo(nxgep); 14563859Sml29623 14573859Sml29623 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 14583859Sml29623 0) != NPI_SUCCESS) 14593859Sml29623 goto fail; 14603859Sml29623 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 14613859Sml29623 14623859Sml29623 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 14633859Sml29623 ~CFG_BMAC_RX_STRIP_CRC; 14643859Sml29623 14653859Sml29623 if (nxgep->filter.all_phys_cnt != 0) 14663859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 14673859Sml29623 14683859Sml29623 if (nxgep->filter.all_multicast_cnt != 0) 14693859Sml29623 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 14703859Sml29623 14713859Sml29623 bconfig |= CFG_BMAC_RX_HASH_FILTER; 14723859Sml29623 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 14733859Sml29623 bconfig)) != NPI_SUCCESS) 14743859Sml29623 goto fail; 14753859Sml29623 nxgep->mac.rx_config = bconfig; 14763859Sml29623 14773859Sml29623 /* Always enable comparison of mac unique address */ 14783859Sml29623 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 14793859Sml29623 != NPI_SUCCESS) 14803859Sml29623 goto fail; 14813859Sml29623 } 14823859Sml29623 14833859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 14843859Sml29623 portn)); 14853859Sml29623 14863859Sml29623 return (NXGE_OK); 14873859Sml29623 14883859Sml29623 fail: 14893859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 14903859Sml29623 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 14913859Sml29623 portn)); 14923859Sml29623 14933859Sml29623 return (NXGE_ERROR | rs); 14943859Sml29623 } 14953859Sml29623 14963859Sml29623 /* Enable TXMAC */ 14973859Sml29623 14983859Sml29623 nxge_status_t 14993859Sml29623 nxge_tx_mac_enable(p_nxge_t nxgep) 15003859Sml29623 { 15013859Sml29623 npi_handle_t handle; 15023859Sml29623 npi_status_t rs = NPI_SUCCESS; 15033859Sml29623 nxge_status_t status = NXGE_OK; 15043859Sml29623 15053859Sml29623 handle = nxgep->npi_handle; 15063859Sml29623 15073859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 15083859Sml29623 nxgep->mac.portnum)); 15093859Sml29623 15103859Sml29623 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 15113859Sml29623 goto fail; 15123859Sml29623 15133859Sml29623 /* based on speed */ 15143859Sml29623 nxgep->msg_min = ETHERMIN; 15153859Sml29623 15163859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15173859Sml29623 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 15183859Sml29623 CFG_XMAC_TX)) != NPI_SUCCESS) 15193859Sml29623 goto fail; 15203859Sml29623 } else { 15213859Sml29623 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 15223859Sml29623 CFG_BMAC_TX)) != NPI_SUCCESS) 15233859Sml29623 goto fail; 15243859Sml29623 } 15253859Sml29623 15263859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 15273859Sml29623 nxgep->mac.portnum)); 15283859Sml29623 15293859Sml29623 return (NXGE_OK); 15303859Sml29623 fail: 15313859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15323859Sml29623 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 15333859Sml29623 nxgep->mac.portnum)); 15343859Sml29623 if (rs != NPI_SUCCESS) 15353859Sml29623 return (NXGE_ERROR | rs); 15363859Sml29623 else 15373859Sml29623 return (status); 15383859Sml29623 } 15393859Sml29623 15403859Sml29623 /* Disable TXMAC */ 15413859Sml29623 15423859Sml29623 nxge_status_t 15433859Sml29623 nxge_tx_mac_disable(p_nxge_t nxgep) 15443859Sml29623 { 15453859Sml29623 npi_handle_t handle; 15463859Sml29623 npi_status_t rs = NPI_SUCCESS; 15473859Sml29623 15483859Sml29623 handle = nxgep->npi_handle; 15493859Sml29623 15503859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 15513859Sml29623 nxgep->mac.portnum)); 15523859Sml29623 15533859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15543859Sml29623 if ((rs = npi_xmac_tx_config(handle, DISABLE, 15553859Sml29623 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 15563859Sml29623 goto fail; 15573859Sml29623 } else { 15583859Sml29623 if ((rs = npi_bmac_tx_config(handle, DISABLE, 15593859Sml29623 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 15603859Sml29623 goto fail; 15613859Sml29623 } 15623859Sml29623 15633859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 15643859Sml29623 nxgep->mac.portnum)); 15653859Sml29623 return (NXGE_OK); 15663859Sml29623 fail: 15673859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 15683859Sml29623 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 15693859Sml29623 nxgep->mac.portnum)); 15703859Sml29623 return (NXGE_ERROR | rs); 15713859Sml29623 } 15723859Sml29623 15733859Sml29623 /* Enable RXMAC */ 15743859Sml29623 15753859Sml29623 nxge_status_t 15763859Sml29623 nxge_rx_mac_enable(p_nxge_t nxgep) 15773859Sml29623 { 15783859Sml29623 npi_handle_t handle; 15793859Sml29623 uint8_t portn; 15803859Sml29623 npi_status_t rs = NPI_SUCCESS; 15813859Sml29623 nxge_status_t status = NXGE_OK; 15823859Sml29623 15833859Sml29623 handle = nxgep->npi_handle; 15843859Sml29623 portn = nxgep->mac.portnum; 15853859Sml29623 15863859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 15873859Sml29623 portn)); 15883859Sml29623 15893859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 15903859Sml29623 goto fail; 15913859Sml29623 15923859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 15933859Sml29623 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 15943859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 15953859Sml29623 goto fail; 15963859Sml29623 } else { 15973859Sml29623 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 15983859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 15993859Sml29623 goto fail; 16003859Sml29623 } 16013859Sml29623 16023859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 16033859Sml29623 portn)); 16043859Sml29623 16053859Sml29623 return (NXGE_OK); 16063859Sml29623 fail: 16073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16083859Sml29623 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 16093859Sml29623 portn)); 16103859Sml29623 16113859Sml29623 if (rs != NPI_SUCCESS) 16123859Sml29623 return (NXGE_ERROR | rs); 16133859Sml29623 else 16143859Sml29623 return (status); 16153859Sml29623 } 16163859Sml29623 16173859Sml29623 /* Disable RXMAC */ 16183859Sml29623 16193859Sml29623 nxge_status_t 16203859Sml29623 nxge_rx_mac_disable(p_nxge_t nxgep) 16213859Sml29623 { 16223859Sml29623 npi_handle_t handle; 16233859Sml29623 uint8_t portn; 16243859Sml29623 npi_status_t rs = NPI_SUCCESS; 16253859Sml29623 16263859Sml29623 handle = nxgep->npi_handle; 16273859Sml29623 portn = nxgep->mac.portnum; 16283859Sml29623 16293859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 16303859Sml29623 portn)); 16313859Sml29623 16323859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 16333859Sml29623 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 16343859Sml29623 CFG_XMAC_RX)) != NPI_SUCCESS) 16353859Sml29623 goto fail; 16363859Sml29623 } else { 16373859Sml29623 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 16383859Sml29623 CFG_BMAC_RX)) != NPI_SUCCESS) 16393859Sml29623 goto fail; 16403859Sml29623 } 16413859Sml29623 16423859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 16433859Sml29623 portn)); 16443859Sml29623 return (NXGE_OK); 16453859Sml29623 fail: 16463859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16473859Sml29623 "nxgep_rx_mac_disable: ", 16483859Sml29623 "Failed to disable port<%d> RxMAC", 16493859Sml29623 portn)); 16503859Sml29623 16513859Sml29623 return (NXGE_ERROR | rs); 16523859Sml29623 } 16533859Sml29623 16543859Sml29623 /* Reset TXMAC */ 16553859Sml29623 16563859Sml29623 nxge_status_t 16573859Sml29623 nxge_tx_mac_reset(p_nxge_t nxgep) 16583859Sml29623 { 16593859Sml29623 npi_handle_t handle; 16603859Sml29623 uint8_t portn; 16613859Sml29623 npi_status_t rs = NPI_SUCCESS; 16623859Sml29623 16633859Sml29623 handle = nxgep->npi_handle; 16643859Sml29623 portn = nxgep->mac.portnum; 16653859Sml29623 16663859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 16673859Sml29623 portn)); 16683859Sml29623 16693859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 16703859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 16713859Sml29623 != NPI_SUCCESS) 16723859Sml29623 goto fail; 16733859Sml29623 } else { 16743859Sml29623 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 16753859Sml29623 != NPI_SUCCESS) 16763859Sml29623 goto fail; 16773859Sml29623 } 16783859Sml29623 16793859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 16803859Sml29623 portn)); 16813859Sml29623 16823859Sml29623 return (NXGE_OK); 16833859Sml29623 fail: 16843859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16853859Sml29623 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 16863859Sml29623 portn)); 16873859Sml29623 16883859Sml29623 return (NXGE_ERROR | rs); 16893859Sml29623 } 16903859Sml29623 16913859Sml29623 /* Reset RXMAC */ 16923859Sml29623 16933859Sml29623 nxge_status_t 16943859Sml29623 nxge_rx_mac_reset(p_nxge_t nxgep) 16953859Sml29623 { 16963859Sml29623 npi_handle_t handle; 16973859Sml29623 uint8_t portn; 16983859Sml29623 npi_status_t rs = NPI_SUCCESS; 16993859Sml29623 17003859Sml29623 handle = nxgep->npi_handle; 17013859Sml29623 portn = nxgep->mac.portnum; 17023859Sml29623 17033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 17043859Sml29623 portn)); 17053859Sml29623 17063859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 17073859Sml29623 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 17083859Sml29623 != NPI_SUCCESS) 17093859Sml29623 goto fail; 17103859Sml29623 } else { 17113859Sml29623 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 17123859Sml29623 != NPI_SUCCESS) 17133859Sml29623 goto fail; 17143859Sml29623 } 17153859Sml29623 17163859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 17173859Sml29623 portn)); 17183859Sml29623 17193859Sml29623 return (NXGE_OK); 17203859Sml29623 fail: 17213859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 17223859Sml29623 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 17233859Sml29623 portn)); 17243859Sml29623 return (NXGE_ERROR | rs); 17253859Sml29623 } 17263859Sml29623 17274732Sdavemq /* 10G fiber link interrupt start routine */ 17284732Sdavemq 17294732Sdavemq static nxge_status_t 17304732Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 17314732Sdavemq { 17324732Sdavemq npi_status_t rs = NPI_SUCCESS; 17334732Sdavemq uint8_t portn = nxgep->mac.portnum; 17344732Sdavemq 17354732Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 17364732Sdavemq 17374732Sdavemq if (rs != NPI_SUCCESS) 17384732Sdavemq return (NXGE_ERROR | rs); 17394732Sdavemq else 17404732Sdavemq return (NXGE_OK); 17414732Sdavemq } 17424732Sdavemq 17434732Sdavemq /* 10G fiber link interrupt stop routine */ 17444732Sdavemq 17454732Sdavemq static nxge_status_t 17464732Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 17474732Sdavemq { 17484732Sdavemq npi_status_t rs = NPI_SUCCESS; 17494732Sdavemq uint8_t portn = nxgep->mac.portnum; 17504732Sdavemq 17514732Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 17524732Sdavemq 17534732Sdavemq if (rs != NPI_SUCCESS) 17544732Sdavemq return (NXGE_ERROR | rs); 17554732Sdavemq else 17564732Sdavemq return (NXGE_OK); 17574732Sdavemq } 17584732Sdavemq 17594732Sdavemq /* 1G fiber link interrupt start routine */ 17604732Sdavemq 17614732Sdavemq static nxge_status_t 17624732Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 17634732Sdavemq { 17644732Sdavemq npi_status_t rs = NPI_SUCCESS; 17654732Sdavemq uint8_t portn = nxgep->mac.portnum; 17664732Sdavemq 17674732Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 17684732Sdavemq if (rs != NPI_SUCCESS) 17694732Sdavemq return (NXGE_ERROR | rs); 17704732Sdavemq else 17714732Sdavemq return (NXGE_OK); 17724732Sdavemq } 17734732Sdavemq 17744732Sdavemq /* 1G fiber link interrupt stop routine */ 17754732Sdavemq 17764732Sdavemq static nxge_status_t 17774732Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 17784732Sdavemq { 17794732Sdavemq npi_status_t rs = NPI_SUCCESS; 17804732Sdavemq uint8_t portn = nxgep->mac.portnum; 17814732Sdavemq 17824732Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 17834732Sdavemq 17844732Sdavemq if (rs != NPI_SUCCESS) 17854732Sdavemq return (NXGE_ERROR | rs); 17864732Sdavemq else 17874732Sdavemq return (NXGE_OK); 17884732Sdavemq } 17894732Sdavemq 17904732Sdavemq /* 1G copper link interrupt start routine */ 17914732Sdavemq 17924732Sdavemq static nxge_status_t 17934732Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 17944732Sdavemq { 17954732Sdavemq npi_status_t rs = NPI_SUCCESS; 17964732Sdavemq uint8_t portn = nxgep->mac.portnum; 17974732Sdavemq 17984732Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 17994732Sdavemq MII_BMSR, BMSR_LSTATUS); 18004732Sdavemq 18014732Sdavemq if (rs != NPI_SUCCESS) 18024732Sdavemq return (NXGE_ERROR | rs); 18034732Sdavemq else 18044732Sdavemq return (NXGE_OK); 18054732Sdavemq } 18064732Sdavemq 18074732Sdavemq /* 1G copper link interrupt stop routine */ 18084732Sdavemq 18094732Sdavemq static nxge_status_t 18104732Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 18114732Sdavemq { 18124732Sdavemq npi_status_t rs = NPI_SUCCESS; 18134732Sdavemq uint8_t portn = nxgep->mac.portnum; 18144732Sdavemq 18154732Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 18164732Sdavemq 18174732Sdavemq if (rs != NPI_SUCCESS) 18184732Sdavemq return (NXGE_ERROR | rs); 18194732Sdavemq else 18204732Sdavemq return (NXGE_OK); 18214732Sdavemq } 18224732Sdavemq 18234732Sdavemq /* Enable/Disable Link Status change interrupt */ 18243859Sml29623 18253859Sml29623 nxge_status_t 18263859Sml29623 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 18273859Sml29623 { 18284732Sdavemq uint8_t portn; 18294732Sdavemq nxge_status_t status = NXGE_OK; 18303859Sml29623 18313859Sml29623 portn = nxgep->mac.portnum; 18323859Sml29623 18333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 18344732Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 18354732Sdavemq return (NXGE_OK); 18364732Sdavemq 18374732Sdavemq if (enable == LINK_INTR_START) 18384732Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 18394732Sdavemq else if (enable == LINK_INTR_STOP) 18404732Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 18414732Sdavemq if (status != NXGE_OK) 18424732Sdavemq goto fail; 18433859Sml29623 18443859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 18453859Sml29623 18463859Sml29623 return (NXGE_OK); 18473859Sml29623 fail: 18483859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 18493859Sml29623 "nxge_link_intr: Failed to set port<%d> mif intr mode", 18503859Sml29623 portn)); 18513859Sml29623 18524732Sdavemq return (status); 18533859Sml29623 } 18543859Sml29623 18553859Sml29623 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 18563859Sml29623 18573859Sml29623 nxge_status_t 18583859Sml29623 nxge_mii_xcvr_init(p_nxge_t nxgep) 18593859Sml29623 { 18603859Sml29623 p_nxge_param_t param_arr; 18613859Sml29623 p_nxge_stats_t statsp; 18623859Sml29623 uint8_t xcvr_portn; 18633859Sml29623 p_mii_regs_t mii_regs; 18643859Sml29623 mii_bmcr_t bmcr; 18653859Sml29623 mii_bmsr_t bmsr; 18663859Sml29623 mii_anar_t anar; 18673859Sml29623 mii_gcr_t gcr; 18683859Sml29623 mii_esr_t esr; 18693859Sml29623 mii_aux_ctl_t bcm5464r_aux; 18703859Sml29623 int status = NXGE_OK; 18713859Sml29623 18723859Sml29623 uint_t delay; 18733859Sml29623 18743859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 18753859Sml29623 18763859Sml29623 param_arr = nxgep->param_arr; 18773859Sml29623 statsp = nxgep->statsp; 18783859Sml29623 xcvr_portn = statsp->mac_stats.xcvr_portn; 18793859Sml29623 18803859Sml29623 mii_regs = NULL; 18813859Sml29623 18823859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 18833859Sml29623 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 18843859Sml29623 18853859Sml29623 /* 18863859Sml29623 * Reset the transceiver. 18873859Sml29623 */ 18883859Sml29623 delay = 0; 18893859Sml29623 bmcr.value = 0; 18903859Sml29623 bmcr.bits.reset = 1; 18913859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 18923859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 18933859Sml29623 goto fail; 18943859Sml29623 do { 18953859Sml29623 drv_usecwait(500); 18963859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 18973859Sml29623 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 18983859Sml29623 != NXGE_OK) 18993859Sml29623 goto fail; 19003859Sml29623 delay++; 19013859Sml29623 } while ((bmcr.bits.reset) && (delay < 1000)); 19023859Sml29623 if (delay == 1000) { 19033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 19043859Sml29623 goto fail; 19053859Sml29623 } 19063859Sml29623 19073859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19083859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 19093859Sml29623 &bmsr.value)) != NXGE_OK) 19103859Sml29623 goto fail; 19113859Sml29623 19123859Sml29623 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 19133859Sml29623 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 19143859Sml29623 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 19153859Sml29623 param_arr[param_anar_100hdx].value = 0; 19163859Sml29623 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 19173859Sml29623 param_arr[param_anar_10hdx].value = 0; 19183859Sml29623 19193859Sml29623 /* 19203859Sml29623 * Initialize the xcvr statistics. 19213859Sml29623 */ 19223859Sml29623 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 19233859Sml29623 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 19243859Sml29623 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 19253859Sml29623 statsp->mac_stats.cap_100hdx = 0; 19263859Sml29623 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 19273859Sml29623 statsp->mac_stats.cap_10hdx = 0; 19283859Sml29623 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 19293859Sml29623 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 19303859Sml29623 19313859Sml29623 /* 19323859Sml29623 * Initialise the xcvr advertised capability statistics. 19333859Sml29623 */ 19343859Sml29623 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 19353859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 19363859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 19373859Sml29623 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 19383859Sml29623 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 19393859Sml29623 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 19403859Sml29623 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 19413859Sml29623 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 19423859Sml29623 statsp->mac_stats.adv_cap_asmpause = 19433859Sml29623 param_arr[param_anar_asmpause].value; 19443859Sml29623 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 19453859Sml29623 19463859Sml29623 19473859Sml29623 /* 19483859Sml29623 * Check for extended status just in case we're 19493859Sml29623 * running a Gigibit phy. 19503859Sml29623 */ 19513859Sml29623 if (bmsr.bits.extend_status) { 19523859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 19533859Sml29623 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 19543859Sml29623 != NXGE_OK) 19553859Sml29623 goto fail; 19563859Sml29623 param_arr[param_anar_1000fdx].value &= 19573859Sml29623 esr.bits.link_1000fdx; 19583859Sml29623 param_arr[param_anar_1000hdx].value = 0; 19593859Sml29623 19603859Sml29623 statsp->mac_stats.cap_1000fdx = 19613859Sml29623 (esr.bits.link_1000Xfdx || 19623859Sml29623 esr.bits.link_1000fdx); 19633859Sml29623 statsp->mac_stats.cap_1000hdx = 0; 19643859Sml29623 } else { 19653859Sml29623 param_arr[param_anar_1000fdx].value = 0; 19663859Sml29623 param_arr[param_anar_1000hdx].value = 0; 19673859Sml29623 } 19683859Sml29623 19693859Sml29623 /* 19703859Sml29623 * Initialize 1G Statistics once the capability is established. 19713859Sml29623 */ 19723859Sml29623 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 19733859Sml29623 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 19743859Sml29623 19753859Sml29623 /* 19763859Sml29623 * Initialise the link statistics. 19773859Sml29623 */ 19783859Sml29623 statsp->mac_stats.link_T4 = 0; 19793859Sml29623 statsp->mac_stats.link_asmpause = 0; 19803859Sml29623 statsp->mac_stats.link_pause = 0; 19813859Sml29623 statsp->mac_stats.link_speed = 0; 19823859Sml29623 statsp->mac_stats.link_duplex = 0; 19833859Sml29623 statsp->mac_stats.link_up = 0; 19843859Sml29623 19853859Sml29623 /* 19863859Sml29623 * Switch off Auto-negotiation, 100M and full duplex. 19873859Sml29623 */ 19883859Sml29623 bmcr.value = 0; 19893859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 19903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 19913859Sml29623 goto fail; 19923859Sml29623 19933859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 19943859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 19953859Sml29623 bmcr.bits.loopback = 1; 19963859Sml29623 bmcr.bits.enable_autoneg = 0; 19973859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 19983859Sml29623 bmcr.bits.speed_1000_sel = 1; 19993859Sml29623 bmcr.bits.duplex_mode = 1; 20003859Sml29623 param_arr[param_autoneg].value = 0; 20013859Sml29623 } else { 20023859Sml29623 bmcr.bits.loopback = 0; 20033859Sml29623 } 20043859Sml29623 20053859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 20063859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 20073859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 20083859Sml29623 param_arr[param_autoneg].value = 0; 20093859Sml29623 bcm5464r_aux.value = 0; 20103859Sml29623 bcm5464r_aux.bits.ext_lb = 1; 20113859Sml29623 bcm5464r_aux.bits.write_1 = 1; 20123859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20133859Sml29623 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 20143859Sml29623 != NXGE_OK) 20153859Sml29623 goto fail; 20163859Sml29623 } 20173859Sml29623 20183859Sml29623 if (param_arr[param_autoneg].value) { 20193859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 20203859Sml29623 "Restarting Auto-negotiation.")); 20213859Sml29623 /* 20223859Sml29623 * Setup our Auto-negotiation advertisement register. 20233859Sml29623 */ 20243859Sml29623 anar.value = 0; 20253859Sml29623 anar.bits.selector = 1; 20263859Sml29623 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 20273859Sml29623 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 20283859Sml29623 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 20293859Sml29623 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 20303859Sml29623 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 20313859Sml29623 anar.bits.cap_asmpause = 0; 20323859Sml29623 anar.bits.cap_pause = 0; 20333859Sml29623 if (param_arr[param_anar_1000fdx].value || 20343859Sml29623 param_arr[param_anar_100fdx].value || 20353859Sml29623 param_arr[param_anar_10fdx].value) { 20363859Sml29623 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 20373859Sml29623 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 20383859Sml29623 } 20393859Sml29623 20403859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20413859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 20423859Sml29623 != NXGE_OK) 20433859Sml29623 goto fail; 20443859Sml29623 if (bmsr.bits.extend_status) { 20453859Sml29623 gcr.value = 0; 20463859Sml29623 gcr.bits.ms_mode_en = 20473859Sml29623 param_arr[param_master_cfg_enable].value; 20483859Sml29623 gcr.bits.master = 20493859Sml29623 param_arr[param_master_cfg_value].value; 20503859Sml29623 gcr.bits.link_1000fdx = 20513859Sml29623 param_arr[param_anar_1000fdx].value; 20523859Sml29623 gcr.bits.link_1000hdx = 20533859Sml29623 param_arr[param_anar_1000hdx].value; 20543859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20553859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 20563859Sml29623 != NXGE_OK) 20573859Sml29623 goto fail; 20583859Sml29623 } 20593859Sml29623 20603859Sml29623 bmcr.bits.enable_autoneg = 1; 20613859Sml29623 bmcr.bits.restart_autoneg = 1; 20623859Sml29623 20633859Sml29623 } else { 20643859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 20653859Sml29623 bmcr.bits.speed_1000_sel = 20663859Sml29623 param_arr[param_anar_1000fdx].value | 20673859Sml29623 param_arr[param_anar_1000hdx].value; 20683859Sml29623 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 20693859Sml29623 (param_arr[param_anar_100fdx].value | 20703859Sml29623 param_arr[param_anar_100hdx].value); 20713859Sml29623 if (bmcr.bits.speed_1000_sel) { 20723859Sml29623 statsp->mac_stats.link_speed = 1000; 20733859Sml29623 gcr.value = 0; 20743859Sml29623 gcr.bits.ms_mode_en = 20753859Sml29623 param_arr[param_master_cfg_enable].value; 20763859Sml29623 gcr.bits.master = 20773859Sml29623 param_arr[param_master_cfg_value].value; 20783859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 20793859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 20803859Sml29623 gcr.value)) 20813859Sml29623 != NXGE_OK) 20823859Sml29623 goto fail; 20833859Sml29623 if (param_arr[param_anar_1000fdx].value) { 20843859Sml29623 bmcr.bits.duplex_mode = 1; 20853859Sml29623 statsp->mac_stats.link_duplex = 2; 20863859Sml29623 } else 20873859Sml29623 statsp->mac_stats.link_duplex = 1; 20883859Sml29623 } else if (bmcr.bits.speed_sel) { 20893859Sml29623 statsp->mac_stats.link_speed = 100; 20903859Sml29623 if (param_arr[param_anar_100fdx].value) { 20913859Sml29623 bmcr.bits.duplex_mode = 1; 20923859Sml29623 statsp->mac_stats.link_duplex = 2; 20933859Sml29623 } else 20943859Sml29623 statsp->mac_stats.link_duplex = 1; 20953859Sml29623 } else { 20963859Sml29623 statsp->mac_stats.link_speed = 10; 20973859Sml29623 if (param_arr[param_anar_10fdx].value) { 20983859Sml29623 bmcr.bits.duplex_mode = 1; 20993859Sml29623 statsp->mac_stats.link_duplex = 2; 21003859Sml29623 } else 21013859Sml29623 statsp->mac_stats.link_duplex = 1; 21023859Sml29623 } 21033859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 21043859Sml29623 statsp->mac_stats.link_asmpause = 21053859Sml29623 statsp->mac_stats.cap_asmpause; 21063859Sml29623 statsp->mac_stats.link_pause = 21073859Sml29623 statsp->mac_stats.cap_pause; 21083859Sml29623 } 21093859Sml29623 21103859Sml29623 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 21113859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 21123859Sml29623 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 21133859Sml29623 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 21143859Sml29623 /* BCM5464R 1000mbps external loopback mode */ 21153859Sml29623 gcr.value = 0; 21163859Sml29623 gcr.bits.ms_mode_en = 1; 21173859Sml29623 gcr.bits.master = 1; 21183859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 21193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gcr), 21203859Sml29623 gcr.value)) 21213859Sml29623 != NXGE_OK) 21223859Sml29623 goto fail; 21233859Sml29623 bmcr.value = 0; 21243859Sml29623 bmcr.bits.speed_1000_sel = 1; 21253859Sml29623 statsp->mac_stats.link_speed = 1000; 21263859Sml29623 } else if (statsp->port_stats.lb_mode 21273859Sml29623 == nxge_lb_ext100) { 21283859Sml29623 /* BCM5464R 100mbps external loopback mode */ 21293859Sml29623 bmcr.value = 0; 21303859Sml29623 bmcr.bits.speed_sel = 1; 21313859Sml29623 bmcr.bits.duplex_mode = 1; 21323859Sml29623 statsp->mac_stats.link_speed = 100; 21333859Sml29623 } else if (statsp->port_stats.lb_mode 21343859Sml29623 == nxge_lb_ext10) { 21353859Sml29623 /* BCM5464R 10mbps external loopback mode */ 21363859Sml29623 bmcr.value = 0; 21373859Sml29623 bmcr.bits.duplex_mode = 1; 21383859Sml29623 statsp->mac_stats.link_speed = 10; 21393859Sml29623 } 21403859Sml29623 } 21413859Sml29623 } 21423859Sml29623 21433859Sml29623 if ((status = nxge_mii_write(nxgep, xcvr_portn, 21443859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), 21453859Sml29623 bmcr.value)) != NXGE_OK) 21463859Sml29623 goto fail; 21473859Sml29623 21483859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 21493859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 21503859Sml29623 goto fail; 21513859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 21523859Sml29623 21533859Sml29623 /* 21543859Sml29623 * Initialize the xcvr status kept in the context structure. 21553859Sml29623 */ 21563859Sml29623 nxgep->soft_bmsr.value = 0; 21573859Sml29623 21583859Sml29623 if ((status = nxge_mii_read(nxgep, xcvr_portn, 21593859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 21603859Sml29623 &nxgep->bmsr.value)) != NXGE_OK) 21613859Sml29623 goto fail; 21623859Sml29623 21633859Sml29623 statsp->mac_stats.xcvr_inits++; 21643859Sml29623 nxgep->bmsr.value = 0; 21653859Sml29623 21663859Sml29623 fail: 21673859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 21683859Sml29623 "<== nxge_mii_xcvr_init status 0x%x", status)); 21693859Sml29623 return (status); 21703859Sml29623 } 21713859Sml29623 21723859Sml29623 /* Read from a MII compliant register */ 21733859Sml29623 21743859Sml29623 nxge_status_t 21753859Sml29623 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 21763859Sml29623 uint16_t *value) 21773859Sml29623 { 21783859Sml29623 npi_status_t rs = NPI_SUCCESS; 21793859Sml29623 21803859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 21813859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 21823859Sml29623 21833859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 21843859Sml29623 21853859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 21863859Sml29623 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 21873859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 21883859Sml29623 goto fail; 21893859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 21903859Sml29623 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 21913859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 21923859Sml29623 goto fail; 21933859Sml29623 } else 21943859Sml29623 goto fail; 21953859Sml29623 21963859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 21973859Sml29623 21983859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 21993859Sml29623 "xcvr_reg<%d> value=0x%x", 22003859Sml29623 xcvr_portn, xcvr_reg, *value)); 22013859Sml29623 return (NXGE_OK); 22023859Sml29623 fail: 22033859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22043859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22053859Sml29623 "nxge_mii_read: Failed to read mii on xcvr %d", 22063859Sml29623 xcvr_portn)); 22073859Sml29623 22083859Sml29623 return (NXGE_ERROR | rs); 22093859Sml29623 } 22103859Sml29623 22113859Sml29623 /* Write to a MII compliant Register */ 22123859Sml29623 22133859Sml29623 nxge_status_t 22143859Sml29623 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 22153859Sml29623 uint16_t value) 22163859Sml29623 { 22173859Sml29623 npi_status_t rs = NPI_SUCCESS; 22183859Sml29623 22193859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 22203859Sml29623 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 22213859Sml29623 value)); 22223859Sml29623 22233859Sml29623 MUTEX_ENTER(&nxge_mii_lock); 22243859Sml29623 22253859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 22263859Sml29623 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 22273859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 22283859Sml29623 goto fail; 22293859Sml29623 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 22303859Sml29623 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 22313859Sml29623 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 22323859Sml29623 goto fail; 22333859Sml29623 } else 22343859Sml29623 goto fail; 22353859Sml29623 22363859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22373859Sml29623 22383859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 22393859Sml29623 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 22403859Sml29623 return (NXGE_OK); 22413859Sml29623 fail: 22423859Sml29623 MUTEX_EXIT(&nxge_mii_lock); 22433859Sml29623 22443859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22453859Sml29623 "nxge_mii_write: Failed to write mii on xcvr %d", 22463859Sml29623 xcvr_portn)); 22473859Sml29623 22483859Sml29623 return (NXGE_ERROR | rs); 22493859Sml29623 } 22503859Sml29623 22513859Sml29623 /* Perform read from Clause45 serdes / transceiver device */ 22523859Sml29623 22533859Sml29623 nxge_status_t 22543859Sml29623 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 22553859Sml29623 uint16_t xcvr_reg, uint16_t *value) 22563859Sml29623 { 22573859Sml29623 npi_status_t rs = NPI_SUCCESS; 22583859Sml29623 22593859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 22603859Sml29623 xcvr_portn)); 22613859Sml29623 22623859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 22633859Sml29623 22643859Sml29623 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 22653859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 22663859Sml29623 goto fail; 22673859Sml29623 22683859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 22693859Sml29623 22703859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 22713859Sml29623 xcvr_portn)); 22723859Sml29623 return (NXGE_OK); 22733859Sml29623 fail: 22743859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 22753859Sml29623 22763859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 22773859Sml29623 "nxge_mdio_read: Failed to read mdio on xcvr %d", 22783859Sml29623 xcvr_portn)); 22793859Sml29623 22803859Sml29623 return (NXGE_ERROR | rs); 22813859Sml29623 } 22823859Sml29623 22833859Sml29623 /* Perform write to Clause45 serdes / transceiver device */ 22843859Sml29623 22853859Sml29623 nxge_status_t 22863859Sml29623 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 22873859Sml29623 uint16_t xcvr_reg, uint16_t value) 22883859Sml29623 { 22893859Sml29623 npi_status_t rs = NPI_SUCCESS; 22903859Sml29623 22913859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 22923859Sml29623 xcvr_portn)); 22933859Sml29623 22943859Sml29623 MUTEX_ENTER(&nxge_mdio_lock); 22953859Sml29623 22963859Sml29623 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 22973859Sml29623 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 22983859Sml29623 goto fail; 22993859Sml29623 23003859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 23013859Sml29623 23023859Sml29623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 23033859Sml29623 xcvr_portn)); 23043859Sml29623 return (NXGE_OK); 23053859Sml29623 fail: 23063859Sml29623 MUTEX_EXIT(&nxge_mdio_lock); 23073859Sml29623 23083859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23093859Sml29623 "nxge_mdio_write: Failed to write mdio on xcvr %d", 23103859Sml29623 xcvr_portn)); 23113859Sml29623 23123859Sml29623 return (NXGE_ERROR | rs); 23133859Sml29623 } 23143859Sml29623 23153859Sml29623 23163859Sml29623 /* Check MII to see if there is any link status change */ 23173859Sml29623 23183859Sml29623 nxge_status_t 23193859Sml29623 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 23203859Sml29623 nxge_link_state_t *link_up) 23213859Sml29623 { 23223859Sml29623 p_nxge_param_t param_arr; 23233859Sml29623 p_nxge_stats_t statsp; 23243859Sml29623 p_mii_regs_t mii_regs; 23253859Sml29623 p_mii_bmsr_t soft_bmsr; 23263859Sml29623 mii_anar_t anar; 23273859Sml29623 mii_anlpar_t anlpar; 23283859Sml29623 mii_anar_t an_common; 23293859Sml29623 mii_aner_t aner; 23303859Sml29623 mii_gsr_t gsr; 23313859Sml29623 nxge_status_t status = NXGE_OK; 23323859Sml29623 23333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 23343859Sml29623 23353859Sml29623 mii_regs = NULL; 23363859Sml29623 param_arr = nxgep->param_arr; 23373859Sml29623 statsp = nxgep->statsp; 23383859Sml29623 soft_bmsr = &nxgep->soft_bmsr; 23393859Sml29623 *link_up = LINK_NO_CHANGE; 23403859Sml29623 23413859Sml29623 if (bmsr_ints.bits.link_status) { 23423859Sml29623 if (bmsr.bits.link_status) { 23433859Sml29623 soft_bmsr->bits.link_status = 1; 23443859Sml29623 } else { 23453859Sml29623 statsp->mac_stats.link_up = 0; 23463859Sml29623 soft_bmsr->bits.link_status = 0; 23473859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 23483859Sml29623 "Link down cable problem")); 23493859Sml29623 *link_up = LINK_IS_DOWN; 23503859Sml29623 } 23513859Sml29623 } 23523859Sml29623 23533859Sml29623 if (param_arr[param_autoneg].value) { 23543859Sml29623 if (bmsr_ints.bits.auto_neg_complete) { 23553859Sml29623 if (bmsr.bits.auto_neg_complete) 23563859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 23573859Sml29623 else 23583859Sml29623 soft_bmsr->bits.auto_neg_complete = 0; 23593859Sml29623 } 23603859Sml29623 if (soft_bmsr->bits.link_status == 0) { 23613859Sml29623 statsp->mac_stats.link_T4 = 0; 23623859Sml29623 statsp->mac_stats.link_speed = 0; 23633859Sml29623 statsp->mac_stats.link_duplex = 0; 23643859Sml29623 statsp->mac_stats.link_asmpause = 0; 23653859Sml29623 statsp->mac_stats.link_pause = 0; 23663859Sml29623 statsp->mac_stats.lp_cap_autoneg = 0; 23673859Sml29623 statsp->mac_stats.lp_cap_100T4 = 0; 23683859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 0; 23693859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 0; 23703859Sml29623 statsp->mac_stats.lp_cap_100fdx = 0; 23713859Sml29623 statsp->mac_stats.lp_cap_100hdx = 0; 23723859Sml29623 statsp->mac_stats.lp_cap_10fdx = 0; 23733859Sml29623 statsp->mac_stats.lp_cap_10hdx = 0; 23743859Sml29623 statsp->mac_stats.lp_cap_10gfdx = 0; 23753859Sml29623 statsp->mac_stats.lp_cap_10ghdx = 0; 23763859Sml29623 statsp->mac_stats.lp_cap_asmpause = 0; 23773859Sml29623 statsp->mac_stats.lp_cap_pause = 0; 23783859Sml29623 } 23793859Sml29623 } else 23803859Sml29623 soft_bmsr->bits.auto_neg_complete = 1; 23813859Sml29623 23823859Sml29623 if ((bmsr_ints.bits.link_status || 23833859Sml29623 bmsr_ints.bits.auto_neg_complete) && 23843859Sml29623 soft_bmsr->bits.link_status && 23853859Sml29623 soft_bmsr->bits.auto_neg_complete) { 23863859Sml29623 statsp->mac_stats.link_up = 1; 23873859Sml29623 if (param_arr[param_autoneg].value) { 23883859Sml29623 if ((status = nxge_mii_read(nxgep, 23893859Sml29623 statsp->mac_stats.xcvr_portn, 23903859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anar), 23913859Sml29623 &anar.value)) != NXGE_OK) 23923859Sml29623 goto fail; 23933859Sml29623 if ((status = nxge_mii_read(nxgep, 23943859Sml29623 statsp->mac_stats.xcvr_portn, 23953859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 23963859Sml29623 &anlpar.value)) != NXGE_OK) 23973859Sml29623 goto fail; 23983859Sml29623 if ((status = nxge_mii_read(nxgep, 23993859Sml29623 statsp->mac_stats.xcvr_portn, 24003859Sml29623 (uint8_t)(uint64_t)(&mii_regs->aner), 24013859Sml29623 &aner.value)) != NXGE_OK) 24023859Sml29623 goto fail; 24033859Sml29623 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 24043859Sml29623 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 24053859Sml29623 statsp->mac_stats.lp_cap_100fdx = 24063859Sml29623 anlpar.bits.cap_100fdx; 24073859Sml29623 statsp->mac_stats.lp_cap_100hdx = 24083859Sml29623 anlpar.bits.cap_100hdx; 24093859Sml29623 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 24103859Sml29623 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 24113859Sml29623 statsp->mac_stats.lp_cap_asmpause = 24123859Sml29623 anlpar.bits.cap_asmpause; 24133859Sml29623 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 24143859Sml29623 an_common.value = anar.value & anlpar.value; 24153859Sml29623 if (param_arr[param_anar_1000fdx].value || 24163859Sml29623 param_arr[param_anar_1000hdx].value) { 24173859Sml29623 if ((status = nxge_mii_read(nxgep, 24183859Sml29623 statsp->mac_stats.xcvr_portn, 24193859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 24203859Sml29623 &gsr.value)) 24213859Sml29623 != NXGE_OK) 24223859Sml29623 goto fail; 24233859Sml29623 statsp->mac_stats.lp_cap_1000fdx = 24243859Sml29623 gsr.bits.link_1000fdx; 24253859Sml29623 statsp->mac_stats.lp_cap_1000hdx = 24263859Sml29623 gsr.bits.link_1000hdx; 24273859Sml29623 if (param_arr[param_anar_1000fdx].value && 24283859Sml29623 gsr.bits.link_1000fdx) { 24293859Sml29623 statsp->mac_stats.link_speed = 1000; 24303859Sml29623 statsp->mac_stats.link_duplex = 2; 24313859Sml29623 } else if ( 24323859Sml29623 param_arr[param_anar_1000hdx].value && 24333859Sml29623 gsr.bits.link_1000hdx) { 24343859Sml29623 statsp->mac_stats.link_speed = 1000; 24353859Sml29623 statsp->mac_stats.link_duplex = 1; 24363859Sml29623 } 24373859Sml29623 } 24383859Sml29623 if ((an_common.value != 0) && 24393859Sml29623 !(statsp->mac_stats.link_speed)) { 24403859Sml29623 if (an_common.bits.cap_100T4) { 24413859Sml29623 statsp->mac_stats.link_T4 = 1; 24423859Sml29623 statsp->mac_stats.link_speed = 100; 24433859Sml29623 statsp->mac_stats.link_duplex = 1; 24443859Sml29623 } else if (an_common.bits.cap_100fdx) { 24453859Sml29623 statsp->mac_stats.link_speed = 100; 24463859Sml29623 statsp->mac_stats.link_duplex = 2; 24473859Sml29623 } else if (an_common.bits.cap_100hdx) { 24483859Sml29623 statsp->mac_stats.link_speed = 100; 24493859Sml29623 statsp->mac_stats.link_duplex = 1; 24503859Sml29623 } else if (an_common.bits.cap_10fdx) { 24513859Sml29623 statsp->mac_stats.link_speed = 10; 24523859Sml29623 statsp->mac_stats.link_duplex = 2; 24533859Sml29623 } else if (an_common.bits.cap_10hdx) { 24543859Sml29623 statsp->mac_stats.link_speed = 10; 24553859Sml29623 statsp->mac_stats.link_duplex = 1; 24563859Sml29623 } else { 24573859Sml29623 goto fail; 24583859Sml29623 } 24593859Sml29623 } 24603859Sml29623 if (statsp->mac_stats.link_duplex != 1) { 24613859Sml29623 statsp->mac_stats.link_asmpause = 24623859Sml29623 an_common.bits.cap_asmpause; 24633859Sml29623 if (statsp->mac_stats.link_asmpause) 24643859Sml29623 if ((statsp->mac_stats.cap_pause == 0) && 24653859Sml29623 (statsp->mac_stats.lp_cap_pause 24663859Sml29623 == 1)) 24673859Sml29623 statsp->mac_stats.link_pause 24683859Sml29623 = 0; 24693859Sml29623 else 24703859Sml29623 statsp->mac_stats.link_pause 24713859Sml29623 = 1; 24723859Sml29623 else 24733859Sml29623 statsp->mac_stats.link_pause = 24743859Sml29623 an_common.bits.cap_pause; 24753859Sml29623 } 24763859Sml29623 } 24773859Sml29623 *link_up = LINK_IS_UP; 24783859Sml29623 } 24793859Sml29623 24803859Sml29623 if (nxgep->link_notify) { 24813859Sml29623 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 24823859Sml29623 LINK_IS_DOWN); 24833859Sml29623 nxgep->link_notify = B_FALSE; 24843859Sml29623 } 24853859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 24863859Sml29623 return (NXGE_OK); 24873859Sml29623 fail: 24883859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 24893859Sml29623 "nxge_mii_check: Unable to check MII")); 24903859Sml29623 return (status); 24913859Sml29623 } 24923859Sml29623 24933859Sml29623 /* Add a multicast address entry into the HW hash table */ 24943859Sml29623 24953859Sml29623 nxge_status_t 24963859Sml29623 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 24973859Sml29623 { 24983859Sml29623 uint32_t mchash; 24993859Sml29623 p_hash_filter_t hash_filter; 25003859Sml29623 uint16_t hash_bit; 25013859Sml29623 boolean_t rx_init = B_FALSE; 25023859Sml29623 uint_t j; 25033859Sml29623 nxge_status_t status = NXGE_OK; 25043859Sml29623 25053859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 25063859Sml29623 25073859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 25083859Sml29623 mchash = crc32_mchash(addrp); 25093859Sml29623 if (nxgep->hash_filter == NULL) { 25103859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25113859Sml29623 "Allocating hash filter storage.")); 25123859Sml29623 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 25133859Sml29623 KM_SLEEP); 25143859Sml29623 } 25153859Sml29623 hash_filter = nxgep->hash_filter; 25163859Sml29623 j = mchash / HASH_REG_WIDTH; 25173859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 25183859Sml29623 hash_filter->hash_filter_regs[j] |= hash_bit; 25193859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]++; 25203859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 25213859Sml29623 hash_filter->hash_ref_cnt++; 25223859Sml29623 rx_init = B_TRUE; 25233859Sml29623 } 25243859Sml29623 if (rx_init) { 25253859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 25263859Sml29623 goto fail; 25273859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 25283859Sml29623 goto fail; 25293859Sml29623 } 25303859Sml29623 25313859Sml29623 RW_EXIT(&nxgep->filter_lock); 25323859Sml29623 25333859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 25343859Sml29623 25353859Sml29623 return (NXGE_OK); 25363859Sml29623 fail: 25373859Sml29623 RW_EXIT(&nxgep->filter_lock); 25383859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 25393859Sml29623 "Unable to add multicast address")); 25403859Sml29623 return (status); 25413859Sml29623 } 25423859Sml29623 25433859Sml29623 /* Remove a multicast address entry from the HW hash table */ 25443859Sml29623 25453859Sml29623 nxge_status_t 25463859Sml29623 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 25473859Sml29623 { 25483859Sml29623 uint32_t mchash; 25493859Sml29623 p_hash_filter_t hash_filter; 25503859Sml29623 uint16_t hash_bit; 25513859Sml29623 boolean_t rx_init = B_FALSE; 25523859Sml29623 uint_t j; 25533859Sml29623 nxge_status_t status = NXGE_OK; 25543859Sml29623 25553859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 25563859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 25573859Sml29623 mchash = crc32_mchash(addrp); 25583859Sml29623 if (nxgep->hash_filter == NULL) { 25593859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25603859Sml29623 "Hash filter already de_allocated.")); 25613859Sml29623 RW_EXIT(&nxgep->filter_lock); 25623859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 25633859Sml29623 return (NXGE_OK); 25643859Sml29623 } 25653859Sml29623 hash_filter = nxgep->hash_filter; 25663859Sml29623 hash_filter->hash_bit_ref_cnt[mchash]--; 25673859Sml29623 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 25683859Sml29623 j = mchash / HASH_REG_WIDTH; 25693859Sml29623 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 25703859Sml29623 hash_filter->hash_filter_regs[j] &= ~hash_bit; 25713859Sml29623 hash_filter->hash_ref_cnt--; 25723859Sml29623 rx_init = B_TRUE; 25733859Sml29623 } 25743859Sml29623 if (hash_filter->hash_ref_cnt == 0) { 25753859Sml29623 NXGE_DEBUG_MSG((NULL, STR_CTL, 25763859Sml29623 "De-allocating hash filter storage.")); 25773859Sml29623 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 25783859Sml29623 nxgep->hash_filter = NULL; 25793859Sml29623 } 25803859Sml29623 25813859Sml29623 if (rx_init) { 25823859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 25833859Sml29623 goto fail; 25843859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 25853859Sml29623 goto fail; 25863859Sml29623 } 25873859Sml29623 RW_EXIT(&nxgep->filter_lock); 25883859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 25893859Sml29623 25903859Sml29623 return (NXGE_OK); 25913859Sml29623 fail: 25923859Sml29623 RW_EXIT(&nxgep->filter_lock); 25933859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 25943859Sml29623 "Unable to remove multicast address")); 25953859Sml29623 25963859Sml29623 return (status); 25973859Sml29623 } 25983859Sml29623 25993859Sml29623 /* Set MAC address into MAC address HW registers */ 26003859Sml29623 26013859Sml29623 nxge_status_t 26023859Sml29623 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 26033859Sml29623 { 26043859Sml29623 nxge_status_t status = NXGE_OK; 26053859Sml29623 26063859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 26073859Sml29623 26083859Sml29623 MUTEX_ENTER(&nxgep->ouraddr_lock); 26093859Sml29623 /* 26103859Sml29623 * Exit if the address is same as ouraddr or multicast or broadcast 26113859Sml29623 */ 26123859Sml29623 if (((addrp->ether_addr_octet[0] & 01) == 1) || 26133859Sml29623 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 26143859Sml29623 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 26153859Sml29623 goto nxge_set_mac_addr_exit; 26163859Sml29623 } 26173859Sml29623 nxgep->ouraddr = *addrp; 26183859Sml29623 /* 26193859Sml29623 * Set new interface local address and re-init device. 26203859Sml29623 * This is destructive to any other streams attached 26213859Sml29623 * to this device. 26223859Sml29623 */ 26233859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 26243859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 26253859Sml29623 goto fail; 26263859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 26273859Sml29623 goto fail; 26283859Sml29623 26293859Sml29623 RW_EXIT(&nxgep->filter_lock); 26303859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26313859Sml29623 goto nxge_set_mac_addr_end; 26323859Sml29623 nxge_set_mac_addr_exit: 26333859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26343859Sml29623 nxge_set_mac_addr_end: 26353859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 26363859Sml29623 26373859Sml29623 return (NXGE_OK); 26383859Sml29623 fail: 26393859Sml29623 MUTEX_EXIT(&nxgep->ouraddr_lock); 26403859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 26413859Sml29623 "Unable to set mac address")); 26423859Sml29623 return (status); 26433859Sml29623 } 26443859Sml29623 26454693Stm144005 static 26464693Stm144005 check_link_state_t 26474693Stm144005 nxge_check_link_stop( 26484693Stm144005 nxge_t *nxge) 26494693Stm144005 { 26504693Stm144005 /* If the poll has been cancelled, return STOP. */ 26514693Stm144005 MUTEX_ENTER(&nxge->poll_lock); 26524693Stm144005 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 26534693Stm144005 nxge->poll_state = LINK_MONITOR_STOP; 26544693Stm144005 nxge->nxge_link_poll_timerid = 0; 26554693Stm144005 cv_broadcast(&nxge->poll_cv); 26564693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 26574693Stm144005 26584693Stm144005 NXGE_DEBUG_MSG((nxge, MAC_CTL, 26594693Stm144005 "nxge_check_%s_link(port<%d>) stopped.", 26604693Stm144005 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 26614693Stm144005 nxge->mac.portnum)); 26624693Stm144005 return (CHECK_LINK_STOP); 26634693Stm144005 } 26644693Stm144005 MUTEX_EXIT(&nxge->poll_lock); 26654693Stm144005 26664693Stm144005 return (CHECK_LINK_RESCHEDULE); 26674693Stm144005 } 26684693Stm144005 26693859Sml29623 /* Check status of MII (MIF or PCS) link */ 26703859Sml29623 26714732Sdavemq static nxge_status_t 26723859Sml29623 nxge_check_mii_link(p_nxge_t nxgep) 26733859Sml29623 { 26743859Sml29623 mii_bmsr_t bmsr_ints, bmsr_data; 26753859Sml29623 mii_anlpar_t anlpar; 26763859Sml29623 mii_gsr_t gsr; 26773859Sml29623 p_mii_regs_t mii_regs; 26783859Sml29623 nxge_status_t status = NXGE_OK; 26793859Sml29623 uint8_t portn; 26803859Sml29623 nxge_link_state_t link_up; 26813859Sml29623 26824693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 26834693Stm144005 return (NXGE_ERROR); 26844693Stm144005 26854693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 26864693Stm144005 return (NXGE_OK); 26874693Stm144005 26883859Sml29623 portn = nxgep->mac.portnum; 26893859Sml29623 26903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 26914693Stm144005 portn)); 26923859Sml29623 26933859Sml29623 mii_regs = NULL; 26943859Sml29623 26953859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 26963859Sml29623 26973859Sml29623 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 26983859Sml29623 goto nxge_check_mii_link_exit; 26993859Sml29623 27003859Sml29623 if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 27013859Sml29623 (uint8_t)(uint64_t)(&mii_regs->bmsr), 27023859Sml29623 &bmsr_data.value)) != NXGE_OK) 27033859Sml29623 goto fail; 27043859Sml29623 27053859Sml29623 if (nxgep->param_arr[param_autoneg].value) { 27063859Sml29623 if ((status = nxge_mii_read(nxgep, 27073859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 27083859Sml29623 (uint8_t)(uint64_t)(&mii_regs->gsr), 27093859Sml29623 &gsr.value)) != NXGE_OK) 27103859Sml29623 goto fail; 27113859Sml29623 if ((status = nxge_mii_read(nxgep, 27123859Sml29623 nxgep->statsp->mac_stats.xcvr_portn, 27133859Sml29623 (uint8_t)(uint64_t)(&mii_regs->anlpar), 27143859Sml29623 &anlpar.value)) != NXGE_OK) 27153859Sml29623 goto fail; 27163859Sml29623 if (nxgep->statsp->mac_stats.link_up && 27173859Sml29623 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 27183859Sml29623 gsr.bits.link_1000fdx) || 27193859Sml29623 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 27203859Sml29623 gsr.bits.link_1000hdx) || 27213859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 27223859Sml29623 anlpar.bits.cap_100T4) || 27233859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 27243859Sml29623 anlpar.bits.cap_100fdx) || 27253859Sml29623 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 27263859Sml29623 anlpar.bits.cap_100hdx) || 27273859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 27283859Sml29623 anlpar.bits.cap_10fdx) || 27293859Sml29623 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 27303859Sml29623 anlpar.bits.cap_10hdx))) { 27313859Sml29623 bmsr_data.bits.link_status = 0; 27323859Sml29623 } 27333859Sml29623 } 27343859Sml29623 27353859Sml29623 /* Workaround for link down issue */ 27363859Sml29623 if (bmsr_data.value == 0) { 27374732Sdavemq cmn_err(CE_NOTE, "nxge%d: !LINK DEBUG: Read zero bmsr\n", 27384732Sdavemq nxgep->instance); 27393859Sml29623 goto nxge_check_mii_link_exit; 27403859Sml29623 } 27413859Sml29623 27423859Sml29623 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 27433859Sml29623 nxgep->bmsr.value = bmsr_data.value; 27443859Sml29623 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up)) 27454693Stm144005 != NXGE_OK) 27463859Sml29623 goto fail; 27473859Sml29623 27483859Sml29623 nxge_check_mii_link_exit: 27493859Sml29623 RW_EXIT(&nxgep->filter_lock); 27503859Sml29623 if (link_up == LINK_IS_UP) { 27513859Sml29623 nxge_link_is_up(nxgep); 27523859Sml29623 } else if (link_up == LINK_IS_DOWN) { 27533859Sml29623 nxge_link_is_down(nxgep); 27543859Sml29623 } 27553859Sml29623 27563859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 27573859Sml29623 27583859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 27594693Stm144005 portn)); 27603859Sml29623 return (NXGE_OK); 27613859Sml29623 27623859Sml29623 fail: 27633859Sml29623 RW_EXIT(&nxgep->filter_lock); 27643859Sml29623 27653859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 27663859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 27674693Stm144005 "nxge_check_mii_link: Failed to check link port<%d>", 27684693Stm144005 portn)); 27693859Sml29623 return (status); 27703859Sml29623 } 27713859Sml29623 27723859Sml29623 27733859Sml29623 /*ARGSUSED*/ 27744732Sdavemq static nxge_status_t 27753859Sml29623 nxge_check_10g_link(p_nxge_t nxgep) 27763859Sml29623 { 27773859Sml29623 uint8_t portn; 27783859Sml29623 27793859Sml29623 nxge_status_t status = NXGE_OK; 27803859Sml29623 boolean_t link_up; 27813859Sml29623 27824693Stm144005 if (nxgep->nxge_magic != NXGE_MAGIC) 27834693Stm144005 return (NXGE_ERROR); 27844693Stm144005 27854693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 27864693Stm144005 return (NXGE_OK); 27874693Stm144005 27883859Sml29623 portn = nxgep->mac.portnum; 27893859Sml29623 27903859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 27914693Stm144005 portn)); 27923859Sml29623 27933859Sml29623 status = nxge_check_bcm8704_link(nxgep, &link_up); 27943859Sml29623 27953859Sml29623 if (status != NXGE_OK) 27963859Sml29623 goto fail; 27973859Sml29623 27983859Sml29623 if (link_up) { 27993859Sml29623 if (nxgep->link_notify || 28003859Sml29623 nxgep->statsp->mac_stats.link_up == 0) { 28013859Sml29623 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 28023859Sml29623 goto fail; 28033859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 28043859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 28053859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 28063859Sml29623 28073859Sml29623 nxge_link_is_up(nxgep); 28083859Sml29623 nxgep->link_notify = B_FALSE; 28093859Sml29623 } 28103859Sml29623 } else { 28113859Sml29623 if (nxgep->link_notify || 28123859Sml29623 nxgep->statsp->mac_stats.link_up == 1) { 28133859Sml29623 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 28143859Sml29623 goto fail; 28153859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 28164732Sdavemq "Link down cable problem")); 28173859Sml29623 nxgep->statsp->mac_stats.link_up = 0; 28183859Sml29623 nxgep->statsp->mac_stats.link_speed = 0; 28193859Sml29623 nxgep->statsp->mac_stats.link_duplex = 0; 28203859Sml29623 28213859Sml29623 nxge_link_is_down(nxgep); 28223859Sml29623 nxgep->link_notify = B_FALSE; 28233859Sml29623 } 28243859Sml29623 } 28253859Sml29623 28263859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 28273859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 28284693Stm144005 portn)); 28293859Sml29623 return (NXGE_OK); 28303859Sml29623 28313859Sml29623 fail: 28324693Stm144005 (void) nxge_check_link_stop(nxgep); 28334693Stm144005 28343859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 28354693Stm144005 "nxge_check_10g_link: Failed to check link port<%d>", 28364693Stm144005 portn)); 28373859Sml29623 return (status); 28383859Sml29623 } 28393859Sml29623 28403859Sml29623 28413859Sml29623 /* Declare link down */ 28423859Sml29623 28433859Sml29623 void 28443859Sml29623 nxge_link_is_down(p_nxge_t nxgep) 28453859Sml29623 { 28464732Sdavemq p_nxge_stats_t statsp; 28474732Sdavemq char link_stat_msg[64]; 28484732Sdavemq 28493859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 28503859Sml29623 28514732Sdavemq statsp = nxgep->statsp; 28524732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 28534732Sdavemq statsp->mac_stats.xcvr_portn); 28544732Sdavemq 28554732Sdavemq if (nxge_no_msg == B_FALSE) { 28564732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 28574732Sdavemq } 28584732Sdavemq 28593859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 28603859Sml29623 28613859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 28623859Sml29623 } 28633859Sml29623 28643859Sml29623 /* Declare link up */ 28653859Sml29623 28663859Sml29623 void 28673859Sml29623 nxge_link_is_up(p_nxge_t nxgep) 28683859Sml29623 { 28694732Sdavemq p_nxge_stats_t statsp; 28704732Sdavemq char link_stat_msg[64]; 28713859Sml29623 uint32_t val; 28723859Sml29623 28733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 28743859Sml29623 28754732Sdavemq statsp = nxgep->statsp; 28764732Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 28774732Sdavemq statsp->mac_stats.xcvr_portn, 28784732Sdavemq statsp->mac_stats.link_speed); 28794732Sdavemq 28804732Sdavemq if (statsp->mac_stats.link_T4) 28814732Sdavemq (void) strcat(link_stat_msg, "T4"); 28824732Sdavemq else if (statsp->mac_stats.link_duplex == 2) 28834732Sdavemq (void) strcat(link_stat_msg, "full duplex"); 28844732Sdavemq else 28854732Sdavemq (void) strcat(link_stat_msg, "half duplex"); 28864732Sdavemq 28873859Sml29623 (void) nxge_xif_init(nxgep); 28883859Sml29623 28893859Sml29623 /* Clean up symbol errors incurred during link transition */ 28903859Sml29623 if (nxgep->mac.portmode == PORT_10G_FIBER) { 28913859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 28923859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 28933859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 28943859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 28953859Sml29623 } 28963859Sml29623 28974732Sdavemq if (nxge_no_msg == B_FALSE) { 28984732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 28994732Sdavemq } 29004732Sdavemq 29013859Sml29623 mac_link_update(nxgep->mach, LINK_STATE_UP); 29023859Sml29623 29033859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 29043859Sml29623 } 29053859Sml29623 29063859Sml29623 /* 29073859Sml29623 * Calculate the bit in the multicast address filter 29083859Sml29623 * that selects the given * address. 29093859Sml29623 * Note: For GEM, the last 8-bits are used. 29103859Sml29623 */ 29113859Sml29623 uint32_t 29123859Sml29623 crc32_mchash(p_ether_addr_t addr) 29133859Sml29623 { 29143859Sml29623 uint8_t *cp; 29153859Sml29623 uint32_t crc; 29163859Sml29623 uint32_t c; 29173859Sml29623 int byte; 29183859Sml29623 int bit; 29193859Sml29623 29203859Sml29623 cp = (uint8_t *)addr; 29213859Sml29623 crc = (uint32_t)0xffffffff; 29223859Sml29623 for (byte = 0; byte < 6; byte++) { 29233859Sml29623 c = (uint32_t)cp[byte]; 29243859Sml29623 for (bit = 0; bit < 8; bit++) { 29253859Sml29623 if ((c & 0x1) ^ (crc & 0x1)) 29263859Sml29623 crc = (crc >> 1)^0xedb88320; 29273859Sml29623 else 29283859Sml29623 crc = (crc >> 1); 29293859Sml29623 c >>= 1; 29303859Sml29623 } 29313859Sml29623 } 29323859Sml29623 return ((~crc) >> (32 - HASH_BITS)); 29333859Sml29623 } 29343859Sml29623 29353859Sml29623 /* Reset serdes */ 29363859Sml29623 29373859Sml29623 nxge_status_t 29383859Sml29623 nxge_serdes_reset(p_nxge_t nxgep) 29393859Sml29623 { 29403859Sml29623 npi_handle_t handle; 29413859Sml29623 29423859Sml29623 handle = nxgep->npi_handle; 29433859Sml29623 29443859Sml29623 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 29453859Sml29623 drv_usecwait(500); 29463859Sml29623 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 29473859Sml29623 29483859Sml29623 return (NXGE_OK); 29493859Sml29623 } 29503859Sml29623 29513859Sml29623 /* Monitor link status using interrupt or polling */ 29523859Sml29623 29533859Sml29623 nxge_status_t 29543859Sml29623 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 29553859Sml29623 { 29563859Sml29623 nxge_status_t status = NXGE_OK; 29573859Sml29623 29583859Sml29623 /* 29594693Stm144005 * Return immediately if this is an imaginary XMAC port. 29604693Stm144005 * (At least, we don't have 4-port XMAC cards yet.) 29613859Sml29623 */ 29623859Sml29623 if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1)) 29633859Sml29623 return (NXGE_OK); 29643859Sml29623 29653859Sml29623 if (nxgep->statsp == NULL) { 29663859Sml29623 /* stats has not been allocated. */ 29673859Sml29623 return (NXGE_OK); 29683859Sml29623 } 29693859Sml29623 /* Don't check link if we're not in internal loopback mode */ 29703859Sml29623 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 29713859Sml29623 return (NXGE_OK); 29723859Sml29623 29733859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 29744693Stm144005 "==> nxge_link_monitor port<%d> enable=%d", 29754693Stm144005 nxgep->mac.portnum, enable)); 29763859Sml29623 if (enable == LINK_MONITOR_START) { 29773859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 29783859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 29794693Stm144005 != NXGE_OK) 29803859Sml29623 goto fail; 29813859Sml29623 } else { 29824693Stm144005 timeout_id_t timerid; 29834693Stm144005 29844693Stm144005 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 29854693Stm144005 return (NXGE_OK); 29864693Stm144005 29874732Sdavemq if (nxgep->xcvr.check_link) { 29884732Sdavemq timerid = timeout( 29894732Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 29904693Stm144005 nxgep, 29914693Stm144005 drv_usectohz(LINK_MONITOR_PERIOD)); 29924732Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 29934732Sdavemq nxgep->nxge_link_poll_timerid = timerid; 29944732Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 29954732Sdavemq } else { 29964693Stm144005 return (NXGE_ERROR); 29973859Sml29623 } 29983859Sml29623 } 29993859Sml29623 } else { 30003859Sml29623 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 30013859Sml29623 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 30024693Stm144005 != NXGE_OK) 30033859Sml29623 goto fail; 30043859Sml29623 } else { 30054693Stm144005 clock_t rv; 30064693Stm144005 30074693Stm144005 MUTEX_ENTER(&nxgep->poll_lock); 30084693Stm144005 30094693Stm144005 /* If <timerid> == 0, the link monitor has */ 30104693Stm144005 /* never been started, or just now stopped. */ 30114693Stm144005 if (nxgep->nxge_link_poll_timerid == 0) { 30124693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 30134693Stm144005 return (NXGE_OK); 30144693Stm144005 } 30154693Stm144005 30164693Stm144005 nxgep->poll_state = LINK_MONITOR_STOPPING; 30174693Stm144005 rv = cv_timedwait(&nxgep->poll_cv, 30184693Stm144005 &nxgep->poll_lock, 30194693Stm144005 ddi_get_lbolt() + 30204693Stm144005 drv_usectohz(LM_WAIT_MULTIPLIER * 30214693Stm144005 LINK_MONITOR_PERIOD)); 30224693Stm144005 if (rv == -1) { 30234693Stm144005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30244693Stm144005 "==> stopping port %d: " 30254693Stm144005 "cv_timedwait(%d) timed out", 30264693Stm144005 nxgep->mac.portnum, nxgep->poll_state)); 30274693Stm144005 nxgep->poll_state = LINK_MONITOR_STOP; 30283859Sml29623 nxgep->nxge_link_poll_timerid = 0; 30293859Sml29623 } 30304693Stm144005 30314693Stm144005 MUTEX_EXIT(&nxgep->poll_lock); 30323859Sml29623 } 30333859Sml29623 } 30343859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 30354693Stm144005 "<== nxge_link_monitor port<%d> enable=%d", 30364693Stm144005 nxgep->mac.portnum, enable)); 30373859Sml29623 return (NXGE_OK); 30383859Sml29623 fail: 30393859Sml29623 return (status); 30403859Sml29623 } 30413859Sml29623 30423859Sml29623 /* Set promiscous mode */ 30433859Sml29623 30443859Sml29623 nxge_status_t 30453859Sml29623 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 30463859Sml29623 { 30473859Sml29623 nxge_status_t status = NXGE_OK; 30483859Sml29623 30494732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 30503859Sml29623 30513859Sml29623 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 30523859Sml29623 30533859Sml29623 RW_ENTER_WRITER(&nxgep->filter_lock); 30543859Sml29623 30553859Sml29623 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 30563859Sml29623 goto fail; 30573859Sml29623 } 30583859Sml29623 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 30593859Sml29623 goto fail; 30603859Sml29623 } 30613859Sml29623 30623859Sml29623 RW_EXIT(&nxgep->filter_lock); 30633859Sml29623 30643859Sml29623 if (on) 30653859Sml29623 nxgep->statsp->mac_stats.promisc = B_TRUE; 30663859Sml29623 else 30673859Sml29623 nxgep->statsp->mac_stats.promisc = B_FALSE; 30683859Sml29623 30693859Sml29623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 30703859Sml29623 30713859Sml29623 return (NXGE_OK); 30723859Sml29623 fail: 30733859Sml29623 RW_EXIT(&nxgep->filter_lock); 30743859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 30754732Sdavemq "Unable to set promisc (%d)", on)); 30763859Sml29623 30773859Sml29623 return (status); 30783859Sml29623 } 30793859Sml29623 30803859Sml29623 /*ARGSUSED*/ 30813859Sml29623 uint_t 30823859Sml29623 nxge_mif_intr(void *arg1, void *arg2) 30833859Sml29623 { 30843859Sml29623 #ifdef NXGE_DEBUG 30853859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 30863859Sml29623 #endif 30873859Sml29623 #if NXGE_MIF 30883859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 30893859Sml29623 uint32_t status; 30903859Sml29623 npi_handle_t handle; 30913859Sml29623 uint8_t portn; 30923859Sml29623 p_nxge_stats_t statsp; 30933859Sml29623 #endif 30943859Sml29623 30953859Sml29623 #ifdef NXGE_MIF 30963859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 30973859Sml29623 nxgep = ldvp->nxgep; 30983859Sml29623 } 30993859Sml29623 nxgep = ldvp->nxgep; 31003859Sml29623 #endif 31013859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 31023859Sml29623 31033859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 31043859Sml29623 return (DDI_INTR_CLAIMED); 31053859Sml29623 31063859Sml29623 mif_intr_fail: 31073859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 31083859Sml29623 return (DDI_INTR_UNCLAIMED); 31093859Sml29623 } 31103859Sml29623 31113859Sml29623 /*ARGSUSED*/ 31123859Sml29623 uint_t 31133859Sml29623 nxge_mac_intr(void *arg1, void *arg2) 31143859Sml29623 { 31153859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 31163859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 31173859Sml29623 p_nxge_ldg_t ldgp; 31183859Sml29623 uint32_t status; 31193859Sml29623 npi_handle_t handle; 31203859Sml29623 uint8_t portn; 31213859Sml29623 p_nxge_stats_t statsp; 31223859Sml29623 npi_status_t rs = NPI_SUCCESS; 31233859Sml29623 31243859Sml29623 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 31253859Sml29623 nxgep = ldvp->nxgep; 31263859Sml29623 } 31273859Sml29623 31283859Sml29623 ldgp = ldvp->ldgp; 31293859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 31304732Sdavemq "group %d", ldgp->ldg)); 31313859Sml29623 31323859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 31333859Sml29623 /* 31343859Sml29623 * This interrupt handler is for a specific 31353859Sml29623 * mac port. 31363859Sml29623 */ 31373859Sml29623 statsp = (p_nxge_stats_t)nxgep->statsp; 31383859Sml29623 portn = nxgep->mac.portnum; 31393859Sml29623 31403859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 31414732Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 31423859Sml29623 31433859Sml29623 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 31443859Sml29623 rs = npi_xmac_tx_get_istatus(handle, portn, 31453859Sml29623 (xmac_tx_iconfig_t *)&status); 31463859Sml29623 if (rs != NPI_SUCCESS) 31473859Sml29623 goto npi_fail; 31483859Sml29623 if (status & ICFG_XMAC_TX_ALL) { 31493859Sml29623 if (status & ICFG_XMAC_TX_UNDERRUN) { 31503859Sml29623 statsp->xmac_stats.tx_underflow_err++; 31513859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31523859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 31533859Sml29623 } 31543859Sml29623 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 31553859Sml29623 statsp->xmac_stats.tx_maxpktsize_err++; 31563859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31573859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 31583859Sml29623 } 31593859Sml29623 if (status & ICFG_XMAC_TX_OVERFLOW) { 31603859Sml29623 statsp->xmac_stats.tx_overflow_err++; 31613859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31623859Sml29623 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 31633859Sml29623 } 31643859Sml29623 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 31653859Sml29623 statsp->xmac_stats.tx_fifo_xfr_err++; 31663859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31673859Sml29623 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 31683859Sml29623 } 31693859Sml29623 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 31703859Sml29623 statsp->xmac_stats.tx_byte_cnt += 31713859Sml29623 XTXMAC_BYTE_CNT_MASK; 31723859Sml29623 } 31733859Sml29623 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 31743859Sml29623 statsp->xmac_stats.tx_frame_cnt += 31753859Sml29623 XTXMAC_FRM_CNT_MASK; 31763859Sml29623 } 31773859Sml29623 } 31783859Sml29623 31793859Sml29623 rs = npi_xmac_rx_get_istatus(handle, portn, 31803859Sml29623 (xmac_rx_iconfig_t *)&status); 31813859Sml29623 if (rs != NPI_SUCCESS) 31823859Sml29623 goto npi_fail; 31833859Sml29623 if (status & ICFG_XMAC_RX_ALL) { 31843859Sml29623 if (status & ICFG_XMAC_RX_OVERFLOW) 31853859Sml29623 statsp->xmac_stats.rx_overflow_err++; 31863859Sml29623 if (status & ICFG_XMAC_RX_UNDERFLOW) { 31873859Sml29623 statsp->xmac_stats.rx_underflow_err++; 31883859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31893859Sml29623 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 31903859Sml29623 } 31913859Sml29623 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 31923859Sml29623 statsp->xmac_stats.rx_crc_err_cnt += 31933859Sml29623 XRXMAC_CRC_ER_CNT_MASK; 31943859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 31953859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 31963859Sml29623 } 31973859Sml29623 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 31983859Sml29623 statsp->xmac_stats.rx_len_err_cnt += 31993859Sml29623 MAC_LEN_ER_CNT_MASK; 32003859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32013859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 32023859Sml29623 } 32033859Sml29623 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 32043859Sml29623 statsp->xmac_stats.rx_viol_err_cnt += 32053859Sml29623 XRXMAC_CD_VIO_CNT_MASK; 32063859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32073859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 32083859Sml29623 } 32093859Sml29623 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 32103859Sml29623 statsp->xmac_stats.rx_byte_cnt += 32113859Sml29623 XRXMAC_BT_CNT_MASK; 32123859Sml29623 } 32133859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 32143859Sml29623 statsp->xmac_stats.rx_hist1_cnt += 32153859Sml29623 XRXMAC_HIST_CNT1_MASK; 32163859Sml29623 } 32173859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 32183859Sml29623 statsp->xmac_stats.rx_hist2_cnt += 32193859Sml29623 XRXMAC_HIST_CNT2_MASK; 32203859Sml29623 } 32213859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 32223859Sml29623 statsp->xmac_stats.rx_hist3_cnt += 32233859Sml29623 XRXMAC_HIST_CNT3_MASK; 32243859Sml29623 } 32253859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 32263859Sml29623 statsp->xmac_stats.rx_hist4_cnt += 32273859Sml29623 XRXMAC_HIST_CNT4_MASK; 32283859Sml29623 } 32293859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 32303859Sml29623 statsp->xmac_stats.rx_hist5_cnt += 32313859Sml29623 XRXMAC_HIST_CNT5_MASK; 32323859Sml29623 } 32333859Sml29623 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 32343859Sml29623 statsp->xmac_stats.rx_hist6_cnt += 32353859Sml29623 XRXMAC_HIST_CNT6_MASK; 32363859Sml29623 } 32373859Sml29623 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 32383859Sml29623 statsp->xmac_stats.rx_broadcast_cnt += 32393859Sml29623 XRXMAC_BC_FRM_CNT_MASK; 32403859Sml29623 } 32413859Sml29623 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 32423859Sml29623 statsp->xmac_stats.rx_mult_cnt += 32433859Sml29623 XRXMAC_MC_FRM_CNT_MASK; 32443859Sml29623 } 32453859Sml29623 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 32463859Sml29623 statsp->xmac_stats.rx_frag_cnt += 32473859Sml29623 XRXMAC_FRAG_CNT_MASK; 32483859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32493859Sml29623 NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 32503859Sml29623 } 32513859Sml29623 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 32523859Sml29623 statsp->xmac_stats.rx_frame_align_err_cnt += 32533859Sml29623 XRXMAC_AL_ER_CNT_MASK; 32543859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32553859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 32563859Sml29623 } 32573859Sml29623 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 32583859Sml29623 statsp->xmac_stats.rx_linkfault_err_cnt += 32593859Sml29623 XMAC_LINK_FLT_CNT_MASK; 32603859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32613859Sml29623 NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 32623859Sml29623 } 32633859Sml29623 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 32643859Sml29623 statsp->xmac_stats.rx_remotefault_err++; 32653859Sml29623 } 32663859Sml29623 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 32673859Sml29623 statsp->xmac_stats.rx_localfault_err++; 32683859Sml29623 } 32693859Sml29623 } 32703859Sml29623 32713859Sml29623 rs = npi_xmac_ctl_get_istatus(handle, portn, 32723859Sml29623 (xmac_ctl_iconfig_t *)&status); 32733859Sml29623 if (rs != NPI_SUCCESS) 32743859Sml29623 goto npi_fail; 32753859Sml29623 if (status & ICFG_XMAC_CTRL_ALL) { 32763859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 32773859Sml29623 statsp->xmac_stats.rx_pause_cnt++; 32783859Sml29623 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 32793859Sml29623 statsp->xmac_stats.tx_pause_state++; 32803859Sml29623 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 32813859Sml29623 statsp->xmac_stats.tx_nopause_state++; 32823859Sml29623 } 32833859Sml29623 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 32843859Sml29623 rs = npi_bmac_tx_get_istatus(handle, portn, 32853859Sml29623 (bmac_tx_iconfig_t *)&status); 32863859Sml29623 if (rs != NPI_SUCCESS) 32873859Sml29623 goto npi_fail; 32883859Sml29623 if (status & ICFG_BMAC_TX_ALL) { 32893859Sml29623 if (status & ICFG_BMAC_TX_UNDERFLOW) { 32903859Sml29623 statsp->bmac_stats.tx_underrun_err++; 32913859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32923859Sml29623 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 32933859Sml29623 } 32943859Sml29623 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 32953859Sml29623 statsp->bmac_stats.tx_max_pkt_err++; 32963859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 32973859Sml29623 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 32983859Sml29623 } 32993859Sml29623 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 33003859Sml29623 statsp->bmac_stats.tx_byte_cnt += 33013859Sml29623 BTXMAC_BYTE_CNT_MASK; 33023859Sml29623 } 33033859Sml29623 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 33043859Sml29623 statsp->bmac_stats.tx_frame_cnt += 33053859Sml29623 BTXMAC_FRM_CNT_MASK; 33063859Sml29623 } 33073859Sml29623 } 33083859Sml29623 33093859Sml29623 rs = npi_bmac_rx_get_istatus(handle, portn, 33103859Sml29623 (bmac_rx_iconfig_t *)&status); 33113859Sml29623 if (rs != NPI_SUCCESS) 33123859Sml29623 goto npi_fail; 33133859Sml29623 if (status & ICFG_BMAC_RX_ALL) { 33143859Sml29623 if (status & ICFG_BMAC_RX_OVERFLOW) { 33153859Sml29623 statsp->bmac_stats.rx_overflow_err++; 33163859Sml29623 } 33173859Sml29623 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 33183859Sml29623 statsp->bmac_stats.rx_frame_cnt += 33193859Sml29623 RXMAC_FRM_CNT_MASK; 33203859Sml29623 } 33213859Sml29623 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 33223859Sml29623 statsp->bmac_stats.rx_crc_err_cnt += 33233859Sml29623 BMAC_CRC_ER_CNT_MASK; 33243859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33253859Sml29623 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 33263859Sml29623 } 33273859Sml29623 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 33283859Sml29623 statsp->bmac_stats.rx_len_err_cnt += 33293859Sml29623 MAC_LEN_ER_CNT_MASK; 33303859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33313859Sml29623 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 33323859Sml29623 } 33333859Sml29623 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 33343859Sml29623 statsp->bmac_stats.rx_viol_err_cnt += 33353859Sml29623 BMAC_CD_VIO_CNT_MASK; 33363859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33373859Sml29623 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 33383859Sml29623 } 33393859Sml29623 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 33403859Sml29623 statsp->bmac_stats.rx_byte_cnt += 33413859Sml29623 BRXMAC_BYTE_CNT_MASK; 33423859Sml29623 } 33433859Sml29623 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 33443859Sml29623 statsp->bmac_stats.rx_align_err_cnt += 33453859Sml29623 BMAC_AL_ER_CNT_MASK; 33463859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 33473859Sml29623 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 33483859Sml29623 } 33493859Sml29623 33503859Sml29623 rs = npi_bmac_ctl_get_istatus(handle, portn, 33513859Sml29623 (bmac_ctl_iconfig_t *)&status); 33523859Sml29623 if (rs != NPI_SUCCESS) 33533859Sml29623 goto npi_fail; 33543859Sml29623 33553859Sml29623 if (status & ICFG_BMAC_CTL_ALL) { 33563859Sml29623 if (status & ICFG_BMAC_CTL_RCVPAUSE) 33573859Sml29623 statsp->bmac_stats.rx_pause_cnt++; 33583859Sml29623 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 33593859Sml29623 statsp->bmac_stats.tx_pause_state++; 33603859Sml29623 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 33613859Sml29623 statsp->bmac_stats.tx_nopause_state++; 33623859Sml29623 } 33633859Sml29623 } 33643859Sml29623 33653859Sml29623 if (ldgp->nldvs == 1) { 33663859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 33673859Sml29623 B_TRUE, ldgp->ldg_timer); 33683859Sml29623 } 33693859Sml29623 33703859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 33713859Sml29623 return (DDI_INTR_CLAIMED); 33723859Sml29623 33733859Sml29623 npi_fail: 33743859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 33753859Sml29623 return (DDI_INTR_UNCLAIMED); 33763859Sml29623 } 33773859Sml29623 33783859Sml29623 nxge_status_t 33793859Sml29623 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 33803859Sml29623 { 33813859Sml29623 uint8_t phy_port_addr; 33823859Sml29623 nxge_status_t status = NXGE_OK; 33833859Sml29623 boolean_t rx_sig_ok; 33843859Sml29623 boolean_t pcs_blk_lock; 33853859Sml29623 boolean_t link_align; 33863859Sml29623 uint16_t val1, val2, val3; 33873859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 33883859Sml29623 uint16_t val_debug; 33893859Sml29623 uint16_t val; 33903859Sml29623 #endif 33913859Sml29623 33923859Sml29623 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 33933859Sml29623 33943859Sml29623 #ifdef NXGE_DEBUG_SYMBOL_ERR 33953859Sml29623 /* Check Device 3 Register Device 3 0xC809 */ 33963859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 33973859Sml29623 if ((val_debug & ~0x200) != 0) { 33983859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 33993859Sml29623 nxgep->mac.portnum, val_debug); 34003859Sml29623 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 34013859Sml29623 &val_debug); 34023859Sml29623 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 34033859Sml29623 nxgep->mac.portnum, val_debug); 34043859Sml29623 } 34053859Sml29623 34063859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34073859Sml29623 XPCS_REG_DESCWERR_COUNTER, &val); 34083859Sml29623 if (val != 0) 34093859Sml29623 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 34103859Sml29623 34113859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34123859Sml29623 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 34133859Sml29623 if (val != 0) 34143859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 34153859Sml29623 34163859Sml29623 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 34173859Sml29623 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 34183859Sml29623 if (val != 0) 34193859Sml29623 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 34203859Sml29623 #endif 34213859Sml29623 34223859Sml29623 /* Check from BCM8704 if 10G link is up or down */ 34233859Sml29623 34243859Sml29623 /* Check Device 1 Register 0xA bit0 */ 34253859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 34263859Sml29623 BCM8704_PMA_PMD_DEV_ADDR, 34273859Sml29623 BCM8704_PMD_RECEIVE_SIG_DETECT, 34283859Sml29623 &val1); 34293859Sml29623 if (status != NXGE_OK) 34303859Sml29623 goto fail; 34313859Sml29623 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 34323859Sml29623 34333859Sml29623 /* Check Device 3 Register 0x20 bit0 */ 34343859Sml29623 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 34353859Sml29623 BCM8704_PCS_DEV_ADDR, 34363859Sml29623 BCM8704_10GBASE_R_PCS_STATUS_REG, 34373859Sml29623 &val2)) != NPI_SUCCESS) 34383859Sml29623 goto fail; 34393859Sml29623 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 34403859Sml29623 34413859Sml29623 /* Check Device 4 Register 0x18 bit12 */ 34423859Sml29623 status = nxge_mdio_read(nxgep, phy_port_addr, 34433859Sml29623 BCM8704_PHYXS_ADDR, 34443859Sml29623 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 34453859Sml29623 &val3); 34463859Sml29623 if (status != NXGE_OK) 34473859Sml29623 goto fail; 34483859Sml29623 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 34493859Sml29623 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 34503859Sml29623 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 34513859Sml29623 34523859Sml29623 #ifdef NXGE_DEBUG_ALIGN_ERR 34533859Sml29623 /* Temp workaround for link down issue */ 34543859Sml29623 if (pcs_blk_lock == B_FALSE) { 34553859Sml29623 if (val2 != 0x4) { 34563859Sml29623 pcs_blk_lock = B_TRUE; 34573859Sml29623 cmn_err(CE_NOTE, 34583859Sml29623 "!LINK DEBUG: port%d PHY Dev3 " 34593859Sml29623 "Reg 0x20 = 0x%x\n", 34603859Sml29623 nxgep->mac.portnum, val2); 34613859Sml29623 } 34623859Sml29623 } 34633859Sml29623 34643859Sml29623 if (link_align == B_FALSE) { 34653859Sml29623 if (val3 != 0x140f) { 34663859Sml29623 link_align = B_TRUE; 34673859Sml29623 cmn_err(CE_NOTE, 34683859Sml29623 "!LINK DEBUG: port%d PHY Dev4 " 34693859Sml29623 "Reg 0x18 = 0x%x\n", 34703859Sml29623 nxgep->mac.portnum, val3); 34713859Sml29623 } 34723859Sml29623 } 34733859Sml29623 34743859Sml29623 if (rx_sig_ok == B_FALSE) { 34753859Sml29623 if ((val2 == 0) || (val3 == 0)) { 34763859Sml29623 rx_sig_ok = B_TRUE; 34773859Sml29623 cmn_err(CE_NOTE, 34783859Sml29623 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 34793859Sml29623 nxgep->mac.portnum); 34803859Sml29623 } 34813859Sml29623 } 34823859Sml29623 #endif 34833859Sml29623 34843859Sml29623 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 34853859Sml29623 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 34863859Sml29623 34873859Sml29623 return (NXGE_OK); 34883859Sml29623 fail: 34893859Sml29623 return (status); 34903859Sml29623 } 34913859Sml29623 34923859Sml29623 nxge_status_t 34933859Sml29623 nxge_10g_link_led_on(p_nxge_t nxgep) 34943859Sml29623 { 34953859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 34964732Sdavemq != NPI_SUCCESS) 34973859Sml29623 return (NXGE_ERROR); 34983859Sml29623 else 34993859Sml29623 return (NXGE_OK); 35003859Sml29623 } 35013859Sml29623 35023859Sml29623 nxge_status_t 35033859Sml29623 nxge_10g_link_led_off(p_nxge_t nxgep) 35043859Sml29623 { 35053859Sml29623 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 35064732Sdavemq != NPI_SUCCESS) 35073859Sml29623 return (NXGE_ERROR); 35083859Sml29623 else 35093859Sml29623 return (NXGE_OK); 35103859Sml29623 } 35114185Sspeer 35124732Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 35134732Sdavemq 35144732Sdavemq static boolean_t 35154732Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 35164732Sdavemq { 35174732Sdavemq int i; 35184732Sdavemq int cl45_arr_len = NUM_CLAUSE_45_IDS; 35194732Sdavemq int cl22_arr_len = NUM_CLAUSE_22_IDS; 35204732Sdavemq boolean_t found = B_FALSE; 35214732Sdavemq 35224732Sdavemq switch (type) { 35234732Sdavemq case CLAUSE_45_TYPE: 35244732Sdavemq for (i = 0; i < cl45_arr_len; i++) { 3525*4782Ssbehera if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 3526*4782Ssbehera (id & BCM_PHY_ID_MASK)) { 35274732Sdavemq found = B_TRUE; 35284732Sdavemq break; 35294732Sdavemq } 35304732Sdavemq } 35314732Sdavemq break; 35324732Sdavemq case CLAUSE_22_TYPE: 35334732Sdavemq for (i = 0; i < cl22_arr_len; i++) { 3534*4782Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 3535*4782Ssbehera (id & BCM_PHY_ID_MASK)) { 35364732Sdavemq found = B_TRUE; 35374732Sdavemq break; 35384732Sdavemq } 35394732Sdavemq } 35404732Sdavemq break; 35414732Sdavemq default: 35424732Sdavemq break; 35434732Sdavemq } 35444732Sdavemq 35454732Sdavemq return (found); 35464732Sdavemq } 35474732Sdavemq 35484732Sdavemq /* 35494732Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 35504732Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 35514732Sdavemq * read. Then use the values obtained to determine the phy type of each port 35524732Sdavemq * and the Neptune type. 35534732Sdavemq */ 35544732Sdavemq 35554732Sdavemq nxge_status_t 35564732Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 35574732Sdavemq { 35584732Sdavemq int i, j, k, l; 35594732Sdavemq uint16_t val1 = 0; 35604732Sdavemq uint16_t val2 = 0; 35614732Sdavemq uint32_t pma_pmd_dev_id = 0; 35624732Sdavemq uint32_t pcs_dev_id = 0; 35634732Sdavemq uint32_t phy_id = 0; 3564*4782Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 3565*4782Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 3566*4782Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 35674732Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 35684732Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 35694732Sdavemq uint8_t phy_fd[NXGE_MAX_PHY_PORTS]; 35704732Sdavemq uint8_t port_fd[NXGE_MAX_PHY_PORTS]; 35714732Sdavemq uint8_t total_port_fd, total_phy_fd; 35724732Sdavemq nxge_status_t status = NXGE_OK; 35734732Sdavemq npi_status_t npi_status = NPI_SUCCESS; 35744732Sdavemq npi_handle_t handle; 35754732Sdavemq int prt_id = -1; 35764732Sdavemq 35774732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 35784732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 35794732Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 35804732Sdavemq nxgep->niu_type)); 35814732Sdavemq 35824732Sdavemq handle = NXGE_DEV_NPI_HANDLE(nxgep); 35834732Sdavemq j = k = l = 0; 35844732Sdavemq total_port_fd = total_phy_fd = 0; 35854732Sdavemq /* 35864732Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 35874732Sdavemq * for on chip serdes usages. 35884732Sdavemq */ 35894732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 35904732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR, 35914732Sdavemq NXGE_DEV_ID_REG_1, &val1); 35924732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PMA_PMD_DEV_ADDR, 35934732Sdavemq NXGE_DEV_ID_REG_2, &val2); 35944732Sdavemq pma_pmd_dev_id = val1; 35954732Sdavemq pma_pmd_dev_id = (pma_pmd_dev_id << 16); 35964732Sdavemq pma_pmd_dev_id |= val2; 35974732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 35984732Sdavemq "devid[0x%llx]", i, pma_pmd_dev_id)); 35994732Sdavemq 36004732Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 36014732Sdavemq pma_pmd_dev_fd[i] = 1; 36024732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 36034732Sdavemq "PMA/PMD dev found", i)); 3604*4782Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 3605*4782Ssbehera port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 3606*4782Ssbehera BCM_PHY_ID_MASK; 36074732Sdavemq j++; 36084732Sdavemq } 36094732Sdavemq } else { 36104732Sdavemq pma_pmd_dev_fd[i] = 0; 36114732Sdavemq } 36124732Sdavemq 36134732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR, 36144732Sdavemq NXGE_DEV_ID_REG_1, &val1); 36154732Sdavemq (void) npi_mac_mif_mdio_read(handle, i, NXGE_PCS_DEV_ADDR, 36164732Sdavemq NXGE_DEV_ID_REG_2, &val2); 36174732Sdavemq pcs_dev_id = val1; 36184732Sdavemq pcs_dev_id = (pcs_dev_id << 16); 36194732Sdavemq pcs_dev_id |= val2; 36204732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 36214732Sdavemq "devid[0x%llx]", i, pcs_dev_id)); 36224732Sdavemq 36234732Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 36244732Sdavemq pcs_dev_fd[i] = 1; 36254732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 36264732Sdavemq "dev found", i)); 3627*4782Ssbehera if (k < NXGE_PORTS_NEPTUNE) { 3628*4782Ssbehera port_pcs_dev_id[k] = pcs_dev_id & 3629*4782Ssbehera BCM_PHY_ID_MASK; 36304732Sdavemq k++; 36314732Sdavemq } 36324732Sdavemq } else { 36334732Sdavemq pcs_dev_fd[i] = 0; 36344732Sdavemq } 36354732Sdavemq 36364732Sdavemq if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) 36374732Sdavemq port_fd[i] = 1; 36384732Sdavemq else 36394732Sdavemq port_fd[i] = 0; 36404732Sdavemq total_port_fd += port_fd[i]; 36414732Sdavemq 36424732Sdavemq npi_status = npi_mac_mif_mii_read(handle, i, 36434732Sdavemq NXGE_PHY_ID_REG_1, &val1); 36444732Sdavemq if (npi_status != NPI_SUCCESS) { 36454732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 36464732Sdavemq "clause 22 read to reg 2 failed!!!")); 36474732Sdavemq goto error_exit; 36484732Sdavemq } 36494732Sdavemq npi_status = npi_mac_mif_mii_read(handle, i, 36504732Sdavemq NXGE_PHY_ID_REG_2, &val2); 36514732Sdavemq if (npi_status != 0) { 36524732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 36534732Sdavemq "clause 22 read to reg 3 failed!!!")); 36544732Sdavemq goto error_exit; 36554732Sdavemq } 36564732Sdavemq phy_id = val1; 36574732Sdavemq phy_id = (phy_id << 16); 36584732Sdavemq phy_id |= val2; 36594732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 36604732Sdavemq "[0x%llx]", i, phy_id)); 36614732Sdavemq 36624732Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 36634732Sdavemq phy_fd[i] = 1; 36644732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 36654732Sdavemq "found", i)); 3666*4782Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 3667*4782Ssbehera port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 36684732Sdavemq l++; 36694732Sdavemq } 36704732Sdavemq } else { 36714732Sdavemq phy_fd[i] = 0; 36724732Sdavemq } 36734732Sdavemq total_phy_fd += phy_fd[i]; 36744732Sdavemq } 36754732Sdavemq 36764732Sdavemq switch (total_port_fd) { 36774732Sdavemq case 2: 36784732Sdavemq switch (total_phy_fd) { 36794732Sdavemq case 2: 36804732Sdavemq /* 2 10G, 2 1G */ 3681*4782Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 3682*4782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 3683*4782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 3684*4782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 3685*4782Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 3686*4782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY))) { 36874732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 36884732Sdavemq } else { 36894732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36904732Sdavemq "Unsupported neptune type 1")); 36914732Sdavemq goto error_exit; 36924732Sdavemq } 36934732Sdavemq break; 36944732Sdavemq case 1: 36954732Sdavemq /* TODO - 2 10G, 1 1G */ 36964732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 36974732Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 36984732Sdavemq goto error_exit; 36994732Sdavemq case 0: 37004732Sdavemq /* 2 10G */ 3701*4782Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 3702*4782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 3703*4782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 3704*4782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 37054732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF; 37064732Sdavemq } else { 37074732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37084732Sdavemq "Unsupported neptune type 2")); 37094732Sdavemq goto error_exit; 37104732Sdavemq } 37114732Sdavemq break; 37124732Sdavemq case 4: 37134732Sdavemq /* Maramba with 2 XAUI */ 3714*4782Ssbehera if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 3715*4782Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 3716*4782Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 3717*4782Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 3718*4782Ssbehera ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 3719*4782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 3720*4782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 3721*4782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 37224732Sdavemq hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 37234732Sdavemq 37244732Sdavemq /* 37254732Sdavemq * Check the first phy port address against 37264732Sdavemq * the known phy start addresses to determine 37274732Sdavemq * the platform type. 37284732Sdavemq */ 37294732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 37304732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 37314732Sdavemq if (phy_fd[i] == 1) 37324732Sdavemq break; 37334732Sdavemq } 37344732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 37354732Sdavemq hw_p->platform_type = 37364732Sdavemq P_NEPTUNE_MARAMBA_P0; 37374732Sdavemq } else if (i == 37384732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 37394732Sdavemq hw_p->platform_type = 37404732Sdavemq P_NEPTUNE_MARAMBA_P1; 37414732Sdavemq } else { 37424732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37434732Sdavemq "Unknown port %d...Cannot " 37444732Sdavemq "determine platform type", i)); 37454732Sdavemq } 37464732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37474732Sdavemq "Maramba with 2 XAUI")); 37484732Sdavemq } else { 37494732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37504732Sdavemq "Unsupported neptune type 3")); 37514732Sdavemq goto error_exit; 37524732Sdavemq } 37534732Sdavemq break; 37544732Sdavemq default: 37554732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37564732Sdavemq "Unsupported neptune type 5")); 37574732Sdavemq goto error_exit; 37584732Sdavemq } 3759*4782Ssbehera break; 37604732Sdavemq case 1: 37614732Sdavemq switch (total_phy_fd) { 37624732Sdavemq case 3: 3763*4782Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 3764*4782Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 37654732Sdavemq /* The 10G port is BCM8704 */ 37664732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 37674732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 37684732Sdavemq if (port_fd[i] == 1) { 37694732Sdavemq prt_id = i; 37704732Sdavemq break; 37714732Sdavemq } 37724732Sdavemq } 37734732Sdavemq 37744732Sdavemq if (nxgep->niu_type == N2_NIU) 37754732Sdavemq prt_id %= BCM8704_N2_PORT_ADDR_BASE; 37764732Sdavemq else 37774732Sdavemq prt_id %= 37784732Sdavemq BCM8704_NEPTUNE_PORT_ADDR_BASE; 37794732Sdavemq 37804732Sdavemq if (prt_id == 0) { 37814732Sdavemq hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 37824732Sdavemq } else if (prt_id == 1) { 37834732Sdavemq hw_p->niu_type = 37844732Sdavemq NEPTUNE_1_1GC_1_10GF_2_1GC; 37854732Sdavemq } else { 37864732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37874732Sdavemq "Unsupported neptune type 6")); 37884732Sdavemq goto error_exit; 37894732Sdavemq } 37904732Sdavemq } else { 37914732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 37924732Sdavemq "Unsupported neptune type 7")); 37934732Sdavemq goto error_exit; 37944732Sdavemq } 37954732Sdavemq break; 37964732Sdavemq case 2: 37974732Sdavemq /* 37984732Sdavemq * TODO 2 1G, 1 10G mode. 37994732Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 38004732Sdavemq * 1_10G_2_1G 38014732Sdavemq */ 38024732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38034732Sdavemq "Unsupported neptune type 8")); 38044732Sdavemq goto error_exit; 38054732Sdavemq case 1: 38064732Sdavemq /* 38074732Sdavemq * TODO 1 1G, 1 10G mode. 38084732Sdavemq * Differentiate between 1_1G_1_10G and 38094732Sdavemq * 1_10G_1_1G 38104732Sdavemq */ 38114732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38124732Sdavemq "Unsupported neptune type 9")); 38134732Sdavemq goto error_exit; 38144732Sdavemq case 0: 38154732Sdavemq /* TODO 1 10G mode */ 38164732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38174732Sdavemq "Unsupported neptune type 10")); 38184732Sdavemq goto error_exit; 38194732Sdavemq case 4: 38204732Sdavemq /* Maramba with 1 XAUI */ 3821*4782Ssbehera if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 3822*4782Ssbehera (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 38234732Sdavemq /* The 10G port is BCM8704 */ 38244732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 38254732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 38264732Sdavemq if (port_fd[i] == 1) { 38274732Sdavemq prt_id = i; 38284732Sdavemq break; 38294732Sdavemq } 38304732Sdavemq } 38314732Sdavemq 38324732Sdavemq prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE; 38334732Sdavemq if (prt_id == 0) { 38344732Sdavemq hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 38354732Sdavemq } else if (prt_id == 1) { 38364732Sdavemq hw_p->niu_type = 38374732Sdavemq NEPTUNE_1_1GC_1_10GF_2_1GC; 38384732Sdavemq } else { 38394732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38404732Sdavemq "Unsupported neptune type 11")); 38414732Sdavemq goto error_exit; 38424732Sdavemq } 38434732Sdavemq 38444732Sdavemq /* 38454732Sdavemq * Check the first phy port address against 38464732Sdavemq * the known phy start addresses to determine 38474732Sdavemq * the platform type. 38484732Sdavemq */ 38494732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 38504732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 38514732Sdavemq if (phy_fd[i] == 1) 38524732Sdavemq break; 38534732Sdavemq } 38544732Sdavemq 38554732Sdavemq if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 38564732Sdavemq hw_p->platform_type = 38574732Sdavemq P_NEPTUNE_MARAMBA_P0; 38584732Sdavemq } else if (i == 38594732Sdavemq BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 38604732Sdavemq hw_p->platform_type = 38614732Sdavemq P_NEPTUNE_MARAMBA_P1; 38624732Sdavemq } else { 38634732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 38644732Sdavemq "Unknown port %d...Cannot " 38654732Sdavemq "determine platform type", i)); 38664732Sdavemq } 38674732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38684732Sdavemq "Maramba with 1 XAUI")); 38694732Sdavemq } else { 38704732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38714732Sdavemq "Unsupported neptune type 12")); 38724732Sdavemq goto error_exit; 38734732Sdavemq } 38744732Sdavemq break; 38754732Sdavemq default: 38764732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 38774732Sdavemq "Unsupported neptune type 13")); 38784732Sdavemq goto error_exit; 38794732Sdavemq } 38804732Sdavemq break; 38814732Sdavemq case 0: 38824732Sdavemq switch (total_phy_fd) { 38834732Sdavemq case 4: 3884*4782Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 3885*4782Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 3886*4782Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 3887*4782Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 38884732Sdavemq 38894732Sdavemq hw_p->niu_type = NEPTUNE_4_1GC; 38904732Sdavemq 38914732Sdavemq /* 38924732Sdavemq * Check the first phy port address against 38934732Sdavemq * the known phy start addresses to determine 38944732Sdavemq * the platform type. 38954732Sdavemq */ 38964732Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; 38974732Sdavemq i < NXGE_MAX_PHY_PORTS; i++) { 38984732Sdavemq if (phy_fd[i] == 1) 38994732Sdavemq break; 39004732Sdavemq } 39014732Sdavemq 39024732Sdavemq if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 39034732Sdavemq hw_p->platform_type = 39044732Sdavemq P_NEPTUNE_MARAMBA_P1; 39054732Sdavemq } 39064732Sdavemq } else { 39074732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39084732Sdavemq "Unsupported neptune type 14")); 39094732Sdavemq goto error_exit; 39104732Sdavemq } 39114732Sdavemq break; 39124732Sdavemq case 3: 39134732Sdavemq /* TODO 3 1G mode */ 39144732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39154732Sdavemq "Unsupported neptune type 15")); 39164732Sdavemq goto error_exit; 39174732Sdavemq case 2: 39184732Sdavemq /* TODO 2 1G mode */ 39194732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39204732Sdavemq "Unsupported neptune type 16")); 39214732Sdavemq goto error_exit; 39224732Sdavemq case 1: 39234732Sdavemq /* TODO 1 1G mode */ 39244732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39254732Sdavemq "Unsupported neptune type 17")); 39264732Sdavemq goto error_exit; 39274732Sdavemq default: 39284732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39294732Sdavemq "Unsupported neptune type 18, total phy fd %d", 39304732Sdavemq total_phy_fd)); 39314732Sdavemq goto error_exit; 39324732Sdavemq } 39334732Sdavemq break; 39344732Sdavemq default: 39354732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39364732Sdavemq "Unsupported neptune type 19")); 39374732Sdavemq goto error_exit; 39384732Sdavemq } 39394732Sdavemq 39404732Sdavemq scan_exit: 39414732Sdavemq 39424732Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 39434732Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 39444732Sdavemq return (status); 39454732Sdavemq 39464732Sdavemq error_exit: 39474732Sdavemq return (NXGE_ERROR); 39484732Sdavemq } 39494732Sdavemq 39504185Sspeer boolean_t 39514185Sspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 39524185Sspeer { 39534185Sspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 39544185Sspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 39554185Sspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 39564185Sspeer return (B_FALSE); 39574185Sspeer else 39584185Sspeer return (B_TRUE); 39594185Sspeer } 39604732Sdavemq 39614732Sdavemq static void 39624732Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 39634732Sdavemq 39644732Sdavemq npi_status_t rs = NPI_SUCCESS; 39654732Sdavemq uint8_t xcvr_portn; 39664732Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 39674732Sdavemq 39684732Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 39694732Sdavemq 39704732Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 39714732Sdavemq xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 39724732Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 39734732Sdavemq xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 39744732Sdavemq } 39754732Sdavemq /* 39764732Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 39774732Sdavemq * swapped with ethernet port number. This is 39784732Sdavemq * designed for better signal integrity in routing. 39794732Sdavemq */ 39804732Sdavemq switch (portn) { 39814732Sdavemq case 0: 39824732Sdavemq xcvr_portn += 3; 39834732Sdavemq break; 39844732Sdavemq case 1: 39854732Sdavemq xcvr_portn += 2; 39864732Sdavemq break; 39874732Sdavemq case 2: 39884732Sdavemq xcvr_portn += 1; 39894732Sdavemq break; 39904732Sdavemq case 3: 39914732Sdavemq default: 39924732Sdavemq break; 39934732Sdavemq } 39944732Sdavemq 39954732Sdavemq MUTEX_ENTER(&nxge_mii_lock); 39964732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 39974732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 39984732Sdavemq if (rs != NPI_SUCCESS) { 39994732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40004732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 40014732Sdavemq "returned error 0x[%x]", rs)); 40024732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 40034732Sdavemq return; 40044732Sdavemq } 40054732Sdavemq 40064732Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 40074732Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 40084732Sdavemq if (rs != NPI_SUCCESS) { 40094732Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40104732Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 40114732Sdavemq "returned error 0x[%x]", rs)); 40124732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 40134732Sdavemq return; 40144732Sdavemq } 40154732Sdavemq 40164732Sdavemq MUTEX_EXIT(&nxge_mii_lock); 40174732Sdavemq } 4018