16f45ec7bSml29623 /* 26f45ec7bSml29623 * CDDL HEADER START 36f45ec7bSml29623 * 46f45ec7bSml29623 * The contents of this file are subject to the terms of the 56f45ec7bSml29623 * Common Development and Distribution License (the "License"). 66f45ec7bSml29623 * You may not use this file except in compliance with the License. 76f45ec7bSml29623 * 86f45ec7bSml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96f45ec7bSml29623 * or http://www.opensolaris.org/os/licensing. 106f45ec7bSml29623 * See the License for the specific language governing permissions 116f45ec7bSml29623 * and limitations under the License. 126f45ec7bSml29623 * 136f45ec7bSml29623 * When distributing Covered Code, include this CDDL HEADER in each 146f45ec7bSml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156f45ec7bSml29623 * If applicable, add the following below this CDDL HEADER, with the 166f45ec7bSml29623 * fields enclosed by brackets "[]" replaced with your own identifying 176f45ec7bSml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 186f45ec7bSml29623 * 196f45ec7bSml29623 * CDDL HEADER END 206f45ec7bSml29623 */ 216f45ec7bSml29623 /* 22*89282175SSantwona Behera * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 236f45ec7bSml29623 */ 246f45ec7bSml29623 256f45ec7bSml29623 #include <sys/nxge/nxge_impl.h> 266f45ec7bSml29623 276f45ec7bSml29623 /* 286f45ec7bSml29623 * Tunable Receive Completion Ring Configuration B parameters. 296f45ec7bSml29623 */ 306f45ec7bSml29623 uint16_t nxge_rx_pkt_thres; /* 16 bits */ 316f45ec7bSml29623 uint8_t nxge_rx_pkt_timeout; /* 6 bits based on DMA clock divider */ 326f45ec7bSml29623 336f45ec7bSml29623 lb_property_t lb_normal = {normal, "normal", nxge_lb_normal}; 346f45ec7bSml29623 lb_property_t lb_external10g = {external, "external10g", nxge_lb_ext10g}; 356f45ec7bSml29623 lb_property_t lb_external1000 = {external, "external1000", nxge_lb_ext1000}; 366f45ec7bSml29623 lb_property_t lb_external100 = {external, "external100", nxge_lb_ext100}; 376f45ec7bSml29623 lb_property_t lb_external10 = {external, "external10", nxge_lb_ext10}; 386f45ec7bSml29623 lb_property_t lb_phy10g = {internal, "phy10g", nxge_lb_phy10g}; 396f45ec7bSml29623 lb_property_t lb_phy1000 = {internal, "phy1000", nxge_lb_phy1000}; 406f45ec7bSml29623 lb_property_t lb_phy = {internal, "phy", nxge_lb_phy}; 416f45ec7bSml29623 lb_property_t lb_serdes10g = {internal, "serdes10g", nxge_lb_serdes10g}; 426f45ec7bSml29623 lb_property_t lb_serdes1000 = {internal, "serdes", nxge_lb_serdes1000}; 436f45ec7bSml29623 lb_property_t lb_mac10g = {internal, "mac10g", nxge_lb_mac10g}; 446f45ec7bSml29623 lb_property_t lb_mac1000 = {internal, "mac1000", nxge_lb_mac1000}; 456f45ec7bSml29623 lb_property_t lb_mac = {internal, "mac10/100", nxge_lb_mac}; 466f45ec7bSml29623 476f45ec7bSml29623 uint32_t nxge_lb_dbg = 1; 486f45ec7bSml29623 void nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp); 496f45ec7bSml29623 void nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp); 50ee5416c9Syc148097 static nxge_status_t nxge_check_xaui_xfp(p_nxge_t nxgep); 516f45ec7bSml29623 526f45ec7bSml29623 extern uint32_t nxge_rx_mode; 536f45ec7bSml29623 extern uint32_t nxge_jumbo_mtu; 544df55fdeSJanie Lu extern uint16_t nxge_rdc_buf_offset; 556f45ec7bSml29623 566f45ec7bSml29623 static void 576f45ec7bSml29623 nxge_rtrace_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *); 586f45ec7bSml29623 596f45ec7bSml29623 /* ARGSUSED */ 60321febdeSsbehera nxge_status_t 616f45ec7bSml29623 nxge_global_reset(p_nxge_t nxgep) 626f45ec7bSml29623 { 63321febdeSsbehera nxge_status_t status = NXGE_OK; 64321febdeSsbehera 656f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_global_reset")); 666f45ec7bSml29623 67321febdeSsbehera if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_STOP)) != NXGE_OK) 68321febdeSsbehera return (status); 696f45ec7bSml29623 (void) nxge_intr_hw_disable(nxgep); 706f45ec7bSml29623 716f45ec7bSml29623 if ((nxgep->suspended) || 726f45ec7bSml29623 ((nxgep->statsp->port_stats.lb_mode == 736f45ec7bSml29623 nxge_lb_phy1000) || 746f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 756f45ec7bSml29623 nxge_lb_phy10g) || 766f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 776f45ec7bSml29623 nxge_lb_serdes1000) || 786f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 796f45ec7bSml29623 nxge_lb_serdes10g))) { 80321febdeSsbehera if ((status = nxge_link_init(nxgep)) != NXGE_OK) 81321febdeSsbehera return (status); 826f45ec7bSml29623 } 83321febdeSsbehera 84321febdeSsbehera if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_START)) != NXGE_OK) 85321febdeSsbehera return (status); 86321febdeSsbehera if ((status = nxge_mac_init(nxgep)) != NXGE_OK) 87321febdeSsbehera return (status); 886f45ec7bSml29623 (void) nxge_intr_hw_enable(nxgep); 896f45ec7bSml29623 906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_global_reset")); 91321febdeSsbehera return (status); 926f45ec7bSml29623 } 936f45ec7bSml29623 946f45ec7bSml29623 /* ARGSUSED */ 956f45ec7bSml29623 void 966f45ec7bSml29623 nxge_hw_id_init(p_nxge_t nxgep) 976f45ec7bSml29623 { 986f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_id_init")); 9948056c53SMichael Speer 1006f45ec7bSml29623 /* 1016f45ec7bSml29623 * Set up initial hardware parameters required such as mac mtu size. 1026f45ec7bSml29623 */ 1036f45ec7bSml29623 nxgep->mac.is_jumbo = B_FALSE; 10448056c53SMichael Speer 1051bd6825cSml29623 /* 1061bd6825cSml29623 * Set the maxframe size to 1522 (1518 + 4) to account for 1071bd6825cSml29623 * VLAN tagged packets. 1081bd6825cSml29623 */ 1091bd6825cSml29623 nxgep->mac.minframesize = NXGE_MIN_MAC_FRAMESIZE; /* 64 */ 1101bd6825cSml29623 nxgep->mac.maxframesize = NXGE_MAX_MAC_FRAMESIZE; /* 1522 */ 1116f45ec7bSml29623 11248056c53SMichael Speer NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init: maxframesize %d", 11348056c53SMichael Speer nxgep->mac.maxframesize)); 1146f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init")); 1156f45ec7bSml29623 } 1166f45ec7bSml29623 1176f45ec7bSml29623 /* ARGSUSED */ 1186f45ec7bSml29623 void 1196f45ec7bSml29623 nxge_hw_init_niu_common(p_nxge_t nxgep) 1206f45ec7bSml29623 { 1216f45ec7bSml29623 p_nxge_hw_list_t hw_p; 1226f45ec7bSml29623 1236f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_init_niu_common")); 1246f45ec7bSml29623 1256f45ec7bSml29623 if ((hw_p = nxgep->nxge_hw_p) == NULL) { 1266f45ec7bSml29623 return; 1276f45ec7bSml29623 } 1286f45ec7bSml29623 MUTEX_ENTER(&hw_p->nxge_cfg_lock); 1296f45ec7bSml29623 if (hw_p->flags & COMMON_INIT_DONE) { 1306f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 1316f45ec7bSml29623 "nxge_hw_init_niu_common" 1326f45ec7bSml29623 " already done for dip $%p function %d exiting", 1336f45ec7bSml29623 hw_p->parent_devp, nxgep->function_num)); 1346f45ec7bSml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 1356f45ec7bSml29623 return; 1366f45ec7bSml29623 } 1376f45ec7bSml29623 1386f45ec7bSml29623 hw_p->flags = COMMON_INIT_START; 1396f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common" 1406f45ec7bSml29623 " Started for device id %x with function %d", 1416f45ec7bSml29623 hw_p->parent_devp, nxgep->function_num)); 1426f45ec7bSml29623 1436f45ec7bSml29623 /* per neptune common block init */ 1446f45ec7bSml29623 (void) nxge_fflp_hw_reset(nxgep); 1456f45ec7bSml29623 1464df55fdeSJanie Lu if (nxgep->niu_hw_type != NIU_HW_TYPE_RF) { 1474df55fdeSJanie Lu switch (nxge_rdc_buf_offset) { 1484df55fdeSJanie Lu case SW_OFFSET_NO_OFFSET: 1494df55fdeSJanie Lu case SW_OFFSET_64: 1504df55fdeSJanie Lu case SW_OFFSET_128: 1514df55fdeSJanie Lu break; 1524df55fdeSJanie Lu default: 1534df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1544df55fdeSJanie Lu "nxge_hw_init_niu_common: Unsupported RDC buffer" 1554df55fdeSJanie Lu " offset code %d, setting to %d", 1564df55fdeSJanie Lu nxge_rdc_buf_offset, SW_OFFSET_NO_OFFSET)); 1574df55fdeSJanie Lu nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET; 1584df55fdeSJanie Lu break; 1594df55fdeSJanie Lu } 1604df55fdeSJanie Lu } else { 1614df55fdeSJanie Lu switch (nxge_rdc_buf_offset) { 1624df55fdeSJanie Lu case SW_OFFSET_NO_OFFSET: 1634df55fdeSJanie Lu case SW_OFFSET_64: 1644df55fdeSJanie Lu case SW_OFFSET_128: 1654df55fdeSJanie Lu case SW_OFFSET_192: 1664df55fdeSJanie Lu case SW_OFFSET_256: 1674df55fdeSJanie Lu case SW_OFFSET_320: 1684df55fdeSJanie Lu case SW_OFFSET_384: 1694df55fdeSJanie Lu case SW_OFFSET_448: 1704df55fdeSJanie Lu break; 1714df55fdeSJanie Lu default: 1724df55fdeSJanie Lu NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1734df55fdeSJanie Lu "nxge_hw_init_niu_common: Unsupported RDC buffer" 1744df55fdeSJanie Lu " offset code %d, setting to %d", 1754df55fdeSJanie Lu nxge_rdc_buf_offset, SW_OFFSET_NO_OFFSET)); 1764df55fdeSJanie Lu nxge_rdc_buf_offset = SW_OFFSET_NO_OFFSET; 1774df55fdeSJanie Lu break; 1784df55fdeSJanie Lu } 1794df55fdeSJanie Lu } 1804df55fdeSJanie Lu 1816f45ec7bSml29623 hw_p->flags = COMMON_INIT_DONE; 1826f45ec7bSml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 1836f45ec7bSml29623 1846f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common" 1856f45ec7bSml29623 " Done for device id %x with function %d", 1866f45ec7bSml29623 hw_p->parent_devp, nxgep->function_num)); 1876f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_init_niu_common")); 1886f45ec7bSml29623 } 1896f45ec7bSml29623 1906f45ec7bSml29623 /* ARGSUSED */ 1916f45ec7bSml29623 uint_t 1926f45ec7bSml29623 nxge_intr(void *arg1, void *arg2) 1936f45ec7bSml29623 { 1946f45ec7bSml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 1956f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 1966f45ec7bSml29623 uint_t serviced = DDI_INTR_UNCLAIMED; 1976f45ec7bSml29623 uint8_t ldv; 1986f45ec7bSml29623 npi_handle_t handle; 1996f45ec7bSml29623 p_nxge_ldgv_t ldgvp; 2006f45ec7bSml29623 p_nxge_ldg_t ldgp, t_ldgp; 2016f45ec7bSml29623 p_nxge_ldv_t t_ldvp; 2026f45ec7bSml29623 uint64_t vector0 = 0, vector1 = 0, vector2 = 0; 2036f45ec7bSml29623 int i, j, nldvs, nintrs = 1; 2046f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 2056f45ec7bSml29623 2066f45ec7bSml29623 /* DDI interface returns second arg as NULL (n2 niumx driver) !!! */ 2076f45ec7bSml29623 if (arg2 == NULL || (void *) ldvp->nxgep != arg2) { 2086f45ec7bSml29623 nxgep = ldvp->nxgep; 2096f45ec7bSml29623 } 2106f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr")); 2116f45ec7bSml29623 2126f45ec7bSml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 2136f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, 2146f45ec7bSml29623 "<== nxge_intr: not initialized 0x%x", serviced)); 2156f45ec7bSml29623 return (serviced); 2166f45ec7bSml29623 } 2176f45ec7bSml29623 2186f45ec7bSml29623 ldgvp = nxgep->ldgvp; 2196f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: ldgvp $%p", ldgvp)); 2206f45ec7bSml29623 if (ldvp == NULL && ldgvp) { 2216f45ec7bSml29623 t_ldvp = ldvp = ldgvp->ldvp; 2226f45ec7bSml29623 } 2236f45ec7bSml29623 if (ldvp) { 2246f45ec7bSml29623 ldgp = t_ldgp = ldvp->ldgp; 2256f45ec7bSml29623 } 2266f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 2276f45ec7bSml29623 "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp)); 2286f45ec7bSml29623 if (ldgvp == NULL || ldvp == NULL || ldgp == NULL) { 2296f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "==> nxge_intr: " 2306f45ec7bSml29623 "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp)); 2316f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_intr: not ready")); 2326f45ec7bSml29623 return (DDI_INTR_UNCLAIMED); 2336f45ec7bSml29623 } 2346f45ec7bSml29623 /* 2356f45ec7bSml29623 * This interrupt handler will have to go through all the logical 2366f45ec7bSml29623 * devices to find out which logical device interrupts us and then call 2376f45ec7bSml29623 * its handler to process the events. 2386f45ec7bSml29623 */ 2396f45ec7bSml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 2406f45ec7bSml29623 t_ldgp = ldgp; 2416f45ec7bSml29623 t_ldvp = ldgp->ldvp; 2426f45ec7bSml29623 2436f45ec7bSml29623 nldvs = ldgp->nldvs; 2446f45ec7bSml29623 2456f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: #ldvs %d #intrs %d", 2466f45ec7bSml29623 nldvs, ldgvp->ldg_intrs)); 2476f45ec7bSml29623 2486f45ec7bSml29623 serviced = DDI_INTR_CLAIMED; 2496f45ec7bSml29623 for (i = 0; i < nintrs; i++, t_ldgp++) { 2506f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr(%d): #ldvs %d " 2516f45ec7bSml29623 " #intrs %d", i, nldvs, nintrs)); 2526f45ec7bSml29623 /* Get this group's flag bits. */ 2536f45ec7bSml29623 rs = npi_ldsv_ldfs_get(handle, t_ldgp->ldg, 2546f45ec7bSml29623 &vector0, &vector1, &vector2); 2556f45ec7bSml29623 if (rs) { 2566f45ec7bSml29623 continue; 2576f45ec7bSml29623 } 2586f45ec7bSml29623 if (!vector0 && !vector1 && !vector2) { 2596f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 2606f45ec7bSml29623 "no interrupts on group %d", t_ldgp->ldg)); 2616f45ec7bSml29623 continue; 2626f45ec7bSml29623 } 2636f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 2646f45ec7bSml29623 "vector0 0x%llx vector1 0x%llx vector2 0x%llx", 2656f45ec7bSml29623 vector0, vector1, vector2)); 2666f45ec7bSml29623 nldvs = t_ldgp->nldvs; 2676f45ec7bSml29623 for (j = 0; j < nldvs; j++, t_ldvp++) { 2686f45ec7bSml29623 /* 2696f45ec7bSml29623 * Call device's handler if flag bits are on. 2706f45ec7bSml29623 */ 2716f45ec7bSml29623 ldv = t_ldvp->ldv; 2726f45ec7bSml29623 if (((ldv < NXGE_MAC_LD_START) && 2736f45ec7bSml29623 (LDV_ON(ldv, vector0) | 2746f45ec7bSml29623 (LDV_ON(ldv, vector1)))) || 2756f45ec7bSml29623 (ldv >= NXGE_MAC_LD_START && 2766f45ec7bSml29623 ((LDV2_ON_1(ldv, vector2)) || 2776f45ec7bSml29623 (LDV2_ON_2(ldv, vector2))))) { 2786f45ec7bSml29623 (void) (t_ldvp->ldv_intr_handler)( 2796f45ec7bSml29623 (caddr_t)t_ldvp, arg2); 2806f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 2816f45ec7bSml29623 "==> nxge_intr: " 2826f45ec7bSml29623 "calling device %d #ldvs %d #intrs %d", 2836f45ec7bSml29623 j, nldvs, nintrs)); 2846f45ec7bSml29623 } 2856f45ec7bSml29623 } 2866f45ec7bSml29623 } 2876f45ec7bSml29623 2886f45ec7bSml29623 t_ldgp = ldgp; 2896f45ec7bSml29623 for (i = 0; i < nintrs; i++, t_ldgp++) { 2906f45ec7bSml29623 /* rearm group interrupts */ 2916f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: arm " 2926f45ec7bSml29623 "group %d", t_ldgp->ldg)); 2936f45ec7bSml29623 (void) npi_intr_ldg_mgmt_set(handle, t_ldgp->ldg, 2946f45ec7bSml29623 t_ldgp->arm, t_ldgp->ldg_timer); 2956f45ec7bSml29623 } 2966f45ec7bSml29623 2976f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr: serviced 0x%x", 2986f45ec7bSml29623 serviced)); 2996f45ec7bSml29623 return (serviced); 3006f45ec7bSml29623 } 3016f45ec7bSml29623 30200161856Syc148097 30300161856Syc148097 /* 30400161856Syc148097 * XFP Related Status Register Values Under 3 Different Conditions 30500161856Syc148097 * 30600161856Syc148097 * -------------+-------------------------+------------------------- 3070cad6a5fSyc148097 * | Intel XFP and Avago | Picolight XFP 30800161856Syc148097 * -------------+---------+---------------+---------+--------------- 30900161856Syc148097 * | STATUS0 | TX_ALARM_STAT | STATUS0 | TX_ALARM_STAT 31000161856Syc148097 * -------------+---------+---------------+---------+--------------- 31100161856Syc148097 * No XFP | 0x639C | 0x40 | 0x639C | 0x40 31200161856Syc148097 * -------------+---------+---------------+---------+--------------- 31300161856Syc148097 * XFP,linkdown | 0x43BC | 0x40 | 0x639C | 0x40 31400161856Syc148097 * -------------+---------+---------------+---------+--------------- 31500161856Syc148097 * XFP,linkup | 0x03FC | 0x0 | 0x03FC | 0x0 31600161856Syc148097 * -------------+---------+---------------+---------+--------------- 31700161856Syc148097 * Note: 31800161856Syc148097 * STATUS0 = BCM8704_USER_ANALOG_STATUS0_REG 31900161856Syc148097 * TX_ALARM_STAT = BCM8704_USER_TX_ALARM_STATUS_REG 32000161856Syc148097 */ 3216f45ec7bSml29623 /* ARGSUSED */ 322ee5416c9Syc148097 static nxge_status_t 323ee5416c9Syc148097 nxge_check_xaui_xfp(p_nxge_t nxgep) 324ee5416c9Syc148097 { 325ee5416c9Syc148097 nxge_status_t status = NXGE_OK; 326ee5416c9Syc148097 uint8_t phy_port_addr; 327ee5416c9Syc148097 uint16_t val; 328ee5416c9Syc148097 uint16_t val1; 329ee5416c9Syc148097 uint8_t portn; 330ee5416c9Syc148097 331ee5416c9Syc148097 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_check_xaui_xfp")); 332ee5416c9Syc148097 333ee5416c9Syc148097 portn = nxgep->mac.portnum; 334ee5416c9Syc148097 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 335ee5416c9Syc148097 33600161856Syc148097 /* 33700161856Syc148097 * Keep the val1 code even though it is not used. Could be 33800161856Syc148097 * used to differenciate the "No XFP" case and "XFP,linkdown" 33900161856Syc148097 * case when a Intel XFP is used. 34000161856Syc148097 */ 341ee5416c9Syc148097 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 342ee5416c9Syc148097 BCM8704_USER_DEV3_ADDR, 343ee5416c9Syc148097 BCM8704_USER_ANALOG_STATUS0_REG, &val)) == NXGE_OK) { 344ee5416c9Syc148097 status = nxge_mdio_read(nxgep, phy_port_addr, 345ee5416c9Syc148097 BCM8704_USER_DEV3_ADDR, 346ee5416c9Syc148097 BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 347ee5416c9Syc148097 } 34800161856Syc148097 349ee5416c9Syc148097 if (status != NXGE_OK) { 350ee5416c9Syc148097 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 351ee5416c9Syc148097 NXGE_FM_EREPORT_XAUI_ERR); 35200161856Syc148097 if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities)) { 353ee5416c9Syc148097 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 354ee5416c9Syc148097 "XAUI is bad or absent on port<%d>\n", portn)); 35500161856Syc148097 } 3560cad6a5fSyc148097 #ifdef NXGE_DEBUG 3570cad6a5fSyc148097 /* 3580cad6a5fSyc148097 * As a workaround for CR6693529, do not execute this block of 3590cad6a5fSyc148097 * code for non-debug driver. When a Picolight XFP transceiver 3600cad6a5fSyc148097 * is used, register BCM8704_USER_ANALOG_STATUS0_REG returns 3610cad6a5fSyc148097 * the same 0x639C value in normal link down case, which causes 3620cad6a5fSyc148097 * false FMA messages and link reconnection problem. 3630cad6a5fSyc148097 */ 364ee5416c9Syc148097 } else if (nxgep->mac.portmode == PORT_10G_FIBER) { 365ee5416c9Syc148097 /* 366f6485eecSyc148097 * 0x03FC = 0000 0011 1111 1100 (XFP is normal) 367f6485eecSyc148097 * 0x639C = 0110 0011 1001 1100 (XFP has problem) 368ee5416c9Syc148097 * bit14 = 1: PDM loss-of-light indicator 369ee5416c9Syc148097 * bit13 = 1: PDM Rx loss-of-signal 370ee5416c9Syc148097 * bit6 = 0: Light is NOT ok 371ee5416c9Syc148097 * bit5 = 0: PMD Rx signal is NOT ok 372ee5416c9Syc148097 */ 373f6485eecSyc148097 if (val == 0x639C) { 374ee5416c9Syc148097 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 375ee5416c9Syc148097 NXGE_FM_EREPORT_XFP_ERR); 37600161856Syc148097 if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities)) { 377ee5416c9Syc148097 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37800161856Syc148097 "XFP is bad or absent on port<%d>\n", 37900161856Syc148097 portn)); 38000161856Syc148097 } 381ee5416c9Syc148097 status = NXGE_ERROR; 382ee5416c9Syc148097 } 3830cad6a5fSyc148097 #endif 384ee5416c9Syc148097 } 385ee5416c9Syc148097 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_check_xaui_xfp")); 386ee5416c9Syc148097 return (status); 387ee5416c9Syc148097 } 388ee5416c9Syc148097 389ee5416c9Syc148097 390ee5416c9Syc148097 /* ARGSUSED */ 3916f45ec7bSml29623 uint_t 3926f45ec7bSml29623 nxge_syserr_intr(void *arg1, void *arg2) 3936f45ec7bSml29623 { 3946f45ec7bSml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 3956f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 3966f45ec7bSml29623 p_nxge_ldg_t ldgp = NULL; 3976f45ec7bSml29623 npi_handle_t handle; 3986f45ec7bSml29623 sys_err_stat_t estat; 3996f45ec7bSml29623 uint_t serviced = DDI_INTR_UNCLAIMED; 4006f45ec7bSml29623 4016f45ec7bSml29623 if (arg1 == NULL && arg2 == NULL) { 4026f45ec7bSml29623 return (serviced); 4036f45ec7bSml29623 } 4046f45ec7bSml29623 if (arg2 == NULL || ((ldvp != NULL && (void *) ldvp->nxgep != arg2))) { 4056f45ec7bSml29623 if (ldvp != NULL) { 4066f45ec7bSml29623 nxgep = ldvp->nxgep; 4076f45ec7bSml29623 } 4086f45ec7bSml29623 } 4096f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, 4106f45ec7bSml29623 "==> nxge_syserr_intr: arg2 $%p arg1 $%p", nxgep, ldvp)); 4116f45ec7bSml29623 if (ldvp != NULL && ldvp->use_timer == B_FALSE) { 4126f45ec7bSml29623 ldgp = ldvp->ldgp; 4136f45ec7bSml29623 if (ldgp == NULL) { 4146f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, SYSERR_CTL, 4156f45ec7bSml29623 "<== nxge_syserrintr(no logical group): " 4166f45ec7bSml29623 "arg2 $%p arg1 $%p", nxgep, ldvp)); 4176f45ec7bSml29623 return (DDI_INTR_UNCLAIMED); 4186f45ec7bSml29623 } 4196f45ec7bSml29623 /* 4206f45ec7bSml29623 * Get the logical device state if the function uses interrupt. 4216f45ec7bSml29623 */ 4226f45ec7bSml29623 } 4236f45ec7bSml29623 4246f45ec7bSml29623 /* This interrupt handler is for system error interrupts. */ 4256f45ec7bSml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 4266f45ec7bSml29623 estat.value = 0; 4276f45ec7bSml29623 (void) npi_fzc_sys_err_stat_get(handle, &estat); 4286f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, 4296f45ec7bSml29623 "==> nxge_syserr_intr: device error 0x%016llx", estat.value)); 4306f45ec7bSml29623 4316f45ec7bSml29623 if (estat.bits.ldw.smx) { 4326f45ec7bSml29623 /* SMX */ 4336f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4346f45ec7bSml29623 "==> nxge_syserr_intr: device error - SMX")); 4356f45ec7bSml29623 } else if (estat.bits.ldw.mac) { 4366f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4376f45ec7bSml29623 "==> nxge_syserr_intr: device error - MAC")); 4386f45ec7bSml29623 /* 4396f45ec7bSml29623 * There is nothing to be done here. All MAC errors go to per 4406f45ec7bSml29623 * MAC port interrupt. MIF interrupt is the only MAC sub-block 4416f45ec7bSml29623 * that can generate status here. MIF status reported will be 4426f45ec7bSml29623 * ignored here. It is checked by per port timer instead. 4436f45ec7bSml29623 */ 4446f45ec7bSml29623 } else if (estat.bits.ldw.ipp) { 4456f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 4466f45ec7bSml29623 "==> nxge_syserr_intr: device error - IPP")); 4476f45ec7bSml29623 (void) nxge_ipp_handle_sys_errors(nxgep); 4486f45ec7bSml29623 } else if (estat.bits.ldw.zcp) { 4496f45ec7bSml29623 /* ZCP */ 450f6485eecSyc148097 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 4516f45ec7bSml29623 "==> nxge_syserr_intr: device error - ZCP")); 4526f45ec7bSml29623 (void) nxge_zcp_handle_sys_errors(nxgep); 4536f45ec7bSml29623 } else if (estat.bits.ldw.tdmc) { 4546f45ec7bSml29623 /* TDMC */ 4556f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4566f45ec7bSml29623 "==> nxge_syserr_intr: device error - TDMC")); 4576f45ec7bSml29623 /* 4586f45ec7bSml29623 * There is no TDMC system errors defined in the PRM. All TDMC 4596f45ec7bSml29623 * channel specific errors are reported on a per channel basis. 4606f45ec7bSml29623 */ 4616f45ec7bSml29623 } else if (estat.bits.ldw.rdmc) { 4626f45ec7bSml29623 /* RDMC */ 4636f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4646f45ec7bSml29623 "==> nxge_syserr_intr: device error - RDMC")); 4656f45ec7bSml29623 (void) nxge_rxdma_handle_sys_errors(nxgep); 4666f45ec7bSml29623 } else if (estat.bits.ldw.txc) { 4676f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4686f45ec7bSml29623 "==> nxge_syserr_intr: device error - TXC")); 4696f45ec7bSml29623 (void) nxge_txc_handle_sys_errors(nxgep); 4706f45ec7bSml29623 } else if ((nxgep->niu_type != N2_NIU) && estat.bits.ldw.peu) { 4716f45ec7bSml29623 /* PCI-E */ 4726f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4736f45ec7bSml29623 "==> nxge_syserr_intr: device error - PCI-E")); 4746f45ec7bSml29623 } else if (estat.bits.ldw.meta1) { 4756f45ec7bSml29623 /* META1 */ 4766f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4776f45ec7bSml29623 "==> nxge_syserr_intr: device error - META1")); 4786f45ec7bSml29623 } else if (estat.bits.ldw.meta2) { 4796f45ec7bSml29623 /* META2 */ 4806f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4816f45ec7bSml29623 "==> nxge_syserr_intr: device error - META2")); 4826f45ec7bSml29623 } else if (estat.bits.ldw.fflp) { 4836f45ec7bSml29623 /* FFLP */ 4846f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4856f45ec7bSml29623 "==> nxge_syserr_intr: device error - FFLP")); 4866f45ec7bSml29623 (void) nxge_fflp_handle_sys_errors(nxgep); 4876f45ec7bSml29623 } 488ee5416c9Syc148097 48900161856Syc148097 /* 49000161856Syc148097 * nxge_check_xaui_xfg checks XAUI for all of the following 49100161856Syc148097 * portmodes, but checks XFP only if portmode == PORT_10G_FIBER. 49200161856Syc148097 */ 493ee5416c9Syc148097 if (nxgep->mac.portmode == PORT_10G_FIBER || 49400161856Syc148097 nxgep->mac.portmode == PORT_10G_COPPER || 49500161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 49600161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010) { 497ee5416c9Syc148097 if (nxge_check_xaui_xfp(nxgep) != NXGE_OK) { 498ee5416c9Syc148097 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 499ee5416c9Syc148097 "==> nxge_syserr_intr: device error - XAUI")); 500ee5416c9Syc148097 } 501ee5416c9Syc148097 } 502ee5416c9Syc148097 5036f45ec7bSml29623 serviced = DDI_INTR_CLAIMED; 5046f45ec7bSml29623 5056f45ec7bSml29623 if (ldgp != NULL && ldvp != NULL && ldgp->nldvs == 1 && 5066f45ec7bSml29623 !ldvp->use_timer) { 5076f45ec7bSml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 5086f45ec7bSml29623 B_TRUE, ldgp->ldg_timer); 5096f45ec7bSml29623 } 5106f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_syserr_intr")); 5116f45ec7bSml29623 return (serviced); 5126f45ec7bSml29623 } 5136f45ec7bSml29623 5146f45ec7bSml29623 /* ARGSUSED */ 5156f45ec7bSml29623 void 5166f45ec7bSml29623 nxge_intr_hw_enable(p_nxge_t nxgep) 5176f45ec7bSml29623 { 5186f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_enable")); 5196f45ec7bSml29623 (void) nxge_intr_mask_mgmt_set(nxgep, B_TRUE); 5206f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_enable")); 5216f45ec7bSml29623 } 5226f45ec7bSml29623 5236f45ec7bSml29623 /* ARGSUSED */ 5246f45ec7bSml29623 void 5256f45ec7bSml29623 nxge_intr_hw_disable(p_nxge_t nxgep) 5266f45ec7bSml29623 { 5276f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_disable")); 5286f45ec7bSml29623 (void) nxge_intr_mask_mgmt_set(nxgep, B_FALSE); 5296f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_disable")); 5306f45ec7bSml29623 } 5316f45ec7bSml29623 5326f45ec7bSml29623 /* ARGSUSED */ 5336f45ec7bSml29623 void 5346f45ec7bSml29623 nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count) 5356f45ec7bSml29623 { 5366f45ec7bSml29623 p_nxge_t nxgep = (p_nxge_t)arg; 5376f45ec7bSml29623 uint8_t channel; 5386f45ec7bSml29623 npi_handle_t handle; 5396f45ec7bSml29623 p_nxge_ldgv_t ldgvp; 5406f45ec7bSml29623 p_nxge_ldv_t ldvp; 5416f45ec7bSml29623 int i; 5426f45ec7bSml29623 5436f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_hw_blank")); 5446f45ec7bSml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 5456f45ec7bSml29623 5466f45ec7bSml29623 if ((ldgvp = nxgep->ldgvp) == NULL) { 5476f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, 5486f45ec7bSml29623 "<== nxge_rx_hw_blank (not enabled)")); 5496f45ec7bSml29623 return; 5506f45ec7bSml29623 } 5516f45ec7bSml29623 ldvp = nxgep->ldgvp->ldvp; 5526f45ec7bSml29623 if (ldvp == NULL) { 5536f45ec7bSml29623 return; 5546f45ec7bSml29623 } 5556f45ec7bSml29623 for (i = 0; i < ldgvp->nldvs; i++, ldvp++) { 5566f45ec7bSml29623 if (ldvp->is_rxdma) { 5576f45ec7bSml29623 channel = ldvp->channel; 5586f45ec7bSml29623 (void) npi_rxdma_cfg_rdc_rcr_threshold(handle, 5596f45ec7bSml29623 channel, count); 5606f45ec7bSml29623 (void) npi_rxdma_cfg_rdc_rcr_timeout(handle, 5616f45ec7bSml29623 channel, ticks); 5626f45ec7bSml29623 } 5636f45ec7bSml29623 } 5646f45ec7bSml29623 5656f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_hw_blank")); 5666f45ec7bSml29623 } 5676f45ec7bSml29623 5686f45ec7bSml29623 /* ARGSUSED */ 5696f45ec7bSml29623 void 5706f45ec7bSml29623 nxge_hw_stop(p_nxge_t nxgep) 5716f45ec7bSml29623 { 5726f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_stop")); 5736f45ec7bSml29623 5746f45ec7bSml29623 (void) nxge_tx_mac_disable(nxgep); 5756f45ec7bSml29623 (void) nxge_rx_mac_disable(nxgep); 5766f45ec7bSml29623 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 5776f45ec7bSml29623 (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 5786f45ec7bSml29623 5796f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_stop")); 5806f45ec7bSml29623 } 5816f45ec7bSml29623 5826f45ec7bSml29623 /* ARGSUSED */ 5836f45ec7bSml29623 void 5846f45ec7bSml29623 nxge_hw_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) 5856f45ec7bSml29623 { 5866f45ec7bSml29623 int cmd; 5876f45ec7bSml29623 5886f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_hw_ioctl")); 5896f45ec7bSml29623 5906f45ec7bSml29623 if (nxgep == NULL) { 5916f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 5926f45ec7bSml29623 return; 5936f45ec7bSml29623 } 5946f45ec7bSml29623 iocp->ioc_error = 0; 5956f45ec7bSml29623 cmd = iocp->ioc_cmd; 5966f45ec7bSml29623 5976f45ec7bSml29623 switch (cmd) { 5986f45ec7bSml29623 default: 5996f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 6006f45ec7bSml29623 return; 6016f45ec7bSml29623 6026f45ec7bSml29623 case NXGE_GET_MII: 6036f45ec7bSml29623 nxge_get_mii(nxgep, mp->b_cont); 6046f45ec7bSml29623 miocack(wq, mp, sizeof (uint16_t), 0); 6056f45ec7bSml29623 break; 6066f45ec7bSml29623 6076f45ec7bSml29623 case NXGE_PUT_MII: 6086f45ec7bSml29623 nxge_put_mii(nxgep, mp->b_cont); 6096f45ec7bSml29623 miocack(wq, mp, 0, 0); 6106f45ec7bSml29623 break; 6116f45ec7bSml29623 6126f45ec7bSml29623 case NXGE_GET64: 6136f45ec7bSml29623 nxge_get64(nxgep, mp->b_cont); 6146f45ec7bSml29623 miocack(wq, mp, sizeof (uint32_t), 0); 6156f45ec7bSml29623 break; 6166f45ec7bSml29623 6176f45ec7bSml29623 case NXGE_PUT64: 6186f45ec7bSml29623 nxge_put64(nxgep, mp->b_cont); 6196f45ec7bSml29623 miocack(wq, mp, 0, 0); 6206f45ec7bSml29623 break; 6216f45ec7bSml29623 6226f45ec7bSml29623 case NXGE_PUT_TCAM: 6236f45ec7bSml29623 nxge_put_tcam(nxgep, mp->b_cont); 6246f45ec7bSml29623 miocack(wq, mp, 0, 0); 6256f45ec7bSml29623 break; 6266f45ec7bSml29623 6276f45ec7bSml29623 case NXGE_GET_TCAM: 6286f45ec7bSml29623 nxge_get_tcam(nxgep, mp->b_cont); 6296f45ec7bSml29623 miocack(wq, mp, 0, 0); 6306f45ec7bSml29623 break; 6316f45ec7bSml29623 6326f45ec7bSml29623 case NXGE_TX_REGS_DUMP: 6336f45ec7bSml29623 nxge_txdma_regs_dump_channels(nxgep); 6346f45ec7bSml29623 miocack(wq, mp, 0, 0); 6356f45ec7bSml29623 break; 6366f45ec7bSml29623 case NXGE_RX_REGS_DUMP: 6376f45ec7bSml29623 nxge_rxdma_regs_dump_channels(nxgep); 6386f45ec7bSml29623 miocack(wq, mp, 0, 0); 6396f45ec7bSml29623 break; 6406f45ec7bSml29623 case NXGE_VIR_INT_REGS_DUMP: 6416f45ec7bSml29623 case NXGE_INT_REGS_DUMP: 6426f45ec7bSml29623 nxge_virint_regs_dump(nxgep); 6436f45ec7bSml29623 miocack(wq, mp, 0, 0); 6446f45ec7bSml29623 break; 6456f45ec7bSml29623 case NXGE_RTRACE: 6466f45ec7bSml29623 nxge_rtrace_ioctl(nxgep, wq, mp, iocp); 6476f45ec7bSml29623 break; 6486f45ec7bSml29623 } 6496f45ec7bSml29623 } 6506f45ec7bSml29623 6516f45ec7bSml29623 /* ARGSUSED */ 6526f45ec7bSml29623 void 6536f45ec7bSml29623 nxge_loopback_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, 6546f45ec7bSml29623 struct iocblk *iocp) 6556f45ec7bSml29623 { 6566f45ec7bSml29623 p_lb_property_t lb_props; 6576f45ec7bSml29623 6586f45ec7bSml29623 size_t size; 6596f45ec7bSml29623 int i; 6606f45ec7bSml29623 6616f45ec7bSml29623 if (mp->b_cont == NULL) { 6626f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 6636f45ec7bSml29623 } 6646f45ec7bSml29623 switch (iocp->ioc_cmd) { 6656f45ec7bSml29623 case LB_GET_MODE: 6666f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_MODE command")); 6676f45ec7bSml29623 if (nxgep != NULL) { 6686f45ec7bSml29623 *(lb_info_sz_t *)mp->b_cont->b_rptr = 6696f45ec7bSml29623 nxgep->statsp->port_stats.lb_mode; 6706f45ec7bSml29623 miocack(wq, mp, sizeof (nxge_lb_t), 0); 671ee5416c9Syc148097 } else { 6726f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 673ee5416c9Syc148097 } 6746f45ec7bSml29623 break; 6756f45ec7bSml29623 case LB_SET_MODE: 6766f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_SET_LB_MODE command")); 6776f45ec7bSml29623 if (iocp->ioc_count != sizeof (uint32_t)) { 6786f45ec7bSml29623 miocack(wq, mp, 0, 0); 6796f45ec7bSml29623 break; 6806f45ec7bSml29623 } 6816f45ec7bSml29623 if ((nxgep != NULL) && nxge_set_lb(nxgep, wq, mp->b_cont)) { 6826f45ec7bSml29623 miocack(wq, mp, 0, 0); 6836f45ec7bSml29623 } else { 6846f45ec7bSml29623 miocnak(wq, mp, 0, EPROTO); 6856f45ec7bSml29623 } 6866f45ec7bSml29623 break; 6876f45ec7bSml29623 case LB_GET_INFO_SIZE: 6886f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "LB_GET_INFO_SIZE command")); 6896f45ec7bSml29623 if (nxgep != NULL) { 6906f45ec7bSml29623 size = sizeof (lb_normal); 6916f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 69200161856Syc148097 /* TN1010 does not support external loopback */ 69300161856Syc148097 if (nxgep->mac.portmode != PORT_1G_TN1010 && 69400161856Syc148097 nxgep->mac.portmode != PORT_10G_TN1010) { 6956f45ec7bSml29623 size += sizeof (lb_external10g); 69600161856Syc148097 } 6976f45ec7bSml29623 size += sizeof (lb_mac10g); 698936117e2Ssbehera /* Publish PHY loopback if PHY is present */ 699936117e2Ssbehera if (nxgep->mac.portmode == PORT_10G_COPPER || 70000161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 701936117e2Ssbehera nxgep->mac.portmode == PORT_10G_FIBER) 702936117e2Ssbehera size += sizeof (lb_phy10g); 7036f45ec7bSml29623 } 70400161856Syc148097 70500161856Syc148097 /* 70600161856Syc148097 * Even if cap_10gfdx is false, we still do 10G 70700161856Syc148097 * serdes loopback as a part of SunVTS xnetlbtest 70800161856Syc148097 * internal loopback test. 70900161856Syc148097 */ 710936117e2Ssbehera if (nxgep->mac.portmode == PORT_10G_FIBER || 711*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 71200161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 713936117e2Ssbehera nxgep->mac.portmode == PORT_10G_SERDES) 714936117e2Ssbehera size += sizeof (lb_serdes10g); 715936117e2Ssbehera 7166f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) { 71700161856Syc148097 /* TN1010 does not support external loopback */ 71800161856Syc148097 if (nxgep->mac.portmode != PORT_1G_TN1010 && 71900161856Syc148097 nxgep->mac.portmode != PORT_10G_TN1010) { 7206f45ec7bSml29623 size += sizeof (lb_external1000); 72100161856Syc148097 } 7226f45ec7bSml29623 size += sizeof (lb_mac1000); 7230cad6a5fSyc148097 if (nxgep->mac.portmode == PORT_1G_COPPER || 72400161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 7250cad6a5fSyc148097 nxgep->mac.portmode == 7260cad6a5fSyc148097 PORT_1G_RGMII_FIBER) 7276f45ec7bSml29623 size += sizeof (lb_phy1000); 7286f45ec7bSml29623 } 7296f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 7306f45ec7bSml29623 size += sizeof (lb_external100); 7316f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 7326f45ec7bSml29623 size += sizeof (lb_external10); 733936117e2Ssbehera if (nxgep->mac.portmode == PORT_1G_FIBER || 73400161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 735936117e2Ssbehera nxgep->mac.portmode == PORT_1G_SERDES) 7366f45ec7bSml29623 size += sizeof (lb_serdes1000); 7372e59129aSraghus 7386f45ec7bSml29623 *(lb_info_sz_t *)mp->b_cont->b_rptr = size; 7396f45ec7bSml29623 7406f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 7416f45ec7bSml29623 "NXGE_GET_LB_INFO command: size %d", size)); 7426f45ec7bSml29623 miocack(wq, mp, sizeof (lb_info_sz_t), 0); 7436f45ec7bSml29623 } else 7446f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 7456f45ec7bSml29623 break; 7466f45ec7bSml29623 7476f45ec7bSml29623 case LB_GET_INFO: 7486f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_INFO command")); 7496f45ec7bSml29623 if (nxgep != NULL) { 7506f45ec7bSml29623 size = sizeof (lb_normal); 7516f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 75200161856Syc148097 /* TN1010 does not support external loopback */ 75300161856Syc148097 if (nxgep->mac.portmode != PORT_1G_TN1010 && 75400161856Syc148097 nxgep->mac.portmode != PORT_10G_TN1010) { 7556f45ec7bSml29623 size += sizeof (lb_external10g); 75600161856Syc148097 } 7576f45ec7bSml29623 size += sizeof (lb_mac10g); 758936117e2Ssbehera /* Publish PHY loopback if PHY is present */ 759936117e2Ssbehera if (nxgep->mac.portmode == PORT_10G_COPPER || 76000161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 761936117e2Ssbehera nxgep->mac.portmode == PORT_10G_FIBER) 762936117e2Ssbehera size += sizeof (lb_phy10g); 7636f45ec7bSml29623 } 764936117e2Ssbehera if (nxgep->mac.portmode == PORT_10G_FIBER || 765*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 76600161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 767936117e2Ssbehera nxgep->mac.portmode == PORT_10G_SERDES) 768936117e2Ssbehera size += sizeof (lb_serdes10g); 769936117e2Ssbehera 7706f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) { 77100161856Syc148097 /* TN1010 does not support external loopback */ 77200161856Syc148097 if (nxgep->mac.portmode != PORT_1G_TN1010 && 77300161856Syc148097 nxgep->mac.portmode != PORT_10G_TN1010) { 7746f45ec7bSml29623 size += sizeof (lb_external1000); 77500161856Syc148097 } 7766f45ec7bSml29623 size += sizeof (lb_mac1000); 7770cad6a5fSyc148097 if (nxgep->mac.portmode == PORT_1G_COPPER || 77800161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 7790cad6a5fSyc148097 nxgep->mac.portmode == 7800cad6a5fSyc148097 PORT_1G_RGMII_FIBER) 7816f45ec7bSml29623 size += sizeof (lb_phy1000); 7826f45ec7bSml29623 } 7836f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 7846f45ec7bSml29623 size += sizeof (lb_external100); 78500161856Syc148097 7866f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 7876f45ec7bSml29623 size += sizeof (lb_external10); 78800161856Syc148097 789936117e2Ssbehera if (nxgep->mac.portmode == PORT_1G_FIBER || 79000161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 791936117e2Ssbehera nxgep->mac.portmode == PORT_1G_SERDES) 7926f45ec7bSml29623 size += sizeof (lb_serdes1000); 7936f45ec7bSml29623 7946f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 7956f45ec7bSml29623 "NXGE_GET_LB_INFO command: size %d", size)); 7966f45ec7bSml29623 if (size == iocp->ioc_count) { 7976f45ec7bSml29623 i = 0; 7986f45ec7bSml29623 lb_props = (p_lb_property_t)mp->b_cont->b_rptr; 7996f45ec7bSml29623 lb_props[i++] = lb_normal; 80000161856Syc148097 8016f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 8026f45ec7bSml29623 lb_props[i++] = lb_mac10g; 803936117e2Ssbehera if (nxgep->mac.portmode == 804936117e2Ssbehera PORT_10G_COPPER || 805936117e2Ssbehera nxgep->mac.portmode == 80600161856Syc148097 PORT_10G_TN1010 || 80700161856Syc148097 nxgep->mac.portmode == 80800161856Syc148097 PORT_10G_FIBER) { 8096f45ec7bSml29623 lb_props[i++] = lb_phy10g; 81000161856Syc148097 } 81100161856Syc148097 /* TN1010 does not support ext lb */ 81200161856Syc148097 if (nxgep->mac.portmode != 81300161856Syc148097 PORT_10G_TN1010 && 81400161856Syc148097 nxgep->mac.portmode != 81500161856Syc148097 PORT_1G_TN1010) { 8166f45ec7bSml29623 lb_props[i++] = lb_external10g; 8176f45ec7bSml29623 } 81800161856Syc148097 } 81900161856Syc148097 820936117e2Ssbehera if (nxgep->mac.portmode == PORT_10G_FIBER || 821*89282175SSantwona Behera nxgep->mac.portmode == PORT_10G_COPPER || 82200161856Syc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 823936117e2Ssbehera nxgep->mac.portmode == PORT_10G_SERDES) 824936117e2Ssbehera lb_props[i++] = lb_serdes10g; 825936117e2Ssbehera 82600161856Syc148097 if (nxgep->statsp->mac_stats.cap_1000fdx) { 82700161856Syc148097 /* TN1010 does not support ext lb */ 82800161856Syc148097 if (nxgep->mac.portmode != 82900161856Syc148097 PORT_10G_TN1010 && 83000161856Syc148097 nxgep->mac.portmode != 83100161856Syc148097 PORT_1G_TN1010) { 8326f45ec7bSml29623 lb_props[i++] = lb_external1000; 83300161856Syc148097 } 83400161856Syc148097 } 83500161856Syc148097 8366f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 8376f45ec7bSml29623 lb_props[i++] = lb_external100; 83800161856Syc148097 8396f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 8406f45ec7bSml29623 lb_props[i++] = lb_external10; 84100161856Syc148097 8426f45ec7bSml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) 8436f45ec7bSml29623 lb_props[i++] = lb_mac1000; 84400161856Syc148097 8450cad6a5fSyc148097 if (nxgep->mac.portmode == PORT_1G_COPPER || 84600161856Syc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 8470cad6a5fSyc148097 nxgep->mac.portmode == 8480cad6a5fSyc148097 PORT_1G_RGMII_FIBER) { 8496f45ec7bSml29623 if (nxgep->statsp->mac_stats. 8506f45ec7bSml29623 cap_1000fdx) 8516f45ec7bSml29623 lb_props[i++] = lb_phy1000; 8520cad6a5fSyc148097 } else if (nxgep->mac.portmode == 8530cad6a5fSyc148097 PORT_1G_FIBER || 8540cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 8550cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_SERDES) { 8566f45ec7bSml29623 lb_props[i++] = lb_serdes1000; 8572e59129aSraghus } 8586f45ec7bSml29623 miocack(wq, mp, size, 0); 8596f45ec7bSml29623 } else 8606f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 8616f45ec7bSml29623 } else { 8626f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 8636f45ec7bSml29623 cmn_err(CE_NOTE, "!nxge_hw_ioctl: invalid command 0x%x", 8646f45ec7bSml29623 iocp->ioc_cmd); 8656f45ec7bSml29623 } 8666f45ec7bSml29623 break; 8676f45ec7bSml29623 } 8686f45ec7bSml29623 } 8696f45ec7bSml29623 8706f45ec7bSml29623 /* 8716f45ec7bSml29623 * DMA channel interfaces to access various channel specific 8726f45ec7bSml29623 * hardware functions. 8736f45ec7bSml29623 */ 8746f45ec7bSml29623 /* ARGSUSED */ 8756f45ec7bSml29623 void 8766f45ec7bSml29623 nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle, void *reg_addrp, 8776f45ec7bSml29623 uint32_t reg_base, uint16_t channel, uint64_t reg_data) 8786f45ec7bSml29623 { 8796f45ec7bSml29623 uint64_t reg_offset; 8806f45ec7bSml29623 8816f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64")); 8826f45ec7bSml29623 8836f45ec7bSml29623 /* 8846f45ec7bSml29623 * Channel is assumed to be from 0 to the maximum DMA channel #. If we 8856f45ec7bSml29623 * use the virtual DMA CSR address space from the config space (in PCI 8866f45ec7bSml29623 * case), then the following code need to be use different offset 8876f45ec7bSml29623 * computation macro. 8886f45ec7bSml29623 */ 8896f45ec7bSml29623 reg_offset = reg_base + DMC_OFFSET(channel); 8906f45ec7bSml29623 NXGE_PIO_WRITE64(handle, reg_addrp, reg_offset, reg_data); 8916f45ec7bSml29623 8926f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64")); 8936f45ec7bSml29623 } 8946f45ec7bSml29623 8956f45ec7bSml29623 /* ARGSUSED */ 8966f45ec7bSml29623 uint64_t 8976f45ec7bSml29623 nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle, void *reg_addrp, 8986f45ec7bSml29623 uint32_t reg_base, uint16_t channel) 8996f45ec7bSml29623 { 9006f45ec7bSml29623 uint64_t reg_offset; 9016f45ec7bSml29623 9026f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64")); 9036f45ec7bSml29623 9046f45ec7bSml29623 /* 9056f45ec7bSml29623 * Channel is assumed to be from 0 to the maximum DMA channel #. If we 9066f45ec7bSml29623 * use the virtual DMA CSR address space from the config space (in PCI 9076f45ec7bSml29623 * case), then the following code need to be use different offset 9086f45ec7bSml29623 * computation macro. 9096f45ec7bSml29623 */ 9106f45ec7bSml29623 reg_offset = reg_base + DMC_OFFSET(channel); 9116f45ec7bSml29623 9126f45ec7bSml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64")); 9136f45ec7bSml29623 9146f45ec7bSml29623 return (NXGE_PIO_READ64(handle, reg_addrp, reg_offset)); 9156f45ec7bSml29623 } 9166f45ec7bSml29623 9176f45ec7bSml29623 /* ARGSUSED */ 9186f45ec7bSml29623 void 9196f45ec7bSml29623 nxge_get32(p_nxge_t nxgep, p_mblk_t mp) 9206f45ec7bSml29623 { 9216f45ec7bSml29623 nxge_os_acc_handle_t nxge_regh; 9226f45ec7bSml29623 9236f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32")); 9246f45ec7bSml29623 nxge_regh = nxgep->dev_regs->nxge_regh; 9256f45ec7bSml29623 9266f45ec7bSml29623 *(uint32_t *)mp->b_rptr = NXGE_PIO_READ32(nxge_regh, 9276f45ec7bSml29623 nxgep->dev_regs->nxge_regp, *(uint32_t *)mp->b_rptr); 9286f45ec7bSml29623 9296f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "value = 0x%08X", 9306f45ec7bSml29623 *(uint32_t *)mp->b_rptr)); 9316f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32")); 9326f45ec7bSml29623 } 9336f45ec7bSml29623 9346f45ec7bSml29623 /* ARGSUSED */ 9356f45ec7bSml29623 void 9366f45ec7bSml29623 nxge_put32(p_nxge_t nxgep, p_mblk_t mp) 9376f45ec7bSml29623 { 9386f45ec7bSml29623 nxge_os_acc_handle_t nxge_regh; 9396f45ec7bSml29623 uint32_t *buf; 9406f45ec7bSml29623 uint8_t *reg; 9416f45ec7bSml29623 9426f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32")); 9436f45ec7bSml29623 nxge_regh = nxgep->dev_regs->nxge_regh; 9446f45ec7bSml29623 9456f45ec7bSml29623 buf = (uint32_t *)mp->b_rptr; 9466f45ec7bSml29623 reg = (uint8_t *)(nxgep->dev_regs->nxge_regp) + buf[0]; 9476f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 9486f45ec7bSml29623 "reg = 0x%016llX index = 0x%08X value = 0x%08X", 9496f45ec7bSml29623 reg, buf[0], buf[1])); 9506f45ec7bSml29623 NXGE_PIO_WRITE32(nxge_regh, (uint32_t *)reg, 0, buf[1]); 9516f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32")); 9526f45ec7bSml29623 } 9536f45ec7bSml29623 9546f45ec7bSml29623 /*ARGSUSED*/ 9556f45ec7bSml29623 boolean_t 9566f45ec7bSml29623 nxge_set_lb(p_nxge_t nxgep, queue_t *wq, p_mblk_t mp) 9576f45ec7bSml29623 { 9586f45ec7bSml29623 boolean_t status = B_TRUE; 9596f45ec7bSml29623 uint32_t lb_mode; 9606f45ec7bSml29623 lb_property_t *lb_info; 9616f45ec7bSml29623 9626f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_set_lb")); 9636f45ec7bSml29623 lb_mode = nxgep->statsp->port_stats.lb_mode; 9646f45ec7bSml29623 if (lb_mode == *(uint32_t *)mp->b_rptr) { 9656f45ec7bSml29623 cmn_err(CE_NOTE, 9666f45ec7bSml29623 "!nxge%d: Loopback mode already set (lb_mode %d).\n", 9676f45ec7bSml29623 nxgep->instance, lb_mode); 9686f45ec7bSml29623 status = B_FALSE; 9696f45ec7bSml29623 goto nxge_set_lb_exit; 9706f45ec7bSml29623 } 9716f45ec7bSml29623 lb_mode = *(uint32_t *)mp->b_rptr; 9726f45ec7bSml29623 lb_info = NULL; 9736f45ec7bSml29623 if (lb_mode == lb_normal.value) 9746f45ec7bSml29623 lb_info = &lb_normal; 9756f45ec7bSml29623 else if ((lb_mode == lb_external10g.value) && 9766f45ec7bSml29623 (nxgep->statsp->mac_stats.cap_10gfdx)) 9776f45ec7bSml29623 lb_info = &lb_external10g; 9786f45ec7bSml29623 else if ((lb_mode == lb_external1000.value) && 9796f45ec7bSml29623 (nxgep->statsp->mac_stats.cap_1000fdx)) 9806f45ec7bSml29623 lb_info = &lb_external1000; 9816f45ec7bSml29623 else if ((lb_mode == lb_external100.value) && 9826f45ec7bSml29623 (nxgep->statsp->mac_stats.cap_100fdx)) 9836f45ec7bSml29623 lb_info = &lb_external100; 9846f45ec7bSml29623 else if ((lb_mode == lb_external10.value) && 9856f45ec7bSml29623 (nxgep->statsp->mac_stats.cap_10fdx)) 9866f45ec7bSml29623 lb_info = &lb_external10; 9876f45ec7bSml29623 else if ((lb_mode == lb_phy10g.value) && 9880cad6a5fSyc148097 (nxgep->mac.portmode == PORT_10G_COPPER || 9890cad6a5fSyc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 9900cad6a5fSyc148097 nxgep->mac.portmode == PORT_10G_FIBER)) 9916f45ec7bSml29623 lb_info = &lb_phy10g; 9926f45ec7bSml29623 else if ((lb_mode == lb_phy1000.value) && 9930cad6a5fSyc148097 (nxgep->mac.portmode == PORT_1G_COPPER || 9940cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 9950cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) 9966f45ec7bSml29623 lb_info = &lb_phy1000; 9976f45ec7bSml29623 else if ((lb_mode == lb_phy.value) && 9986f45ec7bSml29623 (nxgep->mac.portmode == PORT_1G_COPPER)) 9996f45ec7bSml29623 lb_info = &lb_phy; 10006f45ec7bSml29623 else if ((lb_mode == lb_serdes10g.value) && 10010cad6a5fSyc148097 (nxgep->mac.portmode == PORT_10G_FIBER || 10020cad6a5fSyc148097 nxgep->mac.portmode == PORT_10G_COPPER || 10030cad6a5fSyc148097 nxgep->mac.portmode == PORT_10G_TN1010 || 10040cad6a5fSyc148097 nxgep->mac.portmode == PORT_10G_SERDES)) 10056f45ec7bSml29623 lb_info = &lb_serdes10g; 10066f45ec7bSml29623 else if ((lb_mode == lb_serdes1000.value) && 10070cad6a5fSyc148097 (nxgep->mac.portmode == PORT_1G_FIBER || 10080cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_TN1010 || 10090cad6a5fSyc148097 nxgep->mac.portmode == PORT_1G_SERDES)) 10106f45ec7bSml29623 lb_info = &lb_serdes1000; 10116f45ec7bSml29623 else if (lb_mode == lb_mac10g.value) 10126f45ec7bSml29623 lb_info = &lb_mac10g; 10136f45ec7bSml29623 else if (lb_mode == lb_mac1000.value) 10146f45ec7bSml29623 lb_info = &lb_mac1000; 10156f45ec7bSml29623 else if (lb_mode == lb_mac.value) 10166f45ec7bSml29623 lb_info = &lb_mac; 10176f45ec7bSml29623 else { 10186f45ec7bSml29623 cmn_err(CE_NOTE, 10196f45ec7bSml29623 "!nxge%d: Loopback mode not supported(mode %d).\n", 10206f45ec7bSml29623 nxgep->instance, lb_mode); 10216f45ec7bSml29623 status = B_FALSE; 10226f45ec7bSml29623 goto nxge_set_lb_exit; 10236f45ec7bSml29623 } 10246f45ec7bSml29623 10256f45ec7bSml29623 if (lb_mode == nxge_lb_normal) { 10266f45ec7bSml29623 if (nxge_lb_dbg) { 10276f45ec7bSml29623 cmn_err(CE_NOTE, 10286f45ec7bSml29623 "!nxge%d: Returning to normal operation", 10296f45ec7bSml29623 nxgep->instance); 10306f45ec7bSml29623 } 1031321febdeSsbehera if (nxge_set_lb_normal(nxgep) != NXGE_OK) { 1032321febdeSsbehera status = B_FALSE; 1033321febdeSsbehera cmn_err(CE_NOTE, 1034321febdeSsbehera "!nxge%d: Failed to return to normal operation", 1035321febdeSsbehera nxgep->instance); 1036321febdeSsbehera } 10376f45ec7bSml29623 goto nxge_set_lb_exit; 10386f45ec7bSml29623 } 10396f45ec7bSml29623 nxgep->statsp->port_stats.lb_mode = lb_mode; 10406f45ec7bSml29623 10416f45ec7bSml29623 if (nxge_lb_dbg) 10426f45ec7bSml29623 cmn_err(CE_NOTE, 10436f45ec7bSml29623 "!nxge%d: Adapter now in %s loopback mode", 10446f45ec7bSml29623 nxgep->instance, lb_info->key); 10456f45ec7bSml29623 nxgep->param_arr[param_autoneg].value = 0; 10466f45ec7bSml29623 nxgep->param_arr[param_anar_10gfdx].value = 10476f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) || 10486f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) || 10496f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) || 10506f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g); 10516f45ec7bSml29623 nxgep->param_arr[param_anar_10ghdx].value = 0; 10526f45ec7bSml29623 nxgep->param_arr[param_anar_1000fdx].value = 10536f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) || 10546f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac1000) || 10556f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) || 10566f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000); 10576f45ec7bSml29623 nxgep->param_arr[param_anar_1000hdx].value = 0; 10586f45ec7bSml29623 nxgep->param_arr[param_anar_100fdx].value = 10596f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy) || 10606f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) || 10616f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100); 10626f45ec7bSml29623 nxgep->param_arr[param_anar_100hdx].value = 0; 10636f45ec7bSml29623 nxgep->param_arr[param_anar_10fdx].value = 10646f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) || 10656f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10); 10666f45ec7bSml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) { 10676f45ec7bSml29623 nxgep->param_arr[param_master_cfg_enable].value = 1; 10686f45ec7bSml29623 nxgep->param_arr[param_master_cfg_value].value = 1; 10696f45ec7bSml29623 } 10706f45ec7bSml29623 if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) || 10716f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) || 10726f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100) || 10736f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10) || 10746f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) || 10756f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) || 10766f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy)) { 10776f45ec7bSml29623 1078321febdeSsbehera if (nxge_link_monitor(nxgep, LINK_MONITOR_STOP) != NXGE_OK) 1079321febdeSsbehera goto nxge_set_lb_err; 1080321febdeSsbehera if (nxge_xcvr_find(nxgep) != NXGE_OK) 1081321febdeSsbehera goto nxge_set_lb_err; 1082321febdeSsbehera if (nxge_link_init(nxgep) != NXGE_OK) 1083321febdeSsbehera goto nxge_set_lb_err; 1084321febdeSsbehera if (nxge_link_monitor(nxgep, LINK_MONITOR_START) != NXGE_OK) 1085321febdeSsbehera goto nxge_set_lb_err; 10866f45ec7bSml29623 } 10876f45ec7bSml29623 if (lb_info->lb_type == internal) { 10886f45ec7bSml29623 if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) || 10896f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 10906f45ec7bSml29623 nxge_lb_phy10g) || 10916f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 10926f45ec7bSml29623 nxge_lb_serdes10g)) { 10936f45ec7bSml29623 nxgep->statsp->mac_stats.link_speed = 10000; 10946f45ec7bSml29623 } else if ((nxgep->statsp->port_stats.lb_mode 10956f45ec7bSml29623 == nxge_lb_mac1000) || 10966f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 10976f45ec7bSml29623 nxge_lb_phy1000) || 10986f45ec7bSml29623 (nxgep->statsp->port_stats.lb_mode == 10996f45ec7bSml29623 nxge_lb_serdes1000)) { 11006f45ec7bSml29623 nxgep->statsp->mac_stats.link_speed = 1000; 11016f45ec7bSml29623 } else { 11026f45ec7bSml29623 nxgep->statsp->mac_stats.link_speed = 100; 11036f45ec7bSml29623 } 11046f45ec7bSml29623 nxgep->statsp->mac_stats.link_duplex = 2; 11056f45ec7bSml29623 nxgep->statsp->mac_stats.link_up = 1; 11066f45ec7bSml29623 } 1107321febdeSsbehera if (nxge_global_reset(nxgep) != NXGE_OK) 1108321febdeSsbehera goto nxge_set_lb_err; 11096f45ec7bSml29623 11106f45ec7bSml29623 nxge_set_lb_exit: 11116f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 11126f45ec7bSml29623 "<== nxge_set_lb status = 0x%08x", status)); 11136f45ec7bSml29623 return (status); 1114321febdeSsbehera nxge_set_lb_err: 1115321febdeSsbehera status = B_FALSE; 1116321febdeSsbehera cmn_err(CE_NOTE, 1117321febdeSsbehera "!nxge%d: Failed to put adapter in %s loopback mode", 1118321febdeSsbehera nxgep->instance, lb_info->key); 1119321febdeSsbehera return (status); 11206f45ec7bSml29623 } 11216f45ec7bSml29623 112200161856Syc148097 /* Return to normal (no loopback) mode */ 11236f45ec7bSml29623 /* ARGSUSED */ 1124321febdeSsbehera nxge_status_t 11256f45ec7bSml29623 nxge_set_lb_normal(p_nxge_t nxgep) 11266f45ec7bSml29623 { 1127321febdeSsbehera nxge_status_t status = NXGE_OK; 1128321febdeSsbehera 11296f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_lb_normal")); 1130321febdeSsbehera 11316f45ec7bSml29623 nxgep->statsp->port_stats.lb_mode = nxge_lb_normal; 11326f45ec7bSml29623 nxgep->param_arr[param_autoneg].value = 11336f45ec7bSml29623 nxgep->param_arr[param_autoneg].old_value; 11346f45ec7bSml29623 nxgep->param_arr[param_anar_1000fdx].value = 11356f45ec7bSml29623 nxgep->param_arr[param_anar_1000fdx].old_value; 11366f45ec7bSml29623 nxgep->param_arr[param_anar_1000hdx].value = 11376f45ec7bSml29623 nxgep->param_arr[param_anar_1000hdx].old_value; 11386f45ec7bSml29623 nxgep->param_arr[param_anar_100fdx].value = 11396f45ec7bSml29623 nxgep->param_arr[param_anar_100fdx].old_value; 11406f45ec7bSml29623 nxgep->param_arr[param_anar_100hdx].value = 11416f45ec7bSml29623 nxgep->param_arr[param_anar_100hdx].old_value; 11426f45ec7bSml29623 nxgep->param_arr[param_anar_10fdx].value = 11436f45ec7bSml29623 nxgep->param_arr[param_anar_10fdx].old_value; 11446f45ec7bSml29623 nxgep->param_arr[param_master_cfg_enable].value = 11456f45ec7bSml29623 nxgep->param_arr[param_master_cfg_enable].old_value; 11466f45ec7bSml29623 nxgep->param_arr[param_master_cfg_value].value = 11476f45ec7bSml29623 nxgep->param_arr[param_master_cfg_value].old_value; 11486f45ec7bSml29623 1149321febdeSsbehera if ((status = nxge_global_reset(nxgep)) != NXGE_OK) 1150321febdeSsbehera return (status); 11516f45ec7bSml29623 1152321febdeSsbehera if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_STOP)) != NXGE_OK) 1153321febdeSsbehera return (status); 1154321febdeSsbehera if ((status = nxge_xcvr_find(nxgep)) != NXGE_OK) 1155321febdeSsbehera return (status); 1156321febdeSsbehera if ((status = nxge_link_init(nxgep)) != NXGE_OK) 1157321febdeSsbehera return (status); 1158321febdeSsbehera status = nxge_link_monitor(nxgep, LINK_MONITOR_START); 11596f45ec7bSml29623 11606f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_lb_normal")); 1161321febdeSsbehera 1162321febdeSsbehera return (status); 11636f45ec7bSml29623 } 11646f45ec7bSml29623 11656f45ec7bSml29623 /* ARGSUSED */ 11666f45ec7bSml29623 void 11676f45ec7bSml29623 nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp) 11686f45ec7bSml29623 { 11696f45ec7bSml29623 uint16_t reg; 11706f45ec7bSml29623 11716f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_get_mii")); 11726f45ec7bSml29623 11736f45ec7bSml29623 reg = *(uint16_t *)mp->b_rptr; 11746f45ec7bSml29623 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, reg, 11756f45ec7bSml29623 (uint16_t *)mp->b_rptr); 11766f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "reg = 0x%08X value = 0x%04X", 11776f45ec7bSml29623 reg, *(uint16_t *)mp->b_rptr)); 11786f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_get_mii")); 11796f45ec7bSml29623 } 11806f45ec7bSml29623 11816f45ec7bSml29623 /* ARGSUSED */ 11826f45ec7bSml29623 void 11836f45ec7bSml29623 nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp) 11846f45ec7bSml29623 { 11856f45ec7bSml29623 uint16_t *buf; 11866f45ec7bSml29623 uint8_t reg; 11876f45ec7bSml29623 11886f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_put_mii")); 11896f45ec7bSml29623 buf = (uint16_t *)mp->b_rptr; 11906f45ec7bSml29623 reg = (uint8_t)buf[0]; 11916f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 11926f45ec7bSml29623 "reg = 0x%08X index = 0x%08X value = 0x%08X", 11936f45ec7bSml29623 reg, buf[0], buf[1])); 11946f45ec7bSml29623 (void) nxge_mii_write(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 11956f45ec7bSml29623 reg, buf[1]); 11966f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_put_mii")); 11976f45ec7bSml29623 } 11986f45ec7bSml29623 11996f45ec7bSml29623 /* ARGSUSED */ 12006f45ec7bSml29623 void 12016f45ec7bSml29623 nxge_check_hw_state(p_nxge_t nxgep) 12026f45ec7bSml29623 { 12036f45ec7bSml29623 p_nxge_ldgv_t ldgvp; 12046f45ec7bSml29623 p_nxge_ldv_t t_ldvp; 12056f45ec7bSml29623 12066f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "==> nxge_check_hw_state")); 12076f45ec7bSml29623 12086f45ec7bSml29623 MUTEX_ENTER(nxgep->genlock); 12096f45ec7bSml29623 nxgep->nxge_timerid = 0; 12106f45ec7bSml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 12116f45ec7bSml29623 goto nxge_check_hw_state_exit; 12126f45ec7bSml29623 } 12136f45ec7bSml29623 nxge_check_tx_hang(nxgep); 12146f45ec7bSml29623 12156f45ec7bSml29623 ldgvp = nxgep->ldgvp; 12166f45ec7bSml29623 if (ldgvp == NULL || (ldgvp->ldvp_syserr == NULL)) { 12176f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: " 12186f45ec7bSml29623 "NULL ldgvp (interrupt not ready).")); 12196f45ec7bSml29623 goto nxge_check_hw_state_exit; 12206f45ec7bSml29623 } 12216f45ec7bSml29623 t_ldvp = ldgvp->ldvp_syserr; 12226f45ec7bSml29623 if (!t_ldvp->use_timer) { 12236f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: " 12246f45ec7bSml29623 "ldgvp $%p t_ldvp $%p use_timer flag %d", 12256f45ec7bSml29623 ldgvp, t_ldvp, t_ldvp->use_timer)); 12266f45ec7bSml29623 goto nxge_check_hw_state_exit; 12276f45ec7bSml29623 } 12286f45ec7bSml29623 if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 12296f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 12306f45ec7bSml29623 "port%d Bad register acc handle", nxgep->mac.portnum)); 12316f45ec7bSml29623 } 12326f45ec7bSml29623 (void) nxge_syserr_intr((void *) t_ldvp, (void *) nxgep); 12336f45ec7bSml29623 12346f45ec7bSml29623 nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state, 12356f45ec7bSml29623 NXGE_CHECK_TIMER); 12366f45ec7bSml29623 12376f45ec7bSml29623 nxge_check_hw_state_exit: 12386f45ec7bSml29623 MUTEX_EXIT(nxgep->genlock); 12396f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state")); 12406f45ec7bSml29623 } 12416f45ec7bSml29623 12426f45ec7bSml29623 /*ARGSUSED*/ 12436f45ec7bSml29623 static void 12446f45ec7bSml29623 nxge_rtrace_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, 12456f45ec7bSml29623 struct iocblk *iocp) 12466f45ec7bSml29623 { 12476f45ec7bSml29623 ssize_t size; 12486f45ec7bSml29623 rtrace_t *rtp; 12496f45ec7bSml29623 mblk_t *nmp; 12506f45ec7bSml29623 uint32_t i, j; 12516f45ec7bSml29623 uint32_t start_blk; 12526f45ec7bSml29623 uint32_t base_entry; 12536f45ec7bSml29623 uint32_t num_entries; 12546f45ec7bSml29623 12556f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_rtrace_ioctl")); 12566f45ec7bSml29623 12576f45ec7bSml29623 size = 1024; 12586f45ec7bSml29623 if (mp->b_cont == NULL || MBLKL(mp->b_cont) < size) { 12596f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, 12606f45ec7bSml29623 "malformed M_IOCTL MBLKL = %d size = %d", 12616f45ec7bSml29623 MBLKL(mp->b_cont), size)); 12626f45ec7bSml29623 miocnak(wq, mp, 0, EINVAL); 12636f45ec7bSml29623 return; 12646f45ec7bSml29623 } 12656f45ec7bSml29623 nmp = mp->b_cont; 12666f45ec7bSml29623 rtp = (rtrace_t *)nmp->b_rptr; 12676f45ec7bSml29623 start_blk = rtp->next_idx; 12686f45ec7bSml29623 num_entries = rtp->last_idx; 12696f45ec7bSml29623 base_entry = start_blk * MAX_RTRACE_IOC_ENTRIES; 12706f45ec7bSml29623 12716f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "start_blk = %d\n", start_blk)); 12726f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "num_entries = %d\n", num_entries)); 12736f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "base_entry = %d\n", base_entry)); 12746f45ec7bSml29623 12756f45ec7bSml29623 rtp->next_idx = npi_rtracebuf.next_idx; 12766f45ec7bSml29623 rtp->last_idx = npi_rtracebuf.last_idx; 12776f45ec7bSml29623 rtp->wrapped = npi_rtracebuf.wrapped; 12786f45ec7bSml29623 for (i = 0, j = base_entry; i < num_entries; i++, j++) { 12796f45ec7bSml29623 rtp->buf[i].ctl_addr = npi_rtracebuf.buf[j].ctl_addr; 12806f45ec7bSml29623 rtp->buf[i].val_l32 = npi_rtracebuf.buf[j].val_l32; 12816f45ec7bSml29623 rtp->buf[i].val_h32 = npi_rtracebuf.buf[j].val_h32; 12826f45ec7bSml29623 } 12836f45ec7bSml29623 12846f45ec7bSml29623 nmp->b_wptr = nmp->b_rptr + size; 12856f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_rtrace_ioctl")); 12866f45ec7bSml29623 miocack(wq, mp, (int)size, 0); 12876f45ec7bSml29623 } 1288