1*3859Sml29623 /* 2*3859Sml29623 * CDDL HEADER START 3*3859Sml29623 * 4*3859Sml29623 * The contents of this file are subject to the terms of the 5*3859Sml29623 * Common Development and Distribution License (the "License"). 6*3859Sml29623 * You may not use this file except in compliance with the License. 7*3859Sml29623 * 8*3859Sml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3859Sml29623 * or http://www.opensolaris.org/os/licensing. 10*3859Sml29623 * See the License for the specific language governing permissions 11*3859Sml29623 * and limitations under the License. 12*3859Sml29623 * 13*3859Sml29623 * When distributing Covered Code, include this CDDL HEADER in each 14*3859Sml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3859Sml29623 * If applicable, add the following below this CDDL HEADER, with the 16*3859Sml29623 * fields enclosed by brackets "[]" replaced with your own identifying 17*3859Sml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 18*3859Sml29623 * 19*3859Sml29623 * CDDL HEADER END 20*3859Sml29623 */ 21*3859Sml29623 /* 22*3859Sml29623 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*3859Sml29623 * Use is subject to license terms. 24*3859Sml29623 */ 25*3859Sml29623 26*3859Sml29623 #pragma ident "%Z%%M% %I% %E% SMI" 27*3859Sml29623 28*3859Sml29623 #include <sys/nxge/nxge_impl.h> 29*3859Sml29623 30*3859Sml29623 /* 31*3859Sml29623 * Tunable Receive Completion Ring Configuration B parameters. 32*3859Sml29623 */ 33*3859Sml29623 uint16_t nxge_rx_pkt_thres; /* 16 bits */ 34*3859Sml29623 uint8_t nxge_rx_pkt_timeout; /* 6 bits based on DMA clock divider */ 35*3859Sml29623 36*3859Sml29623 lb_property_t lb_normal = {normal, "normal", nxge_lb_normal}; 37*3859Sml29623 lb_property_t lb_external10g = {external, "external10g", nxge_lb_ext10g}; 38*3859Sml29623 lb_property_t lb_external1000 = {external, "external1000", nxge_lb_ext1000}; 39*3859Sml29623 lb_property_t lb_external100 = {external, "external100", nxge_lb_ext100}; 40*3859Sml29623 lb_property_t lb_external10 = {external, "external10", nxge_lb_ext10}; 41*3859Sml29623 lb_property_t lb_phy10g = {internal, "phy10g", nxge_lb_phy10g}; 42*3859Sml29623 lb_property_t lb_phy1000 = {internal, "phy1000", nxge_lb_phy1000}; 43*3859Sml29623 lb_property_t lb_phy = {internal, "phy", nxge_lb_phy}; 44*3859Sml29623 lb_property_t lb_serdes10g = {internal, "serdes10g", nxge_lb_serdes10g}; 45*3859Sml29623 lb_property_t lb_serdes1000 = {internal, "serdes", nxge_lb_serdes1000}; 46*3859Sml29623 lb_property_t lb_mac10g = {internal, "mac10g", nxge_lb_mac10g}; 47*3859Sml29623 lb_property_t lb_mac1000 = {internal, "mac1000", nxge_lb_mac1000}; 48*3859Sml29623 lb_property_t lb_mac = {internal, "mac10/100", nxge_lb_mac}; 49*3859Sml29623 50*3859Sml29623 uint32_t nxge_lb_dbg = 1; 51*3859Sml29623 void nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp); 52*3859Sml29623 void nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp); 53*3859Sml29623 54*3859Sml29623 extern uint32_t nxge_rx_mode; 55*3859Sml29623 extern uint32_t nxge_jumbo_mtu; 56*3859Sml29623 extern boolean_t nxge_jumbo_enable; 57*3859Sml29623 58*3859Sml29623 static void 59*3859Sml29623 nxge_rtrace_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *); 60*3859Sml29623 61*3859Sml29623 /* ARGSUSED */ 62*3859Sml29623 void 63*3859Sml29623 nxge_global_reset(p_nxge_t nxgep) 64*3859Sml29623 { 65*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_global_reset")); 66*3859Sml29623 67*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 68*3859Sml29623 (void) nxge_intr_hw_disable(nxgep); 69*3859Sml29623 70*3859Sml29623 if ((nxgep->suspended) || 71*3859Sml29623 ((nxgep->statsp->port_stats.lb_mode == 72*3859Sml29623 nxge_lb_phy1000) || 73*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 74*3859Sml29623 nxge_lb_phy10g) || 75*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 76*3859Sml29623 nxge_lb_serdes1000) || 77*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 78*3859Sml29623 nxge_lb_serdes10g))) { 79*3859Sml29623 (void) nxge_link_init(nxgep); 80*3859Sml29623 } 81*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 82*3859Sml29623 (void) nxge_mac_init(nxgep); 83*3859Sml29623 (void) nxge_intr_hw_enable(nxgep); 84*3859Sml29623 85*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_global_reset")); 86*3859Sml29623 } 87*3859Sml29623 88*3859Sml29623 /* ARGSUSED */ 89*3859Sml29623 void 90*3859Sml29623 nxge_hw_id_init(p_nxge_t nxgep) 91*3859Sml29623 { 92*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_id_init")); 93*3859Sml29623 /* 94*3859Sml29623 * Set up initial hardware parameters required such as mac mtu size. 95*3859Sml29623 */ 96*3859Sml29623 nxgep->mac.is_jumbo = B_FALSE; 97*3859Sml29623 nxgep->mac.maxframesize = NXGE_MTU_DEFAULT_MAX; /* 1522 */ 98*3859Sml29623 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 99*3859Sml29623 nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu; 100*3859Sml29623 nxgep->mac.is_jumbo = B_TRUE; 101*3859Sml29623 } 102*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 103*3859Sml29623 "==> nxge_hw_id_init: maxframesize %d", 104*3859Sml29623 nxgep->mac.maxframesize)); 105*3859Sml29623 106*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init")); 107*3859Sml29623 } 108*3859Sml29623 109*3859Sml29623 /* ARGSUSED */ 110*3859Sml29623 void 111*3859Sml29623 nxge_hw_init_niu_common(p_nxge_t nxgep) 112*3859Sml29623 { 113*3859Sml29623 p_nxge_hw_list_t hw_p; 114*3859Sml29623 115*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_init_niu_common")); 116*3859Sml29623 117*3859Sml29623 if ((hw_p = nxgep->nxge_hw_p) == NULL) { 118*3859Sml29623 return; 119*3859Sml29623 } 120*3859Sml29623 MUTEX_ENTER(&hw_p->nxge_cfg_lock); 121*3859Sml29623 if (hw_p->flags & COMMON_INIT_DONE) { 122*3859Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, 123*3859Sml29623 "nxge_hw_init_niu_common" 124*3859Sml29623 " already done for dip $%p function %d exiting", 125*3859Sml29623 hw_p->parent_devp, nxgep->function_num)); 126*3859Sml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 127*3859Sml29623 return; 128*3859Sml29623 } 129*3859Sml29623 130*3859Sml29623 hw_p->flags = COMMON_INIT_START; 131*3859Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common" 132*3859Sml29623 " Started for device id %x with function %d", 133*3859Sml29623 hw_p->parent_devp, nxgep->function_num)); 134*3859Sml29623 135*3859Sml29623 /* per neptune common block init */ 136*3859Sml29623 (void) nxge_fflp_hw_reset(nxgep); 137*3859Sml29623 138*3859Sml29623 hw_p->flags = COMMON_INIT_DONE; 139*3859Sml29623 MUTEX_EXIT(&hw_p->nxge_cfg_lock); 140*3859Sml29623 141*3859Sml29623 NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common" 142*3859Sml29623 " Done for device id %x with function %d", 143*3859Sml29623 hw_p->parent_devp, nxgep->function_num)); 144*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_init_niu_common")); 145*3859Sml29623 } 146*3859Sml29623 147*3859Sml29623 /* ARGSUSED */ 148*3859Sml29623 uint_t 149*3859Sml29623 nxge_intr(void *arg1, void *arg2) 150*3859Sml29623 { 151*3859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 152*3859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 153*3859Sml29623 uint_t serviced = DDI_INTR_UNCLAIMED; 154*3859Sml29623 uint8_t ldv; 155*3859Sml29623 npi_handle_t handle; 156*3859Sml29623 p_nxge_ldgv_t ldgvp; 157*3859Sml29623 p_nxge_ldg_t ldgp, t_ldgp; 158*3859Sml29623 p_nxge_ldv_t t_ldvp; 159*3859Sml29623 uint64_t vector0 = 0, vector1 = 0, vector2 = 0; 160*3859Sml29623 int i, j, nldvs, nintrs = 1; 161*3859Sml29623 npi_status_t rs = NPI_SUCCESS; 162*3859Sml29623 163*3859Sml29623 /* DDI interface returns second arg as NULL (n2 niumx driver) !!! */ 164*3859Sml29623 if (arg2 == NULL || (void *) ldvp->nxgep != arg2) { 165*3859Sml29623 nxgep = ldvp->nxgep; 166*3859Sml29623 } 167*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr")); 168*3859Sml29623 169*3859Sml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 170*3859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, 171*3859Sml29623 "<== nxge_intr: not initialized 0x%x", serviced)); 172*3859Sml29623 return (serviced); 173*3859Sml29623 } 174*3859Sml29623 175*3859Sml29623 ldgvp = nxgep->ldgvp; 176*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: ldgvp $%p", ldgvp)); 177*3859Sml29623 if (ldvp == NULL && ldgvp) { 178*3859Sml29623 t_ldvp = ldvp = ldgvp->ldvp; 179*3859Sml29623 } 180*3859Sml29623 if (ldvp) { 181*3859Sml29623 ldgp = t_ldgp = ldvp->ldgp; 182*3859Sml29623 } 183*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 184*3859Sml29623 "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp)); 185*3859Sml29623 if (ldgvp == NULL || ldvp == NULL || ldgp == NULL) { 186*3859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "==> nxge_intr: " 187*3859Sml29623 "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp)); 188*3859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_intr: not ready")); 189*3859Sml29623 return (DDI_INTR_UNCLAIMED); 190*3859Sml29623 } 191*3859Sml29623 /* 192*3859Sml29623 * This interrupt handler will have to go through all the logical 193*3859Sml29623 * devices to find out which logical device interrupts us and then call 194*3859Sml29623 * its handler to process the events. 195*3859Sml29623 */ 196*3859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 197*3859Sml29623 t_ldgp = ldgp; 198*3859Sml29623 t_ldvp = ldgp->ldvp; 199*3859Sml29623 200*3859Sml29623 nldvs = ldgp->nldvs; 201*3859Sml29623 202*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: #ldvs %d #intrs %d", 203*3859Sml29623 nldvs, ldgvp->ldg_intrs)); 204*3859Sml29623 205*3859Sml29623 serviced = DDI_INTR_CLAIMED; 206*3859Sml29623 for (i = 0; i < nintrs; i++, t_ldgp++) { 207*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr(%d): #ldvs %d " 208*3859Sml29623 " #intrs %d", i, nldvs, nintrs)); 209*3859Sml29623 /* Get this group's flag bits. */ 210*3859Sml29623 t_ldgp->interrupted = B_FALSE; 211*3859Sml29623 rs = npi_ldsv_ldfs_get(handle, t_ldgp->ldg, 212*3859Sml29623 &vector0, &vector1, &vector2); 213*3859Sml29623 if (rs) { 214*3859Sml29623 continue; 215*3859Sml29623 } 216*3859Sml29623 if (!vector0 && !vector1 && !vector2) { 217*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 218*3859Sml29623 "no interrupts on group %d", t_ldgp->ldg)); 219*3859Sml29623 continue; 220*3859Sml29623 } 221*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: " 222*3859Sml29623 "vector0 0x%llx vector1 0x%llx vector2 0x%llx", 223*3859Sml29623 vector0, vector1, vector2)); 224*3859Sml29623 t_ldgp->interrupted = B_TRUE; 225*3859Sml29623 nldvs = t_ldgp->nldvs; 226*3859Sml29623 for (j = 0; j < nldvs; j++, t_ldvp++) { 227*3859Sml29623 /* 228*3859Sml29623 * Call device's handler if flag bits are on. 229*3859Sml29623 */ 230*3859Sml29623 ldv = t_ldvp->ldv; 231*3859Sml29623 if (((ldv < NXGE_MAC_LD_START) && 232*3859Sml29623 (LDV_ON(ldv, vector0) | 233*3859Sml29623 (LDV_ON(ldv, vector1)))) || 234*3859Sml29623 (ldv >= NXGE_MAC_LD_START && 235*3859Sml29623 ((LDV2_ON_1(ldv, vector2)) || 236*3859Sml29623 (LDV2_ON_2(ldv, vector2))))) { 237*3859Sml29623 (void) (t_ldvp->ldv_intr_handler)( 238*3859Sml29623 (caddr_t)t_ldvp, arg2); 239*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, 240*3859Sml29623 "==> nxge_intr: " 241*3859Sml29623 "calling device %d #ldvs %d #intrs %d", 242*3859Sml29623 j, nldvs, nintrs)); 243*3859Sml29623 } 244*3859Sml29623 } 245*3859Sml29623 } 246*3859Sml29623 247*3859Sml29623 t_ldgp = ldgp; 248*3859Sml29623 for (i = 0; i < nintrs; i++, t_ldgp++) { 249*3859Sml29623 /* rearm group interrupts */ 250*3859Sml29623 if (t_ldgp->interrupted) { 251*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: arm " 252*3859Sml29623 "group %d", t_ldgp->ldg)); 253*3859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, t_ldgp->ldg, 254*3859Sml29623 t_ldgp->arm, t_ldgp->ldg_timer); 255*3859Sml29623 } 256*3859Sml29623 } 257*3859Sml29623 258*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr: serviced 0x%x", 259*3859Sml29623 serviced)); 260*3859Sml29623 return (serviced); 261*3859Sml29623 } 262*3859Sml29623 263*3859Sml29623 /* ARGSUSED */ 264*3859Sml29623 uint_t 265*3859Sml29623 nxge_syserr_intr(void *arg1, void *arg2) 266*3859Sml29623 { 267*3859Sml29623 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 268*3859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg2; 269*3859Sml29623 p_nxge_ldg_t ldgp = NULL; 270*3859Sml29623 npi_handle_t handle; 271*3859Sml29623 sys_err_stat_t estat; 272*3859Sml29623 uint_t serviced = DDI_INTR_UNCLAIMED; 273*3859Sml29623 274*3859Sml29623 if (arg1 == NULL && arg2 == NULL) { 275*3859Sml29623 return (serviced); 276*3859Sml29623 } 277*3859Sml29623 if (arg2 == NULL || ((ldvp != NULL && (void *) ldvp->nxgep != arg2))) { 278*3859Sml29623 if (ldvp != NULL) { 279*3859Sml29623 nxgep = ldvp->nxgep; 280*3859Sml29623 } 281*3859Sml29623 } 282*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, 283*3859Sml29623 "==> nxge_syserr_intr: arg2 $%p arg1 $%p", nxgep, ldvp)); 284*3859Sml29623 if (ldvp != NULL && ldvp->use_timer == B_FALSE) { 285*3859Sml29623 ldgp = ldvp->ldgp; 286*3859Sml29623 if (ldgp == NULL) { 287*3859Sml29623 NXGE_ERROR_MSG((nxgep, SYSERR_CTL, 288*3859Sml29623 "<== nxge_syserrintr(no logical group): " 289*3859Sml29623 "arg2 $%p arg1 $%p", nxgep, ldvp)); 290*3859Sml29623 return (DDI_INTR_UNCLAIMED); 291*3859Sml29623 } 292*3859Sml29623 /* 293*3859Sml29623 * Get the logical device state if the function uses interrupt. 294*3859Sml29623 */ 295*3859Sml29623 } 296*3859Sml29623 297*3859Sml29623 /* This interrupt handler is for system error interrupts. */ 298*3859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 299*3859Sml29623 estat.value = 0; 300*3859Sml29623 (void) npi_fzc_sys_err_stat_get(handle, &estat); 301*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, 302*3859Sml29623 "==> nxge_syserr_intr: device error 0x%016llx", estat.value)); 303*3859Sml29623 304*3859Sml29623 if (estat.bits.ldw.smx) { 305*3859Sml29623 /* SMX */ 306*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 307*3859Sml29623 "==> nxge_syserr_intr: device error - SMX")); 308*3859Sml29623 } else if (estat.bits.ldw.mac) { 309*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 310*3859Sml29623 "==> nxge_syserr_intr: device error - MAC")); 311*3859Sml29623 /* 312*3859Sml29623 * There is nothing to be done here. All MAC errors go to per 313*3859Sml29623 * MAC port interrupt. MIF interrupt is the only MAC sub-block 314*3859Sml29623 * that can generate status here. MIF status reported will be 315*3859Sml29623 * ignored here. It is checked by per port timer instead. 316*3859Sml29623 */ 317*3859Sml29623 } else if (estat.bits.ldw.ipp) { 318*3859Sml29623 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL, 319*3859Sml29623 "==> nxge_syserr_intr: device error - IPP")); 320*3859Sml29623 (void) nxge_ipp_handle_sys_errors(nxgep); 321*3859Sml29623 } else if (estat.bits.ldw.zcp) { 322*3859Sml29623 /* ZCP */ 323*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 324*3859Sml29623 "==> nxge_syserr_intr: device error - ZCP")); 325*3859Sml29623 (void) nxge_zcp_handle_sys_errors(nxgep); 326*3859Sml29623 } else if (estat.bits.ldw.tdmc) { 327*3859Sml29623 /* TDMC */ 328*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 329*3859Sml29623 "==> nxge_syserr_intr: device error - TDMC")); 330*3859Sml29623 /* 331*3859Sml29623 * There is no TDMC system errors defined in the PRM. All TDMC 332*3859Sml29623 * channel specific errors are reported on a per channel basis. 333*3859Sml29623 */ 334*3859Sml29623 } else if (estat.bits.ldw.rdmc) { 335*3859Sml29623 /* RDMC */ 336*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 337*3859Sml29623 "==> nxge_syserr_intr: device error - RDMC")); 338*3859Sml29623 (void) nxge_rxdma_handle_sys_errors(nxgep); 339*3859Sml29623 } else if (estat.bits.ldw.txc) { 340*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 341*3859Sml29623 "==> nxge_syserr_intr: device error - TXC")); 342*3859Sml29623 (void) nxge_txc_handle_sys_errors(nxgep); 343*3859Sml29623 } else if ((nxgep->niu_type != N2_NIU) && estat.bits.ldw.peu) { 344*3859Sml29623 /* PCI-E */ 345*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 346*3859Sml29623 "==> nxge_syserr_intr: device error - PCI-E")); 347*3859Sml29623 } else if (estat.bits.ldw.meta1) { 348*3859Sml29623 /* META1 */ 349*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 350*3859Sml29623 "==> nxge_syserr_intr: device error - META1")); 351*3859Sml29623 } else if (estat.bits.ldw.meta2) { 352*3859Sml29623 /* META2 */ 353*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 354*3859Sml29623 "==> nxge_syserr_intr: device error - META2")); 355*3859Sml29623 } else if (estat.bits.ldw.fflp) { 356*3859Sml29623 /* FFLP */ 357*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 358*3859Sml29623 "==> nxge_syserr_intr: device error - FFLP")); 359*3859Sml29623 (void) nxge_fflp_handle_sys_errors(nxgep); 360*3859Sml29623 } 361*3859Sml29623 serviced = DDI_INTR_CLAIMED; 362*3859Sml29623 363*3859Sml29623 if (ldgp != NULL && ldvp != NULL && ldgp->nldvs == 1 && 364*3859Sml29623 !ldvp->use_timer) { 365*3859Sml29623 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 366*3859Sml29623 B_TRUE, ldgp->ldg_timer); 367*3859Sml29623 } 368*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_syserr_intr")); 369*3859Sml29623 return (serviced); 370*3859Sml29623 } 371*3859Sml29623 372*3859Sml29623 /* ARGSUSED */ 373*3859Sml29623 void 374*3859Sml29623 nxge_intr_hw_enable(p_nxge_t nxgep) 375*3859Sml29623 { 376*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_enable")); 377*3859Sml29623 (void) nxge_intr_mask_mgmt_set(nxgep, B_TRUE); 378*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_enable")); 379*3859Sml29623 } 380*3859Sml29623 381*3859Sml29623 /* ARGSUSED */ 382*3859Sml29623 void 383*3859Sml29623 nxge_intr_hw_disable(p_nxge_t nxgep) 384*3859Sml29623 { 385*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_disable")); 386*3859Sml29623 (void) nxge_intr_mask_mgmt_set(nxgep, B_FALSE); 387*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_disable")); 388*3859Sml29623 } 389*3859Sml29623 390*3859Sml29623 /* ARGSUSED */ 391*3859Sml29623 void 392*3859Sml29623 nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count) 393*3859Sml29623 { 394*3859Sml29623 p_nxge_t nxgep = (p_nxge_t)arg; 395*3859Sml29623 uint8_t channel; 396*3859Sml29623 npi_handle_t handle; 397*3859Sml29623 p_nxge_ldgv_t ldgvp; 398*3859Sml29623 p_nxge_ldv_t ldvp; 399*3859Sml29623 int i; 400*3859Sml29623 401*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_hw_blank")); 402*3859Sml29623 handle = NXGE_DEV_NPI_HANDLE(nxgep); 403*3859Sml29623 404*3859Sml29623 if ((ldgvp = nxgep->ldgvp) == NULL) { 405*3859Sml29623 NXGE_ERROR_MSG((nxgep, INT_CTL, 406*3859Sml29623 "<== nxge_rx_hw_blank (not enabled)")); 407*3859Sml29623 return; 408*3859Sml29623 } 409*3859Sml29623 ldvp = nxgep->ldgvp->ldvp; 410*3859Sml29623 if (ldvp == NULL) { 411*3859Sml29623 return; 412*3859Sml29623 } 413*3859Sml29623 for (i = 0; i < ldgvp->nldvs; i++, ldvp++) { 414*3859Sml29623 if (ldvp->is_rxdma) { 415*3859Sml29623 channel = ldvp->channel; 416*3859Sml29623 (void) npi_rxdma_cfg_rdc_rcr_threshold(handle, 417*3859Sml29623 channel, count); 418*3859Sml29623 (void) npi_rxdma_cfg_rdc_rcr_timeout(handle, 419*3859Sml29623 channel, ticks); 420*3859Sml29623 } 421*3859Sml29623 } 422*3859Sml29623 423*3859Sml29623 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_hw_blank")); 424*3859Sml29623 } 425*3859Sml29623 426*3859Sml29623 /* ARGSUSED */ 427*3859Sml29623 void 428*3859Sml29623 nxge_hw_stop(p_nxge_t nxgep) 429*3859Sml29623 { 430*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_stop")); 431*3859Sml29623 432*3859Sml29623 (void) nxge_tx_mac_disable(nxgep); 433*3859Sml29623 (void) nxge_rx_mac_disable(nxgep); 434*3859Sml29623 (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP); 435*3859Sml29623 (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP); 436*3859Sml29623 437*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_stop")); 438*3859Sml29623 } 439*3859Sml29623 440*3859Sml29623 /* ARGSUSED */ 441*3859Sml29623 void 442*3859Sml29623 nxge_hw_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp) 443*3859Sml29623 { 444*3859Sml29623 int cmd; 445*3859Sml29623 446*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_hw_ioctl")); 447*3859Sml29623 448*3859Sml29623 if (nxgep == NULL) { 449*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 450*3859Sml29623 return; 451*3859Sml29623 } 452*3859Sml29623 iocp->ioc_error = 0; 453*3859Sml29623 cmd = iocp->ioc_cmd; 454*3859Sml29623 455*3859Sml29623 switch (cmd) { 456*3859Sml29623 default: 457*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 458*3859Sml29623 return; 459*3859Sml29623 460*3859Sml29623 case NXGE_GET_MII: 461*3859Sml29623 nxge_get_mii(nxgep, mp->b_cont); 462*3859Sml29623 miocack(wq, mp, sizeof (uint16_t), 0); 463*3859Sml29623 break; 464*3859Sml29623 465*3859Sml29623 case NXGE_PUT_MII: 466*3859Sml29623 nxge_put_mii(nxgep, mp->b_cont); 467*3859Sml29623 miocack(wq, mp, 0, 0); 468*3859Sml29623 break; 469*3859Sml29623 470*3859Sml29623 case NXGE_GET64: 471*3859Sml29623 nxge_get64(nxgep, mp->b_cont); 472*3859Sml29623 miocack(wq, mp, sizeof (uint32_t), 0); 473*3859Sml29623 break; 474*3859Sml29623 475*3859Sml29623 case NXGE_PUT64: 476*3859Sml29623 nxge_put64(nxgep, mp->b_cont); 477*3859Sml29623 miocack(wq, mp, 0, 0); 478*3859Sml29623 break; 479*3859Sml29623 480*3859Sml29623 case NXGE_PUT_TCAM: 481*3859Sml29623 nxge_put_tcam(nxgep, mp->b_cont); 482*3859Sml29623 miocack(wq, mp, 0, 0); 483*3859Sml29623 break; 484*3859Sml29623 485*3859Sml29623 case NXGE_GET_TCAM: 486*3859Sml29623 nxge_get_tcam(nxgep, mp->b_cont); 487*3859Sml29623 miocack(wq, mp, 0, 0); 488*3859Sml29623 break; 489*3859Sml29623 490*3859Sml29623 case NXGE_TX_REGS_DUMP: 491*3859Sml29623 nxge_txdma_regs_dump_channels(nxgep); 492*3859Sml29623 miocack(wq, mp, 0, 0); 493*3859Sml29623 break; 494*3859Sml29623 case NXGE_RX_REGS_DUMP: 495*3859Sml29623 nxge_rxdma_regs_dump_channels(nxgep); 496*3859Sml29623 miocack(wq, mp, 0, 0); 497*3859Sml29623 break; 498*3859Sml29623 case NXGE_VIR_INT_REGS_DUMP: 499*3859Sml29623 case NXGE_INT_REGS_DUMP: 500*3859Sml29623 nxge_virint_regs_dump(nxgep); 501*3859Sml29623 miocack(wq, mp, 0, 0); 502*3859Sml29623 break; 503*3859Sml29623 case NXGE_RTRACE: 504*3859Sml29623 nxge_rtrace_ioctl(nxgep, wq, mp, iocp); 505*3859Sml29623 break; 506*3859Sml29623 } 507*3859Sml29623 } 508*3859Sml29623 509*3859Sml29623 /* ARGSUSED */ 510*3859Sml29623 void 511*3859Sml29623 nxge_loopback_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, 512*3859Sml29623 struct iocblk *iocp) 513*3859Sml29623 { 514*3859Sml29623 p_lb_property_t lb_props; 515*3859Sml29623 516*3859Sml29623 size_t size; 517*3859Sml29623 int i; 518*3859Sml29623 519*3859Sml29623 if (mp->b_cont == NULL) { 520*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 521*3859Sml29623 } 522*3859Sml29623 switch (iocp->ioc_cmd) { 523*3859Sml29623 case LB_GET_MODE: 524*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_MODE command")); 525*3859Sml29623 if (nxgep != NULL) { 526*3859Sml29623 *(lb_info_sz_t *)mp->b_cont->b_rptr = 527*3859Sml29623 nxgep->statsp->port_stats.lb_mode; 528*3859Sml29623 miocack(wq, mp, sizeof (nxge_lb_t), 0); 529*3859Sml29623 } else 530*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 531*3859Sml29623 break; 532*3859Sml29623 case LB_SET_MODE: 533*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_SET_LB_MODE command")); 534*3859Sml29623 if (iocp->ioc_count != sizeof (uint32_t)) { 535*3859Sml29623 miocack(wq, mp, 0, 0); 536*3859Sml29623 break; 537*3859Sml29623 } 538*3859Sml29623 if ((nxgep != NULL) && nxge_set_lb(nxgep, wq, mp->b_cont)) { 539*3859Sml29623 miocack(wq, mp, 0, 0); 540*3859Sml29623 } else { 541*3859Sml29623 miocnak(wq, mp, 0, EPROTO); 542*3859Sml29623 } 543*3859Sml29623 break; 544*3859Sml29623 case LB_GET_INFO_SIZE: 545*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "LB_GET_INFO_SIZE command")); 546*3859Sml29623 if (nxgep != NULL) { 547*3859Sml29623 size = sizeof (lb_normal); 548*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 549*3859Sml29623 size += sizeof (lb_external10g); 550*3859Sml29623 size += sizeof (lb_phy10g); 551*3859Sml29623 size += sizeof (lb_serdes10g); 552*3859Sml29623 size += sizeof (lb_mac10g); 553*3859Sml29623 } 554*3859Sml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) { 555*3859Sml29623 size += sizeof (lb_external1000); 556*3859Sml29623 size += sizeof (lb_mac1000); 557*3859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) 558*3859Sml29623 size += sizeof (lb_phy1000); 559*3859Sml29623 } 560*3859Sml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 561*3859Sml29623 size += sizeof (lb_external100); 562*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 563*3859Sml29623 size += sizeof (lb_external10); 564*3859Sml29623 else if (nxgep->mac.portmode == PORT_1G_FIBER) 565*3859Sml29623 size += sizeof (lb_serdes1000); 566*3859Sml29623 *(lb_info_sz_t *)mp->b_cont->b_rptr = size; 567*3859Sml29623 568*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 569*3859Sml29623 "NXGE_GET_LB_INFO command: size %d", size)); 570*3859Sml29623 miocack(wq, mp, sizeof (lb_info_sz_t), 0); 571*3859Sml29623 } else 572*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 573*3859Sml29623 break; 574*3859Sml29623 575*3859Sml29623 case LB_GET_INFO: 576*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_INFO command")); 577*3859Sml29623 if (nxgep != NULL) { 578*3859Sml29623 size = sizeof (lb_normal); 579*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 580*3859Sml29623 size += sizeof (lb_external10g); 581*3859Sml29623 size += sizeof (lb_phy10g); 582*3859Sml29623 size += sizeof (lb_serdes10g); 583*3859Sml29623 size += sizeof (lb_mac10g); 584*3859Sml29623 } 585*3859Sml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) { 586*3859Sml29623 size += sizeof (lb_external1000); 587*3859Sml29623 size += sizeof (lb_mac1000); 588*3859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) 589*3859Sml29623 size += sizeof (lb_phy1000); 590*3859Sml29623 } 591*3859Sml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 592*3859Sml29623 size += sizeof (lb_external100); 593*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 594*3859Sml29623 size += sizeof (lb_external10); 595*3859Sml29623 else if (nxgep->mac.portmode == PORT_1G_FIBER) 596*3859Sml29623 size += sizeof (lb_serdes1000); 597*3859Sml29623 598*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 599*3859Sml29623 "NXGE_GET_LB_INFO command: size %d", size)); 600*3859Sml29623 if (size == iocp->ioc_count) { 601*3859Sml29623 i = 0; 602*3859Sml29623 lb_props = (p_lb_property_t)mp->b_cont->b_rptr; 603*3859Sml29623 lb_props[i++] = lb_normal; 604*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10gfdx) { 605*3859Sml29623 lb_props[i++] = lb_mac10g; 606*3859Sml29623 lb_props[i++] = lb_serdes10g; 607*3859Sml29623 lb_props[i++] = lb_phy10g; 608*3859Sml29623 lb_props[i++] = lb_external10g; 609*3859Sml29623 } 610*3859Sml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) 611*3859Sml29623 lb_props[i++] = lb_external1000; 612*3859Sml29623 if (nxgep->statsp->mac_stats.cap_100fdx) 613*3859Sml29623 lb_props[i++] = lb_external100; 614*3859Sml29623 if (nxgep->statsp->mac_stats.cap_10fdx) 615*3859Sml29623 lb_props[i++] = lb_external10; 616*3859Sml29623 if (nxgep->statsp->mac_stats.cap_1000fdx) 617*3859Sml29623 lb_props[i++] = lb_mac1000; 618*3859Sml29623 if (nxgep->mac.portmode == PORT_1G_COPPER) { 619*3859Sml29623 if (nxgep->statsp->mac_stats. 620*3859Sml29623 cap_1000fdx) 621*3859Sml29623 lb_props[i++] = lb_phy1000; 622*3859Sml29623 } else if (nxgep->mac.portmode == 623*3859Sml29623 PORT_1G_FIBER) 624*3859Sml29623 lb_props[i++] = lb_serdes1000; 625*3859Sml29623 miocack(wq, mp, size, 0); 626*3859Sml29623 } else 627*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 628*3859Sml29623 } else { 629*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 630*3859Sml29623 cmn_err(CE_NOTE, "!nxge_hw_ioctl: invalid command 0x%x", 631*3859Sml29623 iocp->ioc_cmd); 632*3859Sml29623 } 633*3859Sml29623 break; 634*3859Sml29623 } 635*3859Sml29623 } 636*3859Sml29623 637*3859Sml29623 /* 638*3859Sml29623 * DMA channel interfaces to access various channel specific 639*3859Sml29623 * hardware functions. 640*3859Sml29623 */ 641*3859Sml29623 /* ARGSUSED */ 642*3859Sml29623 void 643*3859Sml29623 nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle, void *reg_addrp, 644*3859Sml29623 uint32_t reg_base, uint16_t channel, uint64_t reg_data) 645*3859Sml29623 { 646*3859Sml29623 uint64_t reg_offset; 647*3859Sml29623 648*3859Sml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64")); 649*3859Sml29623 650*3859Sml29623 /* 651*3859Sml29623 * Channel is assumed to be from 0 to the maximum DMA channel #. If we 652*3859Sml29623 * use the virtual DMA CSR address space from the config space (in PCI 653*3859Sml29623 * case), then the following code need to be use different offset 654*3859Sml29623 * computation macro. 655*3859Sml29623 */ 656*3859Sml29623 reg_offset = reg_base + DMC_OFFSET(channel); 657*3859Sml29623 NXGE_PIO_WRITE64(handle, reg_addrp, reg_offset, reg_data); 658*3859Sml29623 659*3859Sml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64")); 660*3859Sml29623 } 661*3859Sml29623 662*3859Sml29623 /* ARGSUSED */ 663*3859Sml29623 uint64_t 664*3859Sml29623 nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle, void *reg_addrp, 665*3859Sml29623 uint32_t reg_base, uint16_t channel) 666*3859Sml29623 { 667*3859Sml29623 uint64_t reg_offset; 668*3859Sml29623 669*3859Sml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64")); 670*3859Sml29623 671*3859Sml29623 /* 672*3859Sml29623 * Channel is assumed to be from 0 to the maximum DMA channel #. If we 673*3859Sml29623 * use the virtual DMA CSR address space from the config space (in PCI 674*3859Sml29623 * case), then the following code need to be use different offset 675*3859Sml29623 * computation macro. 676*3859Sml29623 */ 677*3859Sml29623 reg_offset = reg_base + DMC_OFFSET(channel); 678*3859Sml29623 679*3859Sml29623 NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64")); 680*3859Sml29623 681*3859Sml29623 return (NXGE_PIO_READ64(handle, reg_addrp, reg_offset)); 682*3859Sml29623 } 683*3859Sml29623 684*3859Sml29623 /* ARGSUSED */ 685*3859Sml29623 void 686*3859Sml29623 nxge_get32(p_nxge_t nxgep, p_mblk_t mp) 687*3859Sml29623 { 688*3859Sml29623 nxge_os_acc_handle_t nxge_regh; 689*3859Sml29623 690*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32")); 691*3859Sml29623 nxge_regh = nxgep->dev_regs->nxge_regh; 692*3859Sml29623 693*3859Sml29623 *(uint32_t *)mp->b_rptr = NXGE_PIO_READ32(nxge_regh, 694*3859Sml29623 nxgep->dev_regs->nxge_regp, *(uint32_t *)mp->b_rptr); 695*3859Sml29623 696*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "value = 0x%08X", 697*3859Sml29623 *(uint32_t *)mp->b_rptr)); 698*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32")); 699*3859Sml29623 } 700*3859Sml29623 701*3859Sml29623 /* ARGSUSED */ 702*3859Sml29623 void 703*3859Sml29623 nxge_put32(p_nxge_t nxgep, p_mblk_t mp) 704*3859Sml29623 { 705*3859Sml29623 nxge_os_acc_handle_t nxge_regh; 706*3859Sml29623 uint32_t *buf; 707*3859Sml29623 uint8_t *reg; 708*3859Sml29623 709*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32")); 710*3859Sml29623 nxge_regh = nxgep->dev_regs->nxge_regh; 711*3859Sml29623 712*3859Sml29623 buf = (uint32_t *)mp->b_rptr; 713*3859Sml29623 reg = (uint8_t *)(nxgep->dev_regs->nxge_regp) + buf[0]; 714*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 715*3859Sml29623 "reg = 0x%016llX index = 0x%08X value = 0x%08X", 716*3859Sml29623 reg, buf[0], buf[1])); 717*3859Sml29623 NXGE_PIO_WRITE32(nxge_regh, (uint32_t *)reg, 0, buf[1]); 718*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32")); 719*3859Sml29623 } 720*3859Sml29623 721*3859Sml29623 /*ARGSUSED*/ 722*3859Sml29623 boolean_t 723*3859Sml29623 nxge_set_lb(p_nxge_t nxgep, queue_t *wq, p_mblk_t mp) 724*3859Sml29623 { 725*3859Sml29623 boolean_t status = B_TRUE; 726*3859Sml29623 uint32_t lb_mode; 727*3859Sml29623 lb_property_t *lb_info; 728*3859Sml29623 729*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_set_lb")); 730*3859Sml29623 lb_mode = nxgep->statsp->port_stats.lb_mode; 731*3859Sml29623 if (lb_mode == *(uint32_t *)mp->b_rptr) { 732*3859Sml29623 cmn_err(CE_NOTE, 733*3859Sml29623 "!nxge%d: Loopback mode already set (lb_mode %d).\n", 734*3859Sml29623 nxgep->instance, lb_mode); 735*3859Sml29623 status = B_FALSE; 736*3859Sml29623 goto nxge_set_lb_exit; 737*3859Sml29623 } 738*3859Sml29623 lb_mode = *(uint32_t *)mp->b_rptr; 739*3859Sml29623 lb_info = NULL; 740*3859Sml29623 if (lb_mode == lb_normal.value) 741*3859Sml29623 lb_info = &lb_normal; 742*3859Sml29623 else if ((lb_mode == lb_external10g.value) && 743*3859Sml29623 (nxgep->statsp->mac_stats.cap_10gfdx)) 744*3859Sml29623 lb_info = &lb_external10g; 745*3859Sml29623 else if ((lb_mode == lb_external1000.value) && 746*3859Sml29623 (nxgep->statsp->mac_stats.cap_1000fdx)) 747*3859Sml29623 lb_info = &lb_external1000; 748*3859Sml29623 else if ((lb_mode == lb_external100.value) && 749*3859Sml29623 (nxgep->statsp->mac_stats.cap_100fdx)) 750*3859Sml29623 lb_info = &lb_external100; 751*3859Sml29623 else if ((lb_mode == lb_external10.value) && 752*3859Sml29623 (nxgep->statsp->mac_stats.cap_10fdx)) 753*3859Sml29623 lb_info = &lb_external10; 754*3859Sml29623 else if ((lb_mode == lb_phy10g.value) && 755*3859Sml29623 ((nxgep->mac.portmode == PORT_10G_COPPER) || 756*3859Sml29623 (nxgep->mac.portmode == PORT_10G_FIBER))) 757*3859Sml29623 lb_info = &lb_phy10g; 758*3859Sml29623 else if ((lb_mode == lb_phy1000.value) && 759*3859Sml29623 (nxgep->mac.portmode == PORT_1G_COPPER)) 760*3859Sml29623 lb_info = &lb_phy1000; 761*3859Sml29623 else if ((lb_mode == lb_phy.value) && 762*3859Sml29623 (nxgep->mac.portmode == PORT_1G_COPPER)) 763*3859Sml29623 lb_info = &lb_phy; 764*3859Sml29623 else if ((lb_mode == lb_serdes10g.value) && 765*3859Sml29623 (nxgep->mac.portmode == PORT_10G_FIBER) || 766*3859Sml29623 (nxgep->mac.portmode == PORT_10G_COPPER)) 767*3859Sml29623 lb_info = &lb_serdes10g; 768*3859Sml29623 else if ((lb_mode == lb_serdes1000.value) && 769*3859Sml29623 (nxgep->mac.portmode == PORT_1G_FIBER)) 770*3859Sml29623 lb_info = &lb_serdes1000; 771*3859Sml29623 else if (lb_mode == lb_mac10g.value) 772*3859Sml29623 lb_info = &lb_mac10g; 773*3859Sml29623 else if (lb_mode == lb_mac1000.value) 774*3859Sml29623 lb_info = &lb_mac1000; 775*3859Sml29623 else if (lb_mode == lb_mac.value) 776*3859Sml29623 lb_info = &lb_mac; 777*3859Sml29623 else { 778*3859Sml29623 cmn_err(CE_NOTE, 779*3859Sml29623 "!nxge%d: Loopback mode not supported(mode %d).\n", 780*3859Sml29623 nxgep->instance, lb_mode); 781*3859Sml29623 status = B_FALSE; 782*3859Sml29623 goto nxge_set_lb_exit; 783*3859Sml29623 } 784*3859Sml29623 785*3859Sml29623 if (lb_mode == nxge_lb_normal) { 786*3859Sml29623 if (nxge_lb_dbg) { 787*3859Sml29623 cmn_err(CE_NOTE, 788*3859Sml29623 "!nxge%d: Returning to normal operation", 789*3859Sml29623 nxgep->instance); 790*3859Sml29623 } 791*3859Sml29623 nxge_set_lb_normal(nxgep); 792*3859Sml29623 goto nxge_set_lb_exit; 793*3859Sml29623 } 794*3859Sml29623 nxgep->statsp->port_stats.lb_mode = lb_mode; 795*3859Sml29623 796*3859Sml29623 if (nxge_lb_dbg) 797*3859Sml29623 cmn_err(CE_NOTE, 798*3859Sml29623 "!nxge%d: Adapter now in %s loopback mode", 799*3859Sml29623 nxgep->instance, lb_info->key); 800*3859Sml29623 nxgep->param_arr[param_autoneg].value = 0; 801*3859Sml29623 nxgep->param_arr[param_anar_10gfdx].value = 802*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) || 803*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) || 804*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) || 805*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g); 806*3859Sml29623 nxgep->param_arr[param_anar_10ghdx].value = 0; 807*3859Sml29623 nxgep->param_arr[param_anar_1000fdx].value = 808*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) || 809*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac1000) || 810*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) || 811*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000); 812*3859Sml29623 nxgep->param_arr[param_anar_1000hdx].value = 0; 813*3859Sml29623 nxgep->param_arr[param_anar_100fdx].value = 814*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy) || 815*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) || 816*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100); 817*3859Sml29623 nxgep->param_arr[param_anar_100hdx].value = 0; 818*3859Sml29623 nxgep->param_arr[param_anar_10fdx].value = 819*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) || 820*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10); 821*3859Sml29623 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) { 822*3859Sml29623 nxgep->param_arr[param_master_cfg_enable].value = 1; 823*3859Sml29623 nxgep->param_arr[param_master_cfg_value].value = 1; 824*3859Sml29623 } 825*3859Sml29623 if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) || 826*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) || 827*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100) || 828*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10) || 829*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) || 830*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) || 831*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy)) { 832*3859Sml29623 833*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 834*3859Sml29623 (void) nxge_xcvr_find(nxgep); 835*3859Sml29623 (void) nxge_link_init(nxgep); 836*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 837*3859Sml29623 } 838*3859Sml29623 if (lb_info->lb_type == internal) { 839*3859Sml29623 if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) || 840*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 841*3859Sml29623 nxge_lb_phy10g) || 842*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 843*3859Sml29623 nxge_lb_serdes10g)) { 844*3859Sml29623 nxgep->statsp->mac_stats.link_speed = 10000; 845*3859Sml29623 } else if ((nxgep->statsp->port_stats.lb_mode 846*3859Sml29623 == nxge_lb_mac1000) || 847*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 848*3859Sml29623 nxge_lb_phy1000) || 849*3859Sml29623 (nxgep->statsp->port_stats.lb_mode == 850*3859Sml29623 nxge_lb_serdes1000)) { 851*3859Sml29623 nxgep->statsp->mac_stats.link_speed = 1000; 852*3859Sml29623 } else { 853*3859Sml29623 nxgep->statsp->mac_stats.link_speed = 100; 854*3859Sml29623 } 855*3859Sml29623 nxgep->statsp->mac_stats.link_duplex = 2; 856*3859Sml29623 nxgep->statsp->mac_stats.link_up = 1; 857*3859Sml29623 } 858*3859Sml29623 nxge_global_reset(nxgep); 859*3859Sml29623 860*3859Sml29623 nxge_set_lb_exit: 861*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, 862*3859Sml29623 "<== nxge_set_lb status = 0x%08x", status)); 863*3859Sml29623 return (status); 864*3859Sml29623 } 865*3859Sml29623 866*3859Sml29623 /* ARGSUSED */ 867*3859Sml29623 void 868*3859Sml29623 nxge_set_lb_normal(p_nxge_t nxgep) 869*3859Sml29623 { 870*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_lb_normal")); 871*3859Sml29623 nxgep->statsp->port_stats.lb_mode = nxge_lb_normal; 872*3859Sml29623 nxgep->param_arr[param_autoneg].value = 873*3859Sml29623 nxgep->param_arr[param_autoneg].old_value; 874*3859Sml29623 nxgep->param_arr[param_anar_1000fdx].value = 875*3859Sml29623 nxgep->param_arr[param_anar_1000fdx].old_value; 876*3859Sml29623 nxgep->param_arr[param_anar_1000hdx].value = 877*3859Sml29623 nxgep->param_arr[param_anar_1000hdx].old_value; 878*3859Sml29623 nxgep->param_arr[param_anar_100fdx].value = 879*3859Sml29623 nxgep->param_arr[param_anar_100fdx].old_value; 880*3859Sml29623 nxgep->param_arr[param_anar_100hdx].value = 881*3859Sml29623 nxgep->param_arr[param_anar_100hdx].old_value; 882*3859Sml29623 nxgep->param_arr[param_anar_10fdx].value = 883*3859Sml29623 nxgep->param_arr[param_anar_10fdx].old_value; 884*3859Sml29623 nxgep->param_arr[param_master_cfg_enable].value = 885*3859Sml29623 nxgep->param_arr[param_master_cfg_enable].old_value; 886*3859Sml29623 nxgep->param_arr[param_master_cfg_value].value = 887*3859Sml29623 nxgep->param_arr[param_master_cfg_value].old_value; 888*3859Sml29623 889*3859Sml29623 nxge_global_reset(nxgep); 890*3859Sml29623 891*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_STOP); 892*3859Sml29623 (void) nxge_xcvr_find(nxgep); 893*3859Sml29623 (void) nxge_link_init(nxgep); 894*3859Sml29623 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 895*3859Sml29623 896*3859Sml29623 NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_lb_normal")); 897*3859Sml29623 } 898*3859Sml29623 899*3859Sml29623 /* ARGSUSED */ 900*3859Sml29623 void 901*3859Sml29623 nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp) 902*3859Sml29623 { 903*3859Sml29623 uint16_t reg; 904*3859Sml29623 905*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_get_mii")); 906*3859Sml29623 907*3859Sml29623 reg = *(uint16_t *)mp->b_rptr; 908*3859Sml29623 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, reg, 909*3859Sml29623 (uint16_t *)mp->b_rptr); 910*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "reg = 0x%08X value = 0x%04X", 911*3859Sml29623 reg, *(uint16_t *)mp->b_rptr)); 912*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_get_mii")); 913*3859Sml29623 } 914*3859Sml29623 915*3859Sml29623 /* ARGSUSED */ 916*3859Sml29623 void 917*3859Sml29623 nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp) 918*3859Sml29623 { 919*3859Sml29623 uint16_t *buf; 920*3859Sml29623 uint8_t reg; 921*3859Sml29623 922*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_put_mii")); 923*3859Sml29623 buf = (uint16_t *)mp->b_rptr; 924*3859Sml29623 reg = (uint8_t)buf[0]; 925*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, 926*3859Sml29623 "reg = 0x%08X index = 0x%08X value = 0x%08X", 927*3859Sml29623 reg, buf[0], buf[1])); 928*3859Sml29623 (void) nxge_mii_write(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 929*3859Sml29623 reg, buf[1]); 930*3859Sml29623 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_put_mii")); 931*3859Sml29623 } 932*3859Sml29623 933*3859Sml29623 /* ARGSUSED */ 934*3859Sml29623 void 935*3859Sml29623 nxge_check_hw_state(p_nxge_t nxgep) 936*3859Sml29623 { 937*3859Sml29623 p_nxge_ldgv_t ldgvp; 938*3859Sml29623 p_nxge_ldv_t t_ldvp; 939*3859Sml29623 940*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "==> nxge_check_hw_state")); 941*3859Sml29623 942*3859Sml29623 MUTEX_ENTER(nxgep->genlock); 943*3859Sml29623 nxgep->nxge_timerid = 0; 944*3859Sml29623 if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) { 945*3859Sml29623 goto nxge_check_hw_state_exit; 946*3859Sml29623 } 947*3859Sml29623 nxge_check_tx_hang(nxgep); 948*3859Sml29623 949*3859Sml29623 ldgvp = nxgep->ldgvp; 950*3859Sml29623 if (ldgvp == NULL || (ldgvp->ldvp_syserr == NULL)) { 951*3859Sml29623 NXGE_ERROR_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: " 952*3859Sml29623 "NULL ldgvp (interrupt not ready).")); 953*3859Sml29623 goto nxge_check_hw_state_exit; 954*3859Sml29623 } 955*3859Sml29623 t_ldvp = ldgvp->ldvp_syserr; 956*3859Sml29623 if (!t_ldvp->use_timer) { 957*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: " 958*3859Sml29623 "ldgvp $%p t_ldvp $%p use_timer flag %d", 959*3859Sml29623 ldgvp, t_ldvp, t_ldvp->use_timer)); 960*3859Sml29623 goto nxge_check_hw_state_exit; 961*3859Sml29623 } 962*3859Sml29623 if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) { 963*3859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 964*3859Sml29623 "port%d Bad register acc handle", nxgep->mac.portnum)); 965*3859Sml29623 } 966*3859Sml29623 (void) nxge_syserr_intr((void *) t_ldvp, (void *) nxgep); 967*3859Sml29623 968*3859Sml29623 nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state, 969*3859Sml29623 NXGE_CHECK_TIMER); 970*3859Sml29623 971*3859Sml29623 nxge_check_hw_state_exit: 972*3859Sml29623 MUTEX_EXIT(nxgep->genlock); 973*3859Sml29623 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state")); 974*3859Sml29623 } 975*3859Sml29623 976*3859Sml29623 /*ARGSUSED*/ 977*3859Sml29623 static void 978*3859Sml29623 nxge_rtrace_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, 979*3859Sml29623 struct iocblk *iocp) 980*3859Sml29623 { 981*3859Sml29623 ssize_t size; 982*3859Sml29623 rtrace_t *rtp; 983*3859Sml29623 mblk_t *nmp; 984*3859Sml29623 uint32_t i, j; 985*3859Sml29623 uint32_t start_blk; 986*3859Sml29623 uint32_t base_entry; 987*3859Sml29623 uint32_t num_entries; 988*3859Sml29623 989*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_rtrace_ioctl")); 990*3859Sml29623 991*3859Sml29623 size = 1024; 992*3859Sml29623 if (mp->b_cont == NULL || MBLKL(mp->b_cont) < size) { 993*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, 994*3859Sml29623 "malformed M_IOCTL MBLKL = %d size = %d", 995*3859Sml29623 MBLKL(mp->b_cont), size)); 996*3859Sml29623 miocnak(wq, mp, 0, EINVAL); 997*3859Sml29623 return; 998*3859Sml29623 } 999*3859Sml29623 nmp = mp->b_cont; 1000*3859Sml29623 rtp = (rtrace_t *)nmp->b_rptr; 1001*3859Sml29623 start_blk = rtp->next_idx; 1002*3859Sml29623 num_entries = rtp->last_idx; 1003*3859Sml29623 base_entry = start_blk * MAX_RTRACE_IOC_ENTRIES; 1004*3859Sml29623 1005*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "start_blk = %d\n", start_blk)); 1006*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "num_entries = %d\n", num_entries)); 1007*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "base_entry = %d\n", base_entry)); 1008*3859Sml29623 1009*3859Sml29623 rtp->next_idx = npi_rtracebuf.next_idx; 1010*3859Sml29623 rtp->last_idx = npi_rtracebuf.last_idx; 1011*3859Sml29623 rtp->wrapped = npi_rtracebuf.wrapped; 1012*3859Sml29623 for (i = 0, j = base_entry; i < num_entries; i++, j++) { 1013*3859Sml29623 rtp->buf[i].ctl_addr = npi_rtracebuf.buf[j].ctl_addr; 1014*3859Sml29623 rtp->buf[i].val_l32 = npi_rtracebuf.buf[j].val_l32; 1015*3859Sml29623 rtp->buf[i].val_h32 = npi_rtracebuf.buf[j].val_h32; 1016*3859Sml29623 } 1017*3859Sml29623 1018*3859Sml29623 nmp->b_wptr = nmp->b_rptr + size; 1019*3859Sml29623 NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_rtrace_ioctl")); 1020*3859Sml29623 miocack(wq, mp, (int)size, 0); 1021*3859Sml29623 } 1022