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
nxge_global_reset(p_nxge_t nxgep)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
nxge_hw_id_init(p_nxge_t nxgep)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
nxge_hw_init_niu_common(p_nxge_t nxgep)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
nxge_intr(void * arg1,void * arg2)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
nxge_check_xaui_xfp(p_nxge_t nxgep)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
nxge_syserr_intr(void * arg1,void * arg2)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
nxge_intr_hw_enable(p_nxge_t nxgep)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
nxge_intr_hw_disable(p_nxge_t nxgep)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
nxge_rx_hw_blank(void * arg,time_t ticks,uint_t count)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
nxge_hw_stop(p_nxge_t nxgep)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
nxge_hw_ioctl(p_nxge_t nxgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)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
nxge_loopback_ioctl(p_nxge_t nxgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)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
nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle,void * reg_addrp,uint32_t reg_base,uint16_t channel,uint64_t reg_data)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
nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle,void * reg_addrp,uint32_t reg_base,uint16_t channel)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
nxge_get32(p_nxge_t nxgep,p_mblk_t mp)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
nxge_put32(p_nxge_t nxgep,p_mblk_t mp)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
nxge_set_lb(p_nxge_t nxgep,queue_t * wq,p_mblk_t mp)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
nxge_set_lb_normal(p_nxge_t nxgep)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
nxge_get_mii(p_nxge_t nxgep,p_mblk_t mp)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
nxge_put_mii(p_nxge_t nxgep,p_mblk_t mp)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
nxge_check_hw_state(p_nxge_t nxgep)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
nxge_rtrace_ioctl(p_nxge_t nxgep,queue_t * wq,mblk_t * mp,struct iocblk * iocp)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