Crossbow - transition to Mercurial

   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #include <sys/nxge/nxge_impl.h>
  29 
  30 /*
  31  * Tunable Receive Completion Ring Configuration B parameters.
  32  */
  33 uint16_t nxge_rx_pkt_thres;     /* 16 bits */
  34 uint8_t nxge_rx_pkt_timeout;    /* 6 bits based on DMA clock divider */
  35 
  36 lb_property_t lb_normal = {normal, "normal", nxge_lb_normal};
  37 lb_property_t lb_external10g = {external, "external10g", nxge_lb_ext10g};
  38 lb_property_t lb_external1000 = {external, "external1000", nxge_lb_ext1000};
  39 lb_property_t lb_external100 = {external, "external100", nxge_lb_ext100};
  40 lb_property_t lb_external10 = {external, "external10", nxge_lb_ext10};
  41 lb_property_t lb_phy10g = {internal, "phy10g", nxge_lb_phy10g};
  42 lb_property_t lb_phy1000 = {internal, "phy1000", nxge_lb_phy1000};
  43 lb_property_t lb_phy = {internal, "phy", nxge_lb_phy};
  44 lb_property_t lb_serdes10g = {internal, "serdes10g", nxge_lb_serdes10g};
  45 lb_property_t lb_serdes1000 = {internal, "serdes", nxge_lb_serdes1000};
  46 lb_property_t lb_mac10g = {internal, "mac10g", nxge_lb_mac10g};
  47 lb_property_t lb_mac1000 = {internal, "mac1000", nxge_lb_mac1000};
  48 lb_property_t lb_mac = {internal, "mac10/100", nxge_lb_mac};
  49 
  50 uint32_t nxge_lb_dbg = 1;
  51 void nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp);
  52 void nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp);
  53 static nxge_status_t nxge_check_xaui_xfp(p_nxge_t nxgep);
  54 
  55 extern uint32_t nxge_rx_mode;
  56 extern uint32_t nxge_jumbo_mtu;
  57 extern boolean_t nxge_jumbo_enable;
  58 
  59 static void
  60 nxge_rtrace_ioctl(p_nxge_t, queue_t *, mblk_t *, struct iocblk *);
  61 
  62 /* ARGSUSED */
  63 nxge_status_t
  64 nxge_global_reset(p_nxge_t nxgep)
  65 {
  66         nxge_status_t   status = NXGE_OK;
  67 
  68         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_global_reset"));
  69 
  70         if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_STOP)) != NXGE_OK)
  71                 return (status);
  72         (void) nxge_intr_hw_disable(nxgep);
  73 
  74         if ((nxgep->suspended) ||
  75             ((nxgep->statsp->port_stats.lb_mode ==
  76             nxge_lb_phy1000) ||
  77             (nxgep->statsp->port_stats.lb_mode ==
  78             nxge_lb_phy10g) ||
  79             (nxgep->statsp->port_stats.lb_mode ==
  80             nxge_lb_serdes1000) ||
  81             (nxgep->statsp->port_stats.lb_mode ==
  82             nxge_lb_serdes10g))) {
  83                 if ((status = nxge_link_init(nxgep)) != NXGE_OK)
  84                         return (status);
  85         }
  86 
  87         if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_START)) != NXGE_OK)
  88                 return (status);
  89         if ((status = nxge_mac_init(nxgep)) != NXGE_OK)
  90                 return (status);
  91         (void) nxge_intr_hw_enable(nxgep);
  92 
  93         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_global_reset"));
  94         return (status);
  95 }
  96 
  97 /* ARGSUSED */
  98 void
  99 nxge_hw_id_init(p_nxge_t nxgep)
 100 {
 101         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_id_init"));
 102         /*
 103          * Set up initial hardware parameters required such as mac mtu size.
 104          */
 105         nxgep->mac.is_jumbo = B_FALSE;
 106         /*
 107          * Set the maxframe size to 1522 (1518 + 4) to account for
 108          * VLAN tagged packets.
 109          */
 110         nxgep->mac.minframesize = NXGE_MIN_MAC_FRAMESIZE; /* 64   */
 111         nxgep->mac.maxframesize = NXGE_MAX_MAC_FRAMESIZE; /* 1522 */
 112         if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) {
 113                 nxgep->mac.maxframesize = (uint16_t)nxge_jumbo_mtu;
 114                 nxgep->mac.is_jumbo = B_TRUE;
 115         }
 116         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
 117             "==> nxge_hw_id_init: maxframesize %d",
 118             nxgep->mac.maxframesize));
 119 
 120         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_id_init"));
 121 }
 122 
 123 /* ARGSUSED */
 124 void
 125 nxge_hw_init_niu_common(p_nxge_t nxgep)
 126 {
 127         p_nxge_hw_list_t hw_p;
 128 
 129         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_init_niu_common"));
 130 
 131         if ((hw_p = nxgep->nxge_hw_p) == NULL) {
 132                 return;
 133         }
 134         MUTEX_ENTER(&hw_p->nxge_cfg_lock);
 135         if (hw_p->flags & COMMON_INIT_DONE) {
 136                 NXGE_DEBUG_MSG((nxgep, MOD_CTL,
 137                     "nxge_hw_init_niu_common"
 138                     " already done for dip $%p function %d exiting",
 139                     hw_p->parent_devp, nxgep->function_num));
 140                 MUTEX_EXIT(&hw_p->nxge_cfg_lock);
 141                 return;
 142         }
 143 
 144         hw_p->flags = COMMON_INIT_START;
 145         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
 146             " Started for device id %x with function %d",
 147             hw_p->parent_devp, nxgep->function_num));
 148 
 149         /* per neptune common block init */
 150         (void) nxge_fflp_hw_reset(nxgep);
 151 
 152         hw_p->flags = COMMON_INIT_DONE;
 153         MUTEX_EXIT(&hw_p->nxge_cfg_lock);
 154 
 155         NXGE_DEBUG_MSG((nxgep, MOD_CTL, "nxge_hw_init_niu_common"
 156             " Done for device id %x with function %d",
 157             hw_p->parent_devp, nxgep->function_num));
 158         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_init_niu_common"));
 159 }
 160 
 161 /* ARGSUSED */
 162 uint_t
 163 nxge_intr(void *arg1, void *arg2)
 164 {
 165         p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
 166         p_nxge_t nxgep = (p_nxge_t)arg2;
 167         uint_t serviced = DDI_INTR_UNCLAIMED;
 168         uint8_t ldv;
 169         npi_handle_t handle;
 170         p_nxge_ldgv_t ldgvp;
 171         p_nxge_ldg_t ldgp, t_ldgp;
 172         p_nxge_ldv_t t_ldvp;
 173         uint64_t vector0 = 0, vector1 = 0, vector2 = 0;
 174         int i, j, nldvs, nintrs = 1;
 175         npi_status_t rs = NPI_SUCCESS;
 176 
 177         /* DDI interface returns second arg as NULL (n2 niumx driver) !!! */
 178         if (arg2 == NULL || (void *) ldvp->nxgep != arg2) {
 179                 nxgep = ldvp->nxgep;
 180         }
 181         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr"));
 182 
 183         if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
 184                 NXGE_ERROR_MSG((nxgep, INT_CTL,
 185                     "<== nxge_intr: not initialized 0x%x", serviced));
 186                 return (serviced);
 187         }
 188 
 189         ldgvp = nxgep->ldgvp;
 190         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: ldgvp $%p", ldgvp));
 191         if (ldvp == NULL && ldgvp) {
 192                 t_ldvp = ldvp = ldgvp->ldvp;
 193         }
 194         if (ldvp) {
 195                 ldgp = t_ldgp = ldvp->ldgp;
 196         }
 197         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
 198             "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp));
 199         if (ldgvp == NULL || ldvp == NULL || ldgp == NULL) {
 200                 NXGE_ERROR_MSG((nxgep, INT_CTL, "==> nxge_intr: "
 201                     "ldgvp $%p ldvp $%p ldgp $%p", ldgvp, ldvp, ldgp));
 202                 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_intr: not ready"));
 203                 return (DDI_INTR_UNCLAIMED);
 204         }
 205         /*
 206          * This interrupt handler will have to go through all the logical
 207          * devices to find out which logical device interrupts us and then call
 208          * its handler to process the events.
 209          */
 210         handle = NXGE_DEV_NPI_HANDLE(nxgep);
 211         t_ldgp = ldgp;
 212         t_ldvp = ldgp->ldvp;
 213 
 214         nldvs = ldgp->nldvs;
 215 
 216         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: #ldvs %d #intrs %d",
 217             nldvs, ldgvp->ldg_intrs));
 218 
 219         serviced = DDI_INTR_CLAIMED;
 220         for (i = 0; i < nintrs; i++, t_ldgp++) {
 221                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr(%d): #ldvs %d "
 222                     " #intrs %d", i, nldvs, nintrs));
 223                 /* Get this group's flag bits.  */

 224                 rs = npi_ldsv_ldfs_get(handle, t_ldgp->ldg,
 225                     &vector0, &vector1, &vector2);
 226                 if (rs) {
 227                         continue;
 228                 }
 229                 if (!vector0 && !vector1 && !vector2) {
 230                         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
 231                             "no interrupts on group %d", t_ldgp->ldg));
 232                         continue;
 233                 }
 234                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: "
 235                     "vector0 0x%llx vector1 0x%llx vector2 0x%llx",
 236                     vector0, vector1, vector2));

 237                 nldvs = t_ldgp->nldvs;
 238                 for (j = 0; j < nldvs; j++, t_ldvp++) {
 239                         /*
 240                          * Call device's handler if flag bits are on.
 241                          */
 242                         ldv = t_ldvp->ldv;
 243                         if (((ldv < NXGE_MAC_LD_START) &&
 244                             (LDV_ON(ldv, vector0) |
 245                             (LDV_ON(ldv, vector1)))) ||
 246                             (ldv >= NXGE_MAC_LD_START &&
 247                             ((LDV2_ON_1(ldv, vector2)) ||
 248                             (LDV2_ON_2(ldv, vector2))))) {
 249                                 (void) (t_ldvp->ldv_intr_handler)(
 250                                     (caddr_t)t_ldvp, arg2);
 251                                 NXGE_DEBUG_MSG((nxgep, INT_CTL,
 252                                     "==> nxge_intr: "
 253                                     "calling device %d #ldvs %d #intrs %d",
 254                                     j, nldvs, nintrs));
 255                         }
 256                 }
 257         }
 258 
 259         t_ldgp = ldgp;
 260         for (i = 0; i < nintrs; i++, t_ldgp++) {
 261                 /* rearm group interrupts */

 262                 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr: arm "
 263                     "group %d", t_ldgp->ldg));
 264                 (void) npi_intr_ldg_mgmt_set(handle, t_ldgp->ldg,
 265                     t_ldgp->arm, t_ldgp->ldg_timer);
 266         }

 267 
 268         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr: serviced 0x%x",
 269             serviced));
 270         return (serviced);
 271 }
 272 
 273 
 274 /*
 275  * XFP Related Status Register Values Under 3 Different Conditions
 276  *
 277  * -------------+-------------------------+-------------------------
 278  *              |   Intel XFP and Avago   |      Picolight XFP
 279  * -------------+---------+---------------+---------+---------------
 280  *              | STATUS0 | TX_ALARM_STAT | STATUS0 | TX_ALARM_STAT
 281  * -------------+---------+---------------+---------+---------------
 282  *      No XFP  | 0x639C  |      0x40     | 0x639C  |      0x40
 283  * -------------+---------+---------------+---------+---------------
 284  * XFP,linkdown | 0x43BC  |      0x40     | 0x639C  |      0x40
 285  * -------------+---------+---------------+---------+---------------
 286  * XFP,linkup   | 0x03FC  |      0x0      | 0x03FC  |      0x0
 287  * -------------+---------+---------------+---------+---------------
 288  * Note:
 289  *      STATUS0         = BCM8704_USER_ANALOG_STATUS0_REG
 290  *      TX_ALARM_STAT   = BCM8704_USER_TX_ALARM_STATUS_REG
 291  */
 292 /* ARGSUSED */
 293 static nxge_status_t
 294 nxge_check_xaui_xfp(p_nxge_t nxgep)
 295 {
 296         nxge_status_t   status = NXGE_OK;
 297         uint8_t         phy_port_addr;
 298         uint16_t        val;
 299         uint16_t        val1;
 300         uint8_t         portn;
 301 
 302         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_check_xaui_xfp"));
 303 
 304         portn = nxgep->mac.portnum;
 305         phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
 306 
 307         /*
 308          * Keep the val1 code even though it is not used. Could be
 309          * used to differenciate the "No XFP" case and "XFP,linkdown"
 310          * case when a Intel XFP is used.
 311          */
 312         if ((status = nxge_mdio_read(nxgep, phy_port_addr,
 313             BCM8704_USER_DEV3_ADDR,
 314             BCM8704_USER_ANALOG_STATUS0_REG, &val)) == NXGE_OK) {
 315                 status = nxge_mdio_read(nxgep, phy_port_addr,
 316                     BCM8704_USER_DEV3_ADDR,
 317                     BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
 318         }
 319 
 320         if (status != NXGE_OK) {
 321                 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
 322                     NXGE_FM_EREPORT_XAUI_ERR);
 323                 if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities)) {
 324                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 325                             "XAUI is bad or absent on port<%d>\n", portn));
 326                 }
 327 #ifdef NXGE_DEBUG
 328         /*
 329          * As a workaround for CR6693529, do not execute this block of
 330          * code for non-debug driver. When a Picolight XFP transceiver
 331          * is used, register BCM8704_USER_ANALOG_STATUS0_REG returns
 332          * the same 0x639C value in normal link down case, which causes
 333          * false FMA messages and link reconnection problem.
 334          */
 335         } else if (nxgep->mac.portmode == PORT_10G_FIBER) {
 336                 /*
 337                  * 0x03FC = 0000 0011 1111 1100 (XFP is normal)
 338                  * 0x639C = 0110 0011 1001 1100 (XFP has problem)
 339                  * bit14 = 1: PDM loss-of-light indicator
 340                  * bit13 = 1: PDM Rx loss-of-signal
 341                  * bit6  = 0: Light is NOT ok
 342                  * bit5  = 0: PMD Rx signal is NOT ok
 343                  */
 344                 if (val == 0x639C) {
 345                         NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
 346                             NXGE_FM_EREPORT_XFP_ERR);
 347                         if (DDI_FM_EREPORT_CAP(nxgep->fm_capabilities)) {
 348                                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 349                                     "XFP is bad or absent on port<%d>\n",
 350                                     portn));
 351                         }
 352                         status = NXGE_ERROR;
 353                 }
 354 #endif
 355         }
 356         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_check_xaui_xfp"));
 357         return (status);
 358 }
 359 
 360 
 361 /* ARGSUSED */
 362 uint_t
 363 nxge_syserr_intr(void *arg1, void *arg2)
 364 {
 365         p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
 366         p_nxge_t nxgep = (p_nxge_t)arg2;
 367         p_nxge_ldg_t ldgp = NULL;
 368         npi_handle_t handle;
 369         sys_err_stat_t estat;
 370         uint_t serviced = DDI_INTR_UNCLAIMED;
 371 
 372         if (arg1 == NULL && arg2 == NULL) {
 373                 return (serviced);
 374         }
 375         if (arg2 == NULL || ((ldvp != NULL && (void *) ldvp->nxgep != arg2))) {
 376                 if (ldvp != NULL) {
 377                         nxgep = ldvp->nxgep;
 378                 }
 379         }
 380         NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
 381             "==> nxge_syserr_intr: arg2 $%p arg1 $%p", nxgep, ldvp));
 382         if (ldvp != NULL && ldvp->use_timer == B_FALSE) {
 383                 ldgp = ldvp->ldgp;
 384                 if (ldgp == NULL) {
 385                         NXGE_ERROR_MSG((nxgep, SYSERR_CTL,
 386                             "<== nxge_syserrintr(no logical group): "
 387                             "arg2 $%p arg1 $%p", nxgep, ldvp));
 388                         return (DDI_INTR_UNCLAIMED);
 389                 }
 390                 /*
 391                  * Get the logical device state if the function uses interrupt.
 392                  */
 393         }
 394 
 395         /* This interrupt handler is for system error interrupts.  */
 396         handle = NXGE_DEV_NPI_HANDLE(nxgep);
 397         estat.value = 0;
 398         (void) npi_fzc_sys_err_stat_get(handle, &estat);
 399         NXGE_DEBUG_MSG((nxgep, SYSERR_CTL,
 400             "==> nxge_syserr_intr: device error 0x%016llx", estat.value));
 401 
 402         if (estat.bits.ldw.smx) {
 403                 /* SMX */
 404                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 405                     "==> nxge_syserr_intr: device error - SMX"));
 406         } else if (estat.bits.ldw.mac) {
 407                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 408                     "==> nxge_syserr_intr: device error - MAC"));
 409                 /*
 410                  * There is nothing to be done here. All MAC errors go to per
 411                  * MAC port interrupt. MIF interrupt is the only MAC sub-block
 412                  * that can generate status here. MIF status reported will be
 413                  * ignored here. It is checked by per port timer instead.
 414                  */
 415         } else if (estat.bits.ldw.ipp) {
 416                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
 417                     "==> nxge_syserr_intr: device error - IPP"));
 418                 (void) nxge_ipp_handle_sys_errors(nxgep);
 419         } else if (estat.bits.ldw.zcp) {
 420                 /* ZCP */
 421                 NXGE_DEBUG_MSG((nxgep, NXGE_ERR_CTL,
 422                     "==> nxge_syserr_intr: device error - ZCP"));
 423                 (void) nxge_zcp_handle_sys_errors(nxgep);
 424         } else if (estat.bits.ldw.tdmc) {
 425                 /* TDMC */
 426                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 427                     "==> nxge_syserr_intr: device error - TDMC"));
 428                 /*
 429                  * There is no TDMC system errors defined in the PRM. All TDMC
 430                  * channel specific errors are reported on a per channel basis.
 431                  */
 432         } else if (estat.bits.ldw.rdmc) {
 433                 /* RDMC */
 434                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 435                     "==> nxge_syserr_intr: device error - RDMC"));
 436                 (void) nxge_rxdma_handle_sys_errors(nxgep);
 437         } else if (estat.bits.ldw.txc) {
 438                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 439                     "==> nxge_syserr_intr: device error - TXC"));
 440                 (void) nxge_txc_handle_sys_errors(nxgep);
 441         } else if ((nxgep->niu_type != N2_NIU) && estat.bits.ldw.peu) {
 442                 /* PCI-E */
 443                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 444                     "==> nxge_syserr_intr: device error - PCI-E"));
 445         } else if (estat.bits.ldw.meta1) {
 446                 /* META1 */
 447                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 448                     "==> nxge_syserr_intr: device error - META1"));
 449         } else if (estat.bits.ldw.meta2) {
 450                 /* META2 */
 451                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 452                     "==> nxge_syserr_intr: device error - META2"));
 453         } else if (estat.bits.ldw.fflp) {
 454                 /* FFLP */
 455                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 456                     "==> nxge_syserr_intr: device error - FFLP"));
 457                 (void) nxge_fflp_handle_sys_errors(nxgep);
 458         }
 459 
 460         /*
 461          * nxge_check_xaui_xfg checks XAUI for all of the following
 462          * portmodes, but checks XFP only if portmode == PORT_10G_FIBER.
 463          */
 464         if (nxgep->mac.portmode == PORT_10G_FIBER ||
 465             nxgep->mac.portmode == PORT_10G_COPPER ||
 466             nxgep->mac.portmode == PORT_10G_TN1010 ||
 467             nxgep->mac.portmode == PORT_1G_TN1010) {
 468                 if (nxge_check_xaui_xfp(nxgep) != NXGE_OK) {
 469                         NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
 470                             "==> nxge_syserr_intr: device error - XAUI"));
 471                 }
 472         }
 473 
 474         serviced = DDI_INTR_CLAIMED;
 475 
 476         if (ldgp != NULL && ldvp != NULL && ldgp->nldvs == 1 &&
 477             !ldvp->use_timer) {
 478                 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
 479                     B_TRUE, ldgp->ldg_timer);
 480         }
 481         NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_syserr_intr"));
 482         return (serviced);
 483 }
 484 
 485 /* ARGSUSED */
 486 void
 487 nxge_intr_hw_enable(p_nxge_t nxgep)
 488 {
 489         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_enable"));
 490         (void) nxge_intr_mask_mgmt_set(nxgep, B_TRUE);
 491         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_enable"));
 492 }
 493 
 494 /* ARGSUSED */
 495 void
 496 nxge_intr_hw_disable(p_nxge_t nxgep)
 497 {
 498         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_intr_hw_disable"));
 499         (void) nxge_intr_mask_mgmt_set(nxgep, B_FALSE);
 500         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_intr_hw_disable"));
 501 }
 502 
 503 /* ARGSUSED */
 504 void
 505 nxge_rx_hw_blank(void *arg, time_t ticks, uint_t count)
 506 {
 507         p_nxge_t nxgep = (p_nxge_t)arg;
 508         uint8_t channel;
 509         npi_handle_t handle;
 510         p_nxge_ldgv_t ldgvp;
 511         p_nxge_ldv_t ldvp;
 512         int i;
 513 
 514         NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_rx_hw_blank"));
 515         handle = NXGE_DEV_NPI_HANDLE(nxgep);
 516 
 517         if ((ldgvp = nxgep->ldgvp) == NULL) {
 518                 NXGE_ERROR_MSG((nxgep, INT_CTL,
 519                     "<== nxge_rx_hw_blank (not enabled)"));
 520                 return;
 521         }
 522         ldvp = nxgep->ldgvp->ldvp;
 523         if (ldvp == NULL) {
 524                 return;
 525         }
 526         for (i = 0; i < ldgvp->nldvs; i++, ldvp++) {
 527                 if (ldvp->is_rxdma) {
 528                         channel = ldvp->channel;
 529                         (void) npi_rxdma_cfg_rdc_rcr_threshold(handle,
 530                             channel, count);
 531                         (void) npi_rxdma_cfg_rdc_rcr_timeout(handle,
 532                             channel, ticks);
 533                 }
 534         }
 535 
 536         NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_rx_hw_blank"));
 537 }
 538 
 539 /* ARGSUSED */
 540 void
 541 nxge_hw_stop(p_nxge_t nxgep)
 542 {
 543         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_hw_stop"));
 544 
 545         (void) nxge_tx_mac_disable(nxgep);
 546         (void) nxge_rx_mac_disable(nxgep);
 547         (void) nxge_txdma_hw_mode(nxgep, NXGE_DMA_STOP);
 548         (void) nxge_rxdma_hw_mode(nxgep, NXGE_DMA_STOP);
 549 
 550         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_hw_stop"));
 551 }
 552 
 553 /* ARGSUSED */
 554 void
 555 nxge_hw_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
 556 {
 557         int cmd;
 558 
 559         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_hw_ioctl"));
 560 
 561         if (nxgep == NULL) {
 562                 miocnak(wq, mp, 0, EINVAL);
 563                 return;
 564         }
 565         iocp->ioc_error = 0;
 566         cmd = iocp->ioc_cmd;
 567 
 568         switch (cmd) {
 569         default:
 570                 miocnak(wq, mp, 0, EINVAL);
 571                 return;
 572 
 573         case NXGE_GET_MII:
 574                 nxge_get_mii(nxgep, mp->b_cont);
 575                 miocack(wq, mp, sizeof (uint16_t), 0);
 576                 break;
 577 
 578         case NXGE_PUT_MII:
 579                 nxge_put_mii(nxgep, mp->b_cont);
 580                 miocack(wq, mp, 0, 0);
 581                 break;
 582 
 583         case NXGE_GET64:
 584                 nxge_get64(nxgep, mp->b_cont);
 585                 miocack(wq, mp, sizeof (uint32_t), 0);
 586                 break;
 587 
 588         case NXGE_PUT64:
 589                 nxge_put64(nxgep, mp->b_cont);
 590                 miocack(wq, mp, 0, 0);
 591                 break;
 592 
 593         case NXGE_PUT_TCAM:
 594                 nxge_put_tcam(nxgep, mp->b_cont);
 595                 miocack(wq, mp, 0, 0);
 596                 break;
 597 
 598         case NXGE_GET_TCAM:
 599                 nxge_get_tcam(nxgep, mp->b_cont);
 600                 miocack(wq, mp, 0, 0);
 601                 break;
 602 
 603         case NXGE_TX_REGS_DUMP:
 604                 nxge_txdma_regs_dump_channels(nxgep);
 605                 miocack(wq, mp, 0, 0);
 606                 break;
 607         case NXGE_RX_REGS_DUMP:
 608                 nxge_rxdma_regs_dump_channels(nxgep);
 609                 miocack(wq, mp, 0, 0);
 610                 break;
 611         case NXGE_VIR_INT_REGS_DUMP:
 612         case NXGE_INT_REGS_DUMP:
 613                 nxge_virint_regs_dump(nxgep);
 614                 miocack(wq, mp, 0, 0);
 615                 break;
 616         case NXGE_RTRACE:
 617                 nxge_rtrace_ioctl(nxgep, wq, mp, iocp);
 618                 break;
 619         }
 620 }
 621 
 622 /* ARGSUSED */
 623 void
 624 nxge_loopback_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp,
 625         struct iocblk *iocp)
 626 {
 627         p_lb_property_t lb_props;
 628 
 629         size_t size;
 630         int i;
 631 
 632         if (mp->b_cont == NULL) {
 633                 miocnak(wq, mp, 0, EINVAL);
 634         }
 635         switch (iocp->ioc_cmd) {
 636         case LB_GET_MODE:
 637                 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_MODE command"));
 638                 if (nxgep != NULL) {
 639                         *(lb_info_sz_t *)mp->b_cont->b_rptr =
 640                             nxgep->statsp->port_stats.lb_mode;
 641                         miocack(wq, mp, sizeof (nxge_lb_t), 0);
 642                 } else {
 643                         miocnak(wq, mp, 0, EINVAL);
 644                 }
 645                 break;
 646         case LB_SET_MODE:
 647                 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_SET_LB_MODE command"));
 648                 if (iocp->ioc_count != sizeof (uint32_t)) {
 649                         miocack(wq, mp, 0, 0);
 650                         break;
 651                 }
 652                 if ((nxgep != NULL) && nxge_set_lb(nxgep, wq, mp->b_cont)) {
 653                         miocack(wq, mp, 0, 0);
 654                 } else {
 655                         miocnak(wq, mp, 0, EPROTO);
 656                 }
 657                 break;
 658         case LB_GET_INFO_SIZE:
 659                 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "LB_GET_INFO_SIZE command"));
 660                 if (nxgep != NULL) {
 661                         size = sizeof (lb_normal);
 662                         if (nxgep->statsp->mac_stats.cap_10gfdx) {
 663                                 /* TN1010 does not support external loopback */
 664                                 if (nxgep->mac.portmode != PORT_1G_TN1010 &&
 665                                     nxgep->mac.portmode != PORT_10G_TN1010) {
 666                                         size += sizeof (lb_external10g);
 667                                 }
 668                                 size += sizeof (lb_mac10g);
 669                                 /* Publish PHY loopback if PHY is present */
 670                                 if (nxgep->mac.portmode == PORT_10G_COPPER ||
 671                                     nxgep->mac.portmode == PORT_10G_TN1010 ||
 672                                     nxgep->mac.portmode == PORT_10G_FIBER)
 673                                         size += sizeof (lb_phy10g);
 674                         }
 675 
 676                         /*
 677                          * Even if cap_10gfdx is false, we still do 10G
 678                          * serdes loopback as a part of SunVTS xnetlbtest
 679                          * internal loopback test.
 680                          */
 681                         if (nxgep->mac.portmode == PORT_10G_FIBER ||
 682                             nxgep->mac.portmode == PORT_10G_TN1010 ||
 683                             nxgep->mac.portmode == PORT_10G_SERDES)
 684                                 size += sizeof (lb_serdes10g);
 685 
 686                         if (nxgep->statsp->mac_stats.cap_1000fdx) {
 687                                 /* TN1010 does not support external loopback */
 688                                 if (nxgep->mac.portmode != PORT_1G_TN1010 &&
 689                                     nxgep->mac.portmode != PORT_10G_TN1010) {
 690                                         size += sizeof (lb_external1000);
 691                                 }
 692                                 size += sizeof (lb_mac1000);
 693                                 if (nxgep->mac.portmode == PORT_1G_COPPER ||
 694                                     nxgep->mac.portmode == PORT_1G_TN1010 ||
 695                                     nxgep->mac.portmode ==
 696                                     PORT_1G_RGMII_FIBER)
 697                                         size += sizeof (lb_phy1000);
 698                         }
 699                         if (nxgep->statsp->mac_stats.cap_100fdx)
 700                                 size += sizeof (lb_external100);
 701                         if (nxgep->statsp->mac_stats.cap_10fdx)
 702                                 size += sizeof (lb_external10);
 703                         if (nxgep->mac.portmode == PORT_1G_FIBER ||
 704                             nxgep->mac.portmode == PORT_1G_TN1010 ||
 705                             nxgep->mac.portmode == PORT_1G_SERDES)
 706                                 size += sizeof (lb_serdes1000);
 707 
 708                         *(lb_info_sz_t *)mp->b_cont->b_rptr = size;
 709 
 710                         NXGE_DEBUG_MSG((nxgep, IOC_CTL,
 711                             "NXGE_GET_LB_INFO command: size %d", size));
 712                         miocack(wq, mp, sizeof (lb_info_sz_t), 0);
 713                 } else
 714                         miocnak(wq, mp, 0, EINVAL);
 715                 break;
 716 
 717         case LB_GET_INFO:
 718                 NXGE_DEBUG_MSG((nxgep, IOC_CTL, "NXGE_GET_LB_INFO command"));
 719                 if (nxgep != NULL) {
 720                         size = sizeof (lb_normal);
 721                         if (nxgep->statsp->mac_stats.cap_10gfdx) {
 722                                 /* TN1010 does not support external loopback */
 723                                 if (nxgep->mac.portmode != PORT_1G_TN1010 &&
 724                                     nxgep->mac.portmode != PORT_10G_TN1010) {
 725                                         size += sizeof (lb_external10g);
 726                                 }
 727                                 size += sizeof (lb_mac10g);
 728                                 /* Publish PHY loopback if PHY is present */
 729                                 if (nxgep->mac.portmode == PORT_10G_COPPER ||
 730                                     nxgep->mac.portmode == PORT_10G_TN1010 ||
 731                                     nxgep->mac.portmode == PORT_10G_FIBER)
 732                                         size += sizeof (lb_phy10g);
 733                         }
 734                         if (nxgep->mac.portmode == PORT_10G_FIBER ||
 735                             nxgep->mac.portmode == PORT_10G_TN1010 ||
 736                             nxgep->mac.portmode == PORT_10G_SERDES)
 737                                 size += sizeof (lb_serdes10g);
 738 
 739                         if (nxgep->statsp->mac_stats.cap_1000fdx) {
 740                                 /* TN1010 does not support external loopback */
 741                                 if (nxgep->mac.portmode != PORT_1G_TN1010 &&
 742                                     nxgep->mac.portmode != PORT_10G_TN1010) {
 743                                         size += sizeof (lb_external1000);
 744                                 }
 745                                 size += sizeof (lb_mac1000);
 746                                 if (nxgep->mac.portmode == PORT_1G_COPPER ||
 747                                     nxgep->mac.portmode == PORT_1G_TN1010 ||
 748                                     nxgep->mac.portmode ==
 749                                     PORT_1G_RGMII_FIBER)
 750                                         size += sizeof (lb_phy1000);
 751                         }
 752                         if (nxgep->statsp->mac_stats.cap_100fdx)
 753                                 size += sizeof (lb_external100);
 754 
 755                         if (nxgep->statsp->mac_stats.cap_10fdx)
 756                                 size += sizeof (lb_external10);
 757 
 758                         if (nxgep->mac.portmode == PORT_1G_FIBER ||
 759                             nxgep->mac.portmode == PORT_1G_TN1010 ||
 760                             nxgep->mac.portmode == PORT_1G_SERDES)
 761                                 size += sizeof (lb_serdes1000);
 762 
 763                         NXGE_DEBUG_MSG((nxgep, IOC_CTL,
 764                             "NXGE_GET_LB_INFO command: size %d", size));
 765                         if (size == iocp->ioc_count) {
 766                                 i = 0;
 767                                 lb_props = (p_lb_property_t)mp->b_cont->b_rptr;
 768                                 lb_props[i++] = lb_normal;
 769 
 770                                 if (nxgep->statsp->mac_stats.cap_10gfdx) {
 771                                         lb_props[i++] = lb_mac10g;
 772                                         if (nxgep->mac.portmode ==
 773                                             PORT_10G_COPPER ||
 774                                             nxgep->mac.portmode ==
 775                                             PORT_10G_TN1010 ||
 776                                             nxgep->mac.portmode ==
 777                                             PORT_10G_FIBER) {
 778                                                 lb_props[i++] = lb_phy10g;
 779                                         }
 780                                         /* TN1010 does not support ext lb */
 781                                         if (nxgep->mac.portmode !=
 782                                             PORT_10G_TN1010 &&
 783                                             nxgep->mac.portmode !=
 784                                             PORT_1G_TN1010) {
 785                                                 lb_props[i++] = lb_external10g;
 786                                         }
 787                                 }
 788 
 789                                 if (nxgep->mac.portmode == PORT_10G_FIBER ||
 790                                     nxgep->mac.portmode == PORT_10G_TN1010 ||
 791                                     nxgep->mac.portmode == PORT_10G_SERDES)
 792                                         lb_props[i++] = lb_serdes10g;
 793 
 794                                 if (nxgep->statsp->mac_stats.cap_1000fdx) {
 795                                         /* TN1010 does not support ext lb */
 796                                         if (nxgep->mac.portmode !=
 797                                             PORT_10G_TN1010 &&
 798                                             nxgep->mac.portmode !=
 799                                             PORT_1G_TN1010) {
 800                                                 lb_props[i++] = lb_external1000;
 801                                         }
 802                                 }
 803 
 804                                 if (nxgep->statsp->mac_stats.cap_100fdx)
 805                                         lb_props[i++] = lb_external100;
 806 
 807                                 if (nxgep->statsp->mac_stats.cap_10fdx)
 808                                         lb_props[i++] = lb_external10;
 809 
 810                                 if (nxgep->statsp->mac_stats.cap_1000fdx)
 811                                         lb_props[i++] = lb_mac1000;
 812 
 813                                 if (nxgep->mac.portmode == PORT_1G_COPPER ||
 814                                     nxgep->mac.portmode == PORT_1G_TN1010 ||
 815                                     nxgep->mac.portmode ==
 816                                     PORT_1G_RGMII_FIBER) {
 817                                         if (nxgep->statsp->mac_stats.
 818                                             cap_1000fdx)
 819                                                 lb_props[i++] = lb_phy1000;
 820                                 } else if (nxgep->mac.portmode ==
 821                                     PORT_1G_FIBER ||
 822                                     nxgep->mac.portmode == PORT_1G_TN1010 ||
 823                                     nxgep->mac.portmode == PORT_1G_SERDES) {
 824                                         lb_props[i++] = lb_serdes1000;
 825                                 }
 826                                 miocack(wq, mp, size, 0);
 827                         } else
 828                                 miocnak(wq, mp, 0, EINVAL);
 829                 } else {
 830                         miocnak(wq, mp, 0, EINVAL);
 831                         cmn_err(CE_NOTE, "!nxge_hw_ioctl: invalid command 0x%x",
 832                             iocp->ioc_cmd);
 833                 }
 834                 break;
 835         }
 836 }
 837 
 838 /*
 839  * DMA channel interfaces to access various channel specific
 840  * hardware functions.
 841  */
 842 /* ARGSUSED */
 843 void
 844 nxge_rxdma_channel_put64(nxge_os_acc_handle_t handle, void *reg_addrp,
 845         uint32_t reg_base, uint16_t channel, uint64_t reg_data)
 846 {
 847         uint64_t reg_offset;
 848 
 849         NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
 850 
 851         /*
 852          * Channel is assumed to be from 0 to the maximum DMA channel #. If we
 853          * use the virtual DMA CSR address space from the config space (in PCI
 854          * case), then the following code need to be use different offset
 855          * computation macro.
 856          */
 857         reg_offset = reg_base + DMC_OFFSET(channel);
 858         NXGE_PIO_WRITE64(handle, reg_addrp, reg_offset, reg_data);
 859 
 860         NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_put64"));
 861 }
 862 
 863 /* ARGSUSED */
 864 uint64_t
 865 nxge_rxdma_channel_get64(nxge_os_acc_handle_t handle, void *reg_addrp,
 866         uint32_t reg_base, uint16_t channel)
 867 {
 868         uint64_t reg_offset;
 869 
 870         NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
 871 
 872         /*
 873          * Channel is assumed to be from 0 to the maximum DMA channel #. If we
 874          * use the virtual DMA CSR address space from the config space (in PCI
 875          * case), then the following code need to be use different offset
 876          * computation macro.
 877          */
 878         reg_offset = reg_base + DMC_OFFSET(channel);
 879 
 880         NXGE_DEBUG_MSG((NULL, DMA_CTL, "<== nxge_rxdma_channel_get64"));
 881 
 882         return (NXGE_PIO_READ64(handle, reg_addrp, reg_offset));
 883 }
 884 
 885 /* ARGSUSED */
 886 void
 887 nxge_get32(p_nxge_t nxgep, p_mblk_t mp)
 888 {
 889         nxge_os_acc_handle_t nxge_regh;
 890 
 891         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
 892         nxge_regh = nxgep->dev_regs->nxge_regh;
 893 
 894         *(uint32_t *)mp->b_rptr = NXGE_PIO_READ32(nxge_regh,
 895             nxgep->dev_regs->nxge_regp, *(uint32_t *)mp->b_rptr);
 896 
 897         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "value = 0x%08X",
 898             *(uint32_t *)mp->b_rptr));
 899         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_get32"));
 900 }
 901 
 902 /* ARGSUSED */
 903 void
 904 nxge_put32(p_nxge_t nxgep, p_mblk_t mp)
 905 {
 906         nxge_os_acc_handle_t nxge_regh;
 907         uint32_t *buf;
 908         uint8_t *reg;
 909 
 910         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
 911         nxge_regh = nxgep->dev_regs->nxge_regh;
 912 
 913         buf = (uint32_t *)mp->b_rptr;
 914         reg = (uint8_t *)(nxgep->dev_regs->nxge_regp) + buf[0];
 915         NXGE_DEBUG_MSG((nxgep, IOC_CTL,
 916             "reg = 0x%016llX index = 0x%08X value = 0x%08X",
 917             reg, buf[0], buf[1]));
 918         NXGE_PIO_WRITE32(nxge_regh, (uint32_t *)reg, 0, buf[1]);
 919         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "nxge_put32"));
 920 }
 921 
 922 /*ARGSUSED*/
 923 boolean_t
 924 nxge_set_lb(p_nxge_t nxgep, queue_t *wq, p_mblk_t mp)
 925 {
 926         boolean_t status = B_TRUE;
 927         uint32_t lb_mode;
 928         lb_property_t *lb_info;
 929 
 930         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_set_lb"));
 931         lb_mode = nxgep->statsp->port_stats.lb_mode;
 932         if (lb_mode == *(uint32_t *)mp->b_rptr) {
 933                 cmn_err(CE_NOTE,
 934                     "!nxge%d: Loopback mode already set (lb_mode %d).\n",
 935                     nxgep->instance, lb_mode);
 936                 status = B_FALSE;
 937                 goto nxge_set_lb_exit;
 938         }
 939         lb_mode = *(uint32_t *)mp->b_rptr;
 940         lb_info = NULL;
 941         if (lb_mode == lb_normal.value)
 942                 lb_info = &lb_normal;
 943         else if ((lb_mode == lb_external10g.value) &&
 944             (nxgep->statsp->mac_stats.cap_10gfdx))
 945                 lb_info = &lb_external10g;
 946         else if ((lb_mode == lb_external1000.value) &&
 947             (nxgep->statsp->mac_stats.cap_1000fdx))
 948                 lb_info = &lb_external1000;
 949         else if ((lb_mode == lb_external100.value) &&
 950             (nxgep->statsp->mac_stats.cap_100fdx))
 951                 lb_info = &lb_external100;
 952         else if ((lb_mode == lb_external10.value) &&
 953             (nxgep->statsp->mac_stats.cap_10fdx))
 954                 lb_info = &lb_external10;
 955         else if ((lb_mode == lb_phy10g.value) &&
 956             (nxgep->mac.portmode == PORT_10G_COPPER ||
 957             nxgep->mac.portmode == PORT_10G_TN1010 ||
 958             nxgep->mac.portmode == PORT_10G_FIBER))
 959                 lb_info = &lb_phy10g;
 960         else if ((lb_mode == lb_phy1000.value) &&
 961             (nxgep->mac.portmode == PORT_1G_COPPER ||
 962             nxgep->mac.portmode == PORT_1G_TN1010 ||
 963             nxgep->mac.portmode == PORT_1G_RGMII_FIBER))
 964                 lb_info = &lb_phy1000;
 965         else if ((lb_mode == lb_phy.value) &&
 966             (nxgep->mac.portmode == PORT_1G_COPPER))
 967                 lb_info = &lb_phy;
 968         else if ((lb_mode == lb_serdes10g.value) &&
 969             (nxgep->mac.portmode == PORT_10G_FIBER ||
 970             nxgep->mac.portmode == PORT_10G_COPPER ||
 971             nxgep->mac.portmode == PORT_10G_TN1010 ||
 972             nxgep->mac.portmode == PORT_10G_SERDES))
 973                 lb_info = &lb_serdes10g;
 974         else if ((lb_mode == lb_serdes1000.value) &&
 975             (nxgep->mac.portmode == PORT_1G_FIBER ||
 976             nxgep->mac.portmode == PORT_1G_TN1010 ||
 977             nxgep->mac.portmode == PORT_1G_SERDES))
 978                 lb_info = &lb_serdes1000;
 979         else if (lb_mode == lb_mac10g.value)
 980                 lb_info = &lb_mac10g;
 981         else if (lb_mode == lb_mac1000.value)
 982                 lb_info = &lb_mac1000;
 983         else if (lb_mode == lb_mac.value)
 984                 lb_info = &lb_mac;
 985         else {
 986                 cmn_err(CE_NOTE,
 987                     "!nxge%d: Loopback mode not supported(mode %d).\n",
 988                     nxgep->instance, lb_mode);
 989                 status = B_FALSE;
 990                 goto nxge_set_lb_exit;
 991         }
 992 
 993         if (lb_mode == nxge_lb_normal) {
 994                 if (nxge_lb_dbg) {
 995                         cmn_err(CE_NOTE,
 996                             "!nxge%d: Returning to normal operation",
 997                             nxgep->instance);
 998                 }
 999                 if (nxge_set_lb_normal(nxgep) != NXGE_OK) {
1000                         status = B_FALSE;
1001                         cmn_err(CE_NOTE,
1002                             "!nxge%d: Failed to return to normal operation",
1003                             nxgep->instance);
1004                 }
1005                 goto nxge_set_lb_exit;
1006         }
1007         nxgep->statsp->port_stats.lb_mode = lb_mode;
1008 
1009         if (nxge_lb_dbg)
1010                 cmn_err(CE_NOTE,
1011                     "!nxge%d: Adapter now in %s loopback mode",
1012                     nxgep->instance, lb_info->key);
1013         nxgep->param_arr[param_autoneg].value = 0;
1014         nxgep->param_arr[param_anar_10gfdx].value =
1015             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
1016             (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
1017             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
1018             (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g);
1019         nxgep->param_arr[param_anar_10ghdx].value = 0;
1020         nxgep->param_arr[param_anar_1000fdx].value =
1021             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
1022             (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac1000) ||
1023             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
1024             (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000);
1025         nxgep->param_arr[param_anar_1000hdx].value = 0;
1026         nxgep->param_arr[param_anar_100fdx].value =
1027             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy) ||
1028             (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
1029             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100);
1030         nxgep->param_arr[param_anar_100hdx].value = 0;
1031         nxgep->param_arr[param_anar_10fdx].value =
1032             (nxgep->statsp->port_stats.lb_mode == nxge_lb_mac) ||
1033             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10);
1034         if (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) {
1035                 nxgep->param_arr[param_master_cfg_enable].value = 1;
1036                 nxgep->param_arr[param_master_cfg_value].value = 1;
1037         }
1038         if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10g) ||
1039             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
1040             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext100) ||
1041             (nxgep->statsp->port_stats.lb_mode == nxge_lb_ext10) ||
1042             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) ||
1043             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
1044             (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy)) {
1045 
1046                 if (nxge_link_monitor(nxgep, LINK_MONITOR_STOP) != NXGE_OK)
1047                         goto nxge_set_lb_err;
1048                 if (nxge_xcvr_find(nxgep) != NXGE_OK)
1049                         goto nxge_set_lb_err;
1050                 if (nxge_link_init(nxgep) != NXGE_OK)
1051                         goto nxge_set_lb_err;
1052                 if (nxge_link_monitor(nxgep, LINK_MONITOR_START) != NXGE_OK)
1053                         goto nxge_set_lb_err;
1054         }
1055         if (lb_info->lb_type == internal) {
1056                 if ((nxgep->statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
1057                     (nxgep->statsp->port_stats.lb_mode ==
1058                     nxge_lb_phy10g) ||
1059                     (nxgep->statsp->port_stats.lb_mode ==
1060                     nxge_lb_serdes10g)) {
1061                         nxgep->statsp->mac_stats.link_speed = 10000;
1062                 } else if ((nxgep->statsp->port_stats.lb_mode
1063                     == nxge_lb_mac1000) ||
1064                     (nxgep->statsp->port_stats.lb_mode ==
1065                     nxge_lb_phy1000) ||
1066                     (nxgep->statsp->port_stats.lb_mode ==
1067                     nxge_lb_serdes1000)) {
1068                         nxgep->statsp->mac_stats.link_speed = 1000;
1069                 } else {
1070                         nxgep->statsp->mac_stats.link_speed = 100;
1071                 }
1072                 nxgep->statsp->mac_stats.link_duplex = 2;
1073                 nxgep->statsp->mac_stats.link_up = 1;
1074         }
1075         if (nxge_global_reset(nxgep) != NXGE_OK)
1076                 goto nxge_set_lb_err;
1077 
1078 nxge_set_lb_exit:
1079         NXGE_DEBUG_MSG((nxgep, DDI_CTL,
1080             "<== nxge_set_lb status = 0x%08x", status));
1081         return (status);
1082 nxge_set_lb_err:
1083         status = B_FALSE;
1084         cmn_err(CE_NOTE,
1085             "!nxge%d: Failed to put adapter in %s loopback mode",
1086             nxgep->instance, lb_info->key);
1087         return (status);
1088 }
1089 
1090 /* Return to normal (no loopback) mode */
1091 /* ARGSUSED */
1092 nxge_status_t
1093 nxge_set_lb_normal(p_nxge_t nxgep)
1094 {
1095         nxge_status_t   status = NXGE_OK;
1096 
1097         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "==> nxge_set_lb_normal"));
1098 
1099         nxgep->statsp->port_stats.lb_mode = nxge_lb_normal;
1100         nxgep->param_arr[param_autoneg].value =
1101             nxgep->param_arr[param_autoneg].old_value;
1102         nxgep->param_arr[param_anar_1000fdx].value =
1103             nxgep->param_arr[param_anar_1000fdx].old_value;
1104         nxgep->param_arr[param_anar_1000hdx].value =
1105             nxgep->param_arr[param_anar_1000hdx].old_value;
1106         nxgep->param_arr[param_anar_100fdx].value =
1107             nxgep->param_arr[param_anar_100fdx].old_value;
1108         nxgep->param_arr[param_anar_100hdx].value =
1109             nxgep->param_arr[param_anar_100hdx].old_value;
1110         nxgep->param_arr[param_anar_10fdx].value =
1111             nxgep->param_arr[param_anar_10fdx].old_value;
1112         nxgep->param_arr[param_master_cfg_enable].value =
1113             nxgep->param_arr[param_master_cfg_enable].old_value;
1114         nxgep->param_arr[param_master_cfg_value].value =
1115             nxgep->param_arr[param_master_cfg_value].old_value;
1116 
1117         if ((status = nxge_global_reset(nxgep)) != NXGE_OK)
1118                 return (status);
1119 
1120         if ((status = nxge_link_monitor(nxgep, LINK_MONITOR_STOP)) != NXGE_OK)
1121                 return (status);
1122         if ((status = nxge_xcvr_find(nxgep)) != NXGE_OK)
1123                 return (status);
1124         if ((status = nxge_link_init(nxgep)) != NXGE_OK)
1125                 return (status);
1126         status = nxge_link_monitor(nxgep, LINK_MONITOR_START);
1127 
1128         NXGE_DEBUG_MSG((nxgep, DDI_CTL, "<== nxge_set_lb_normal"));
1129 
1130         return (status);
1131 }
1132 
1133 /* ARGSUSED */
1134 void
1135 nxge_get_mii(p_nxge_t nxgep, p_mblk_t mp)
1136 {
1137         uint16_t reg;
1138 
1139         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_get_mii"));
1140 
1141         reg = *(uint16_t *)mp->b_rptr;
1142         (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, reg,
1143             (uint16_t *)mp->b_rptr);
1144         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "reg = 0x%08X value = 0x%04X",
1145             reg, *(uint16_t *)mp->b_rptr));
1146         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_get_mii"));
1147 }
1148 
1149 /* ARGSUSED */
1150 void
1151 nxge_put_mii(p_nxge_t nxgep, p_mblk_t mp)
1152 {
1153         uint16_t *buf;
1154         uint8_t reg;
1155 
1156         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "==> nxge_put_mii"));
1157         buf = (uint16_t *)mp->b_rptr;
1158         reg = (uint8_t)buf[0];
1159         NXGE_DEBUG_MSG((nxgep, IOC_CTL,
1160             "reg = 0x%08X index = 0x%08X value = 0x%08X",
1161             reg, buf[0], buf[1]));
1162         (void) nxge_mii_write(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
1163             reg, buf[1]);
1164         NXGE_DEBUG_MSG((nxgep, IOC_CTL, "<== nxge_put_mii"));
1165 }
1166 
1167 /* ARGSUSED */
1168 void
1169 nxge_check_hw_state(p_nxge_t nxgep)
1170 {
1171         p_nxge_ldgv_t ldgvp;
1172         p_nxge_ldv_t t_ldvp;
1173 
1174         NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "==> nxge_check_hw_state"));
1175 
1176         MUTEX_ENTER(nxgep->genlock);
1177         nxgep->nxge_timerid = 0;
1178         if (!(nxgep->drv_state & STATE_HW_INITIALIZED)) {
1179                 goto nxge_check_hw_state_exit;
1180         }
1181         nxge_check_tx_hang(nxgep);
1182 
1183         ldgvp = nxgep->ldgvp;
1184         if (ldgvp == NULL || (ldgvp->ldvp_syserr == NULL)) {
1185                 NXGE_ERROR_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
1186                     "NULL ldgvp (interrupt not ready)."));
1187                 goto nxge_check_hw_state_exit;
1188         }
1189         t_ldvp = ldgvp->ldvp_syserr;
1190         if (!t_ldvp->use_timer) {
1191                 NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state: "
1192                     "ldgvp $%p t_ldvp $%p use_timer flag %d",
1193                     ldgvp, t_ldvp, t_ldvp->use_timer));
1194                 goto nxge_check_hw_state_exit;
1195         }
1196         if (fm_check_acc_handle(nxgep->dev_regs->nxge_regh) != DDI_FM_OK) {
1197                 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1198                     "port%d Bad register acc handle", nxgep->mac.portnum));
1199         }
1200         (void) nxge_syserr_intr((void *) t_ldvp, (void *) nxgep);
1201 
1202         nxgep->nxge_timerid = nxge_start_timer(nxgep, nxge_check_hw_state,
1203             NXGE_CHECK_TIMER);
1204 
1205 nxge_check_hw_state_exit:
1206         MUTEX_EXIT(nxgep->genlock);
1207         NXGE_DEBUG_MSG((nxgep, SYSERR_CTL, "<== nxge_check_hw_state"));
1208 }
1209 
1210 /*ARGSUSED*/
1211 static void
1212 nxge_rtrace_ioctl(p_nxge_t nxgep, queue_t *wq, mblk_t *mp,
1213         struct iocblk *iocp)
1214 {
1215         ssize_t size;
1216         rtrace_t *rtp;
1217         mblk_t *nmp;
1218         uint32_t i, j;
1219         uint32_t start_blk;
1220         uint32_t base_entry;
1221         uint32_t num_entries;
1222 
1223         NXGE_DEBUG_MSG((nxgep, STR_CTL, "==> nxge_rtrace_ioctl"));
1224 
1225         size = 1024;
1226         if (mp->b_cont == NULL || MBLKL(mp->b_cont) < size) {
1227                 NXGE_DEBUG_MSG((nxgep, STR_CTL,
1228                     "malformed M_IOCTL MBLKL = %d size = %d",
1229                     MBLKL(mp->b_cont), size));
1230                 miocnak(wq, mp, 0, EINVAL);
1231                 return;
1232         }
1233         nmp = mp->b_cont;
1234         rtp = (rtrace_t *)nmp->b_rptr;
1235         start_blk = rtp->next_idx;
1236         num_entries = rtp->last_idx;
1237         base_entry = start_blk * MAX_RTRACE_IOC_ENTRIES;
1238 
1239         NXGE_DEBUG_MSG((nxgep, STR_CTL, "start_blk = %d\n", start_blk));
1240         NXGE_DEBUG_MSG((nxgep, STR_CTL, "num_entries = %d\n", num_entries));
1241         NXGE_DEBUG_MSG((nxgep, STR_CTL, "base_entry = %d\n", base_entry));
1242 
1243         rtp->next_idx = npi_rtracebuf.next_idx;
1244         rtp->last_idx = npi_rtracebuf.last_idx;
1245         rtp->wrapped = npi_rtracebuf.wrapped;
1246         for (i = 0, j = base_entry; i < num_entries; i++, j++) {
1247                 rtp->buf[i].ctl_addr = npi_rtracebuf.buf[j].ctl_addr;
1248                 rtp->buf[i].val_l32 = npi_rtracebuf.buf[j].val_l32;
1249                 rtp->buf[i].val_h32 = npi_rtracebuf.buf[j].val_h32;
1250         }
1251 
1252         nmp->b_wptr = nmp->b_rptr + size;
1253         NXGE_DEBUG_MSG((nxgep, STR_CTL, "<== nxge_rtrace_ioctl"));
1254         miocack(wq, mp, (int)size, 0);
1255 }
--- EOF ---