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 /*
  23  * Copyright(c) 2007-2010 Intel Corporation. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  28  * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
  29  */
  30 
  31 #include "igb_sw.h"
  32 
  33 int
  34 igb_m_stat(void *arg, uint_t stat, uint64_t *val)
  35 {
  36         igb_t *igb = (igb_t *)arg;
  37         struct e1000_hw *hw = &igb->hw;
  38         igb_stat_t *igb_ks;
  39         uint32_t low_val, high_val;
  40 
  41         igb_ks = (igb_stat_t *)igb->igb_ks->ks_data;
  42 
  43         mutex_enter(&igb->gen_lock);
  44 
  45         if (igb->igb_state & IGB_SUSPENDED) {
  46                 mutex_exit(&igb->gen_lock);
  47                 return (ECANCELED);
  48         }
  49 
  50         switch (stat) {
  51         case MAC_STAT_IFSPEED:
  52                 *val = igb->link_speed * 1000000ull;
  53                 break;
  54 
  55         case MAC_STAT_MULTIRCV:
  56                 igb_ks->mprc.value.ui64 +=
  57                     E1000_READ_REG(hw, E1000_MPRC);
  58                 *val = igb_ks->mprc.value.ui64;
  59                 break;
  60 
  61         case MAC_STAT_BRDCSTRCV:
  62                 igb_ks->bprc.value.ui64 +=
  63                     E1000_READ_REG(hw, E1000_BPRC);
  64                 *val = igb_ks->bprc.value.ui64;
  65                 break;
  66 
  67         case MAC_STAT_MULTIXMT:
  68                 igb_ks->mptc.value.ui64 +=
  69                     E1000_READ_REG(hw, E1000_MPTC);
  70                 *val = igb_ks->mptc.value.ui64;
  71                 break;
  72 
  73         case MAC_STAT_BRDCSTXMT:
  74                 igb_ks->bptc.value.ui64 +=
  75                     E1000_READ_REG(hw, E1000_BPTC);
  76                 *val = igb_ks->bptc.value.ui64;
  77                 break;
  78 
  79         case MAC_STAT_NORCVBUF:
  80                 igb_ks->rnbc.value.ui64 +=
  81                     E1000_READ_REG(hw, E1000_RNBC);
  82                 *val = igb_ks->rnbc.value.ui64;
  83                 break;
  84 
  85         case MAC_STAT_IERRORS:
  86                 igb_ks->rxerrc.value.ui64 +=
  87                     E1000_READ_REG(hw, E1000_RXERRC);
  88                 igb_ks->algnerrc.value.ui64 +=
  89                     E1000_READ_REG(hw, E1000_ALGNERRC);
  90                 igb_ks->rlec.value.ui64 +=
  91                     E1000_READ_REG(hw, E1000_RLEC);
  92                 igb_ks->crcerrs.value.ui64 +=
  93                     E1000_READ_REG(hw, E1000_CRCERRS);
  94                 igb_ks->cexterr.value.ui64 +=
  95                     E1000_READ_REG(hw, E1000_CEXTERR);
  96                 *val = igb_ks->rxerrc.value.ui64 +
  97                     igb_ks->algnerrc.value.ui64 +
  98                     igb_ks->rlec.value.ui64 +
  99                     igb_ks->crcerrs.value.ui64 +
 100                     igb_ks->cexterr.value.ui64;
 101                 break;
 102 
 103         case MAC_STAT_NOXMTBUF:
 104                 *val = 0;
 105                 break;
 106 
 107         case MAC_STAT_OERRORS:
 108                 igb_ks->ecol.value.ui64 +=
 109                     E1000_READ_REG(hw, E1000_ECOL);
 110                 *val = igb_ks->ecol.value.ui64;
 111                 break;
 112 
 113         case MAC_STAT_COLLISIONS:
 114                 igb_ks->colc.value.ui64 +=
 115                     E1000_READ_REG(hw, E1000_COLC);
 116                 *val = igb_ks->colc.value.ui64;
 117                 break;
 118 
 119         case MAC_STAT_RBYTES:
 120                 /*
 121                  * The 64-bit register will reset whenever the upper
 122                  * 32 bits are read. So we need to read the lower
 123                  * 32 bits first, then read the upper 32 bits.
 124                  */
 125                 low_val = E1000_READ_REG(hw, E1000_TORL);
 126                 high_val = E1000_READ_REG(hw, E1000_TORH);
 127                 igb_ks->tor.value.ui64 +=
 128                     (uint64_t)high_val << 32 | (uint64_t)low_val;
 129                 *val = igb_ks->tor.value.ui64;
 130                 break;
 131 
 132         case MAC_STAT_IPACKETS:
 133                 igb_ks->tpr.value.ui64 +=
 134                     E1000_READ_REG(hw, E1000_TPR);
 135                 *val = igb_ks->tpr.value.ui64;
 136                 break;
 137 
 138         case MAC_STAT_OBYTES:
 139                 /*
 140                  * The 64-bit register will reset whenever the upper
 141                  * 32 bits are read. So we need to read the lower
 142                  * 32 bits first, then read the upper 32 bits.
 143                  */
 144                 low_val = E1000_READ_REG(hw, E1000_TOTL);
 145                 high_val = E1000_READ_REG(hw, E1000_TOTH);
 146                 igb_ks->tot.value.ui64 +=
 147                     (uint64_t)high_val << 32 | (uint64_t)low_val;
 148                 *val = igb_ks->tot.value.ui64;
 149                 break;
 150 
 151         case MAC_STAT_OPACKETS:
 152                 igb_ks->tpt.value.ui64 +=
 153                     E1000_READ_REG(hw, E1000_TPT);
 154                 *val = igb_ks->tpt.value.ui64;
 155                 break;
 156 
 157         /* RFC 1643 stats */
 158         case ETHER_STAT_ALIGN_ERRORS:
 159                 igb_ks->algnerrc.value.ui64 +=
 160                     E1000_READ_REG(hw, E1000_ALGNERRC);
 161                 *val = igb_ks->algnerrc.value.ui64;
 162                 break;
 163 
 164         case ETHER_STAT_FCS_ERRORS:
 165                 igb_ks->crcerrs.value.ui64 +=
 166                     E1000_READ_REG(hw, E1000_CRCERRS);
 167                 *val = igb_ks->crcerrs.value.ui64;
 168                 break;
 169 
 170         case ETHER_STAT_FIRST_COLLISIONS:
 171                 igb_ks->scc.value.ui64 +=
 172                     E1000_READ_REG(hw, E1000_SCC);
 173                 *val = igb_ks->scc.value.ui64;
 174                 break;
 175 
 176         case ETHER_STAT_MULTI_COLLISIONS:
 177                 igb_ks->mcc.value.ui64 +=
 178                     E1000_READ_REG(hw, E1000_MCC);
 179                 *val = igb_ks->mcc.value.ui64;
 180                 break;
 181 
 182         case ETHER_STAT_SQE_ERRORS:
 183                 igb_ks->sec.value.ui64 +=
 184                     E1000_READ_REG(hw, E1000_SEC);
 185                 *val = igb_ks->sec.value.ui64;
 186                 break;
 187 
 188         case ETHER_STAT_DEFER_XMTS:
 189                 igb_ks->dc.value.ui64 +=
 190                     E1000_READ_REG(hw, E1000_DC);
 191                 *val = igb_ks->dc.value.ui64;
 192                 break;
 193 
 194         case ETHER_STAT_TX_LATE_COLLISIONS:
 195                 igb_ks->latecol.value.ui64 +=
 196                     E1000_READ_REG(hw, E1000_LATECOL);
 197                 *val = igb_ks->latecol.value.ui64;
 198                 break;
 199 
 200         case ETHER_STAT_EX_COLLISIONS:
 201                 igb_ks->ecol.value.ui64 +=
 202                     E1000_READ_REG(hw, E1000_ECOL);
 203                 *val = igb_ks->ecol.value.ui64;
 204                 break;
 205 
 206         case ETHER_STAT_MACXMT_ERRORS:
 207                 igb_ks->ecol.value.ui64 +=
 208                     E1000_READ_REG(hw, E1000_ECOL);
 209                 *val = igb_ks->ecol.value.ui64;
 210                 break;
 211 
 212         case ETHER_STAT_CARRIER_ERRORS:
 213                 igb_ks->cexterr.value.ui64 +=
 214                     E1000_READ_REG(hw, E1000_CEXTERR);
 215                 *val = igb_ks->cexterr.value.ui64;
 216                 break;
 217 
 218         case ETHER_STAT_TOOLONG_ERRORS:
 219                 igb_ks->roc.value.ui64 +=
 220                     E1000_READ_REG(hw, E1000_ROC);
 221                 *val = igb_ks->roc.value.ui64;
 222                 break;
 223 
 224         case ETHER_STAT_MACRCV_ERRORS:
 225                 igb_ks->rxerrc.value.ui64 +=
 226                     E1000_READ_REG(hw, E1000_RXERRC);
 227                 *val = igb_ks->rxerrc.value.ui64;
 228                 break;
 229 
 230         /* MII/GMII stats */
 231         case ETHER_STAT_XCVR_ADDR:
 232                 /* The Internal PHY's MDI address for each MAC is 1 */
 233                 *val = 1;
 234                 break;
 235 
 236         case ETHER_STAT_XCVR_ID:
 237                 *val = hw->phy.id | hw->phy.revision;
 238                 break;
 239 
 240         case ETHER_STAT_XCVR_INUSE:
 241                 switch (igb->link_speed) {
 242                 case SPEED_1000:
 243                         *val =
 244                             (hw->phy.media_type == e1000_media_type_copper) ?
 245                             XCVR_1000T : XCVR_1000X;
 246                         break;
 247                 case SPEED_100:
 248                         *val =
 249                             (hw->phy.media_type == e1000_media_type_copper) ?
 250                             (igb->param_100t4_cap == 1) ?
 251                             XCVR_100T4 : XCVR_100T2 : XCVR_100X;
 252                         break;
 253                 case SPEED_10:
 254                         *val = XCVR_10;
 255                         break;
 256                 default:
 257                         *val = XCVR_NONE;
 258                         break;
 259                 }
 260                 break;
 261 
 262         case ETHER_STAT_CAP_1000FDX:
 263                 *val = igb->param_1000fdx_cap;
 264                 break;
 265 
 266         case ETHER_STAT_CAP_1000HDX:
 267                 *val = igb->param_1000hdx_cap;
 268                 break;
 269 
 270         case ETHER_STAT_CAP_100FDX:
 271                 *val = igb->param_100fdx_cap;
 272                 break;
 273 
 274         case ETHER_STAT_CAP_100HDX:
 275                 *val = igb->param_100hdx_cap;
 276                 break;
 277 
 278         case ETHER_STAT_CAP_10FDX:
 279                 *val = igb->param_10fdx_cap;
 280                 break;
 281 
 282         case ETHER_STAT_CAP_10HDX:
 283                 *val = igb->param_10hdx_cap;
 284                 break;
 285 
 286         case ETHER_STAT_CAP_ASMPAUSE:
 287                 *val = igb->param_asym_pause_cap;
 288                 break;
 289 
 290         case ETHER_STAT_CAP_PAUSE:
 291                 *val = igb->param_pause_cap;
 292                 break;
 293 
 294         case ETHER_STAT_CAP_AUTONEG:
 295                 *val = igb->param_autoneg_cap;
 296                 break;
 297 
 298         case ETHER_STAT_ADV_CAP_1000FDX:
 299                 *val = igb->param_adv_1000fdx_cap;
 300                 break;
 301 
 302         case ETHER_STAT_ADV_CAP_1000HDX:
 303                 *val = igb->param_adv_1000hdx_cap;
 304                 break;
 305 
 306         case ETHER_STAT_ADV_CAP_100FDX:
 307                 *val = igb->param_adv_100fdx_cap;
 308                 break;
 309 
 310         case ETHER_STAT_ADV_CAP_100HDX:
 311                 *val = igb->param_adv_100hdx_cap;
 312                 break;
 313 
 314         case ETHER_STAT_ADV_CAP_10FDX:
 315                 *val = igb->param_adv_10fdx_cap;
 316                 break;
 317 
 318         case ETHER_STAT_ADV_CAP_10HDX:
 319                 *val = igb->param_adv_10hdx_cap;
 320                 break;
 321 
 322         case ETHER_STAT_ADV_CAP_ASMPAUSE:
 323                 *val = igb->param_adv_asym_pause_cap;
 324                 break;
 325 
 326         case ETHER_STAT_ADV_CAP_PAUSE:
 327                 *val = igb->param_adv_pause_cap;
 328                 break;
 329 
 330         case ETHER_STAT_ADV_CAP_AUTONEG:
 331                 *val = hw->mac.autoneg;
 332                 break;
 333 
 334         case ETHER_STAT_LP_CAP_1000FDX:
 335                 *val = igb->param_lp_1000fdx_cap;
 336                 break;
 337 
 338         case ETHER_STAT_LP_CAP_1000HDX:
 339                 *val = igb->param_lp_1000hdx_cap;
 340                 break;
 341 
 342         case ETHER_STAT_LP_CAP_100FDX:
 343                 *val = igb->param_lp_100fdx_cap;
 344                 break;
 345 
 346         case ETHER_STAT_LP_CAP_100HDX:
 347                 *val = igb->param_lp_100hdx_cap;
 348                 break;
 349 
 350         case ETHER_STAT_LP_CAP_10FDX:
 351                 *val = igb->param_lp_10fdx_cap;
 352                 break;
 353 
 354         case ETHER_STAT_LP_CAP_10HDX:
 355                 *val = igb->param_lp_10hdx_cap;
 356                 break;
 357 
 358         case ETHER_STAT_LP_CAP_ASMPAUSE:
 359                 *val = igb->param_lp_asym_pause_cap;
 360                 break;
 361 
 362         case ETHER_STAT_LP_CAP_PAUSE:
 363                 *val = igb->param_lp_pause_cap;
 364                 break;
 365 
 366         case ETHER_STAT_LP_CAP_AUTONEG:
 367                 *val = igb->param_lp_autoneg_cap;
 368                 break;
 369 
 370         case ETHER_STAT_LINK_ASMPAUSE:
 371                 *val = igb->param_asym_pause_cap;
 372                 break;
 373 
 374         case ETHER_STAT_LINK_PAUSE:
 375                 *val = igb->param_pause_cap;
 376                 break;
 377 
 378         case ETHER_STAT_LINK_AUTONEG:
 379                 *val = hw->mac.autoneg;
 380                 break;
 381 
 382         case ETHER_STAT_LINK_DUPLEX:
 383                 *val = (igb->link_duplex == FULL_DUPLEX) ?
 384                     LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
 385                 break;
 386 
 387         case ETHER_STAT_TOOSHORT_ERRORS:
 388                 igb_ks->ruc.value.ui64 +=
 389                     E1000_READ_REG(hw, E1000_RUC);
 390                 *val = igb_ks->ruc.value.ui64;
 391                 break;
 392 
 393         case ETHER_STAT_CAP_REMFAULT:
 394                 *val = igb->param_rem_fault;
 395                 break;
 396 
 397         case ETHER_STAT_ADV_REMFAULT:
 398                 *val = igb->param_adv_rem_fault;
 399                 break;
 400 
 401         case ETHER_STAT_LP_REMFAULT:
 402                 *val = igb->param_lp_rem_fault;
 403                 break;
 404 
 405         case ETHER_STAT_JABBER_ERRORS:
 406                 igb_ks->rjc.value.ui64 +=
 407                     E1000_READ_REG(hw, E1000_RJC);
 408                 *val = igb_ks->rjc.value.ui64;
 409                 break;
 410 
 411         case ETHER_STAT_CAP_100T4:
 412                 *val = igb->param_100t4_cap;
 413                 break;
 414 
 415         case ETHER_STAT_ADV_CAP_100T4:
 416                 *val = igb->param_adv_100t4_cap;
 417                 break;
 418 
 419         case ETHER_STAT_LP_CAP_100T4:
 420                 *val = igb->param_lp_100t4_cap;
 421                 break;
 422 
 423         default:
 424                 mutex_exit(&igb->gen_lock);
 425                 return (ENOTSUP);
 426         }
 427 
 428         mutex_exit(&igb->gen_lock);
 429 
 430         if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
 431                 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
 432                 return (EIO);
 433         }
 434 
 435         return (0);
 436 }
 437 
 438 /*
 439  * Bring the device out of the reset/quiesced state that it
 440  * was in when the interface was registered.
 441  */
 442 int
 443 igb_m_start(void *arg)
 444 {
 445         igb_t *igb = (igb_t *)arg;
 446 
 447         mutex_enter(&igb->gen_lock);
 448 
 449         if (igb->igb_state & IGB_SUSPENDED) {
 450                 mutex_exit(&igb->gen_lock);
 451                 return (ECANCELED);
 452         }
 453 
 454         if (igb_start(igb, B_TRUE) != IGB_SUCCESS) {
 455                 mutex_exit(&igb->gen_lock);
 456                 return (EIO);
 457         }
 458 
 459         atomic_or_32(&igb->igb_state, IGB_STARTED);
 460 
 461         mutex_exit(&igb->gen_lock);
 462 
 463         /*
 464          * Enable and start the watchdog timer
 465          */
 466         igb_enable_watchdog_timer(igb);
 467 
 468         return (0);
 469 }
 470 
 471 /*
 472  * Stop the device and put it in a reset/quiesced state such
 473  * that the interface can be unregistered.
 474  */
 475 void
 476 igb_m_stop(void *arg)
 477 {
 478         igb_t *igb = (igb_t *)arg;
 479 
 480         mutex_enter(&igb->gen_lock);
 481 
 482         if (igb->igb_state & IGB_SUSPENDED) {
 483                 mutex_exit(&igb->gen_lock);
 484                 return;
 485         }
 486 
 487         atomic_and_32(&igb->igb_state, ~IGB_STARTED);
 488 
 489         igb_stop(igb, B_TRUE);
 490 
 491         mutex_exit(&igb->gen_lock);
 492 
 493         /*
 494          * Disable and stop the watchdog timer
 495          */
 496         igb_disable_watchdog_timer(igb);
 497 }
 498 
 499 /*
 500  * Set the promiscuity of the device.
 501  */
 502 int
 503 igb_m_promisc(void *arg, boolean_t on)
 504 {
 505         igb_t *igb = (igb_t *)arg;
 506         uint32_t reg_val;
 507 
 508         mutex_enter(&igb->gen_lock);
 509 
 510         if (igb->igb_state & IGB_SUSPENDED) {
 511                 mutex_exit(&igb->gen_lock);
 512                 return (ECANCELED);
 513         }
 514 
 515         reg_val = E1000_READ_REG(&igb->hw, E1000_RCTL);
 516 
 517         if (on)
 518                 reg_val |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
 519         else
 520                 reg_val &= (~(E1000_RCTL_UPE | E1000_RCTL_MPE));
 521 
 522         E1000_WRITE_REG(&igb->hw, E1000_RCTL, reg_val);
 523 
 524         mutex_exit(&igb->gen_lock);
 525 
 526         if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
 527                 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
 528                 return (EIO);
 529         }
 530 
 531         return (0);
 532 }
 533 
 534 /*
 535  * Add/remove the addresses to/from the set of multicast
 536  * addresses for which the device will receive packets.
 537  */
 538 int
 539 igb_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr)
 540 {
 541         igb_t *igb = (igb_t *)arg;
 542         int result;
 543 
 544         mutex_enter(&igb->gen_lock);
 545 
 546         if (igb->igb_state & IGB_SUSPENDED) {
 547                 mutex_exit(&igb->gen_lock);
 548                 return (ECANCELED);
 549         }
 550 
 551         result = (add) ? igb_multicst_add(igb, mcst_addr)
 552             : igb_multicst_remove(igb, mcst_addr);
 553 
 554         mutex_exit(&igb->gen_lock);
 555 
 556         return (result);
 557 }
 558 
 559 /*
 560  * Pass on M_IOCTL messages passed to the DLD, and support
 561  * private IOCTLs for debugging and ndd.
 562  */
 563 void
 564 igb_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
 565 {
 566         igb_t *igb = (igb_t *)arg;
 567         struct iocblk *iocp;
 568         enum ioc_reply status;
 569 
 570         iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
 571         iocp->ioc_error = 0;
 572 
 573         mutex_enter(&igb->gen_lock);
 574         if (igb->igb_state & IGB_SUSPENDED) {
 575                 mutex_exit(&igb->gen_lock);
 576                 miocnak(q, mp, 0, EINVAL);
 577                 return;
 578         }
 579         mutex_exit(&igb->gen_lock);
 580 
 581         switch (iocp->ioc_cmd) {
 582         case LB_GET_INFO_SIZE:
 583         case LB_GET_INFO:
 584         case LB_GET_MODE:
 585         case LB_SET_MODE:
 586                 status = igb_loopback_ioctl(igb, iocp, mp);
 587                 break;
 588 
 589         default:
 590                 status = IOC_INVAL;
 591                 break;
 592         }
 593 
 594         /*
 595          * Decide how to reply
 596          */
 597         switch (status) {
 598         default:
 599         case IOC_INVAL:
 600                 /*
 601                  * Error, reply with a NAK and EINVAL or the specified error
 602                  */
 603                 miocnak(q, mp, 0, iocp->ioc_error == 0 ?
 604                     EINVAL : iocp->ioc_error);
 605                 break;
 606 
 607         case IOC_DONE:
 608                 /*
 609                  * OK, reply already sent
 610                  */
 611                 break;
 612 
 613         case IOC_ACK:
 614                 /*
 615                  * OK, reply with an ACK
 616                  */
 617                 miocack(q, mp, 0, 0);
 618                 break;
 619 
 620         case IOC_REPLY:
 621                 /*
 622                  * OK, send prepared reply as ACK or NAK
 623                  */
 624                 mp->b_datap->db_type = iocp->ioc_error == 0 ?
 625                     M_IOCACK : M_IOCNAK;
 626                 qreply(q, mp);
 627                 break;
 628         }
 629 }
 630 
 631 /*
 632  * Add a MAC address to the target RX group.
 633  */
 634 static int
 635 igb_addmac(void *arg, const uint8_t *mac_addr)
 636 {
 637         igb_rx_group_t *rx_group = (igb_rx_group_t *)arg;
 638         igb_t *igb = rx_group->igb;
 639         struct e1000_hw *hw = &igb->hw;
 640         int i, slot;
 641 
 642         mutex_enter(&igb->gen_lock);
 643 
 644         if (igb->igb_state & IGB_SUSPENDED) {
 645                 mutex_exit(&igb->gen_lock);
 646                 return (ECANCELED);
 647         }
 648 
 649         if (igb->unicst_avail == 0) {
 650                 /* no slots available */
 651                 mutex_exit(&igb->gen_lock);
 652                 return (ENOSPC);
 653         }
 654 
 655         /*
 656          * The slots from 0 to igb->num_rx_groups are reserved slots which
 657          * are 1 to 1 mapped with group index directly. The other slots are
 658          * shared between the all of groups. While adding a MAC address,
 659          * it will try to set the reserved slots first, then the shared slots.
 660          */
 661         slot = -1;
 662         if (igb->unicst_addr[rx_group->index].mac.set == 1) {
 663                 /*
 664                  * The reserved slot for current group is used, find the free
 665                  * slots in the shared slots.
 666                  */
 667                 for (i = igb->num_rx_groups; i < igb->unicst_total; i++) {
 668                         if (igb->unicst_addr[i].mac.set == 0) {
 669                                 slot = i;
 670                                 break;
 671                         }
 672                 }
 673         } else
 674                 slot = rx_group->index;
 675 
 676         if (slot == -1) {
 677                 /* no slots available in the shared slots */
 678                 mutex_exit(&igb->gen_lock);
 679                 return (ENOSPC);
 680         }
 681 
 682         /* Set VMDq according to the mode supported by hardware. */
 683         e1000_rar_set_vmdq(hw, mac_addr, slot, igb->vmdq_mode, rx_group->index);
 684 
 685         bcopy(mac_addr, igb->unicst_addr[slot].mac.addr, ETHERADDRL);
 686         igb->unicst_addr[slot].mac.group_index = rx_group->index;
 687         igb->unicst_addr[slot].mac.set = 1;
 688         igb->unicst_avail--;
 689 
 690         mutex_exit(&igb->gen_lock);
 691 
 692         return (0);
 693 }
 694 
 695 /*
 696  * Remove a MAC address from the specified RX group.
 697  */
 698 static int
 699 igb_remmac(void *arg, const uint8_t *mac_addr)
 700 {
 701         igb_rx_group_t *rx_group = (igb_rx_group_t *)arg;
 702         igb_t *igb = rx_group->igb;
 703         struct e1000_hw *hw = &igb->hw;
 704         int slot;
 705 
 706         mutex_enter(&igb->gen_lock);
 707 
 708         if (igb->igb_state & IGB_SUSPENDED) {
 709                 mutex_exit(&igb->gen_lock);
 710                 return (ECANCELED);
 711         }
 712 
 713         slot = igb_unicst_find(igb, mac_addr);
 714         if (slot == -1) {
 715                 mutex_exit(&igb->gen_lock);
 716                 return (EINVAL);
 717         }
 718 
 719         if (igb->unicst_addr[slot].mac.set == 0) {
 720                 mutex_exit(&igb->gen_lock);
 721                 return (EINVAL);
 722         }
 723 
 724         /* Clear the MAC ddress in the slot */
 725         e1000_rar_clear(hw, slot);
 726         igb->unicst_addr[slot].mac.set = 0;
 727         igb->unicst_avail++;
 728 
 729         mutex_exit(&igb->gen_lock);
 730 
 731         return (0);
 732 }
 733 
 734 /*
 735  * Enable interrupt on the specificed rx ring.
 736  */
 737 int
 738 igb_rx_ring_intr_enable(mac_intr_handle_t intrh)
 739 {
 740         igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh;
 741         igb_t *igb = rx_ring->igb;
 742         struct e1000_hw *hw = &igb->hw;
 743         uint32_t index = rx_ring->index;
 744 
 745         if (igb->intr_type == DDI_INTR_TYPE_MSIX) {
 746                 /* Interrupt enabling for MSI-X */
 747                 igb->eims_mask |= (E1000_EICR_RX_QUEUE0 << index);
 748                 E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask);
 749                 E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask);
 750         } else {
 751                 ASSERT(index == 0);
 752                 /* Interrupt enabling for MSI and legacy */
 753                 igb->ims_mask |= E1000_IMS_RXT0;
 754                 E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask);
 755         }
 756 
 757         E1000_WRITE_FLUSH(hw);
 758 
 759         return (0);
 760 }
 761 
 762 /*
 763  * Disable interrupt on the specificed rx ring.
 764  */
 765 int
 766 igb_rx_ring_intr_disable(mac_intr_handle_t intrh)
 767 {
 768         igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh;
 769         igb_t *igb = rx_ring->igb;
 770         struct e1000_hw *hw = &igb->hw;
 771         uint32_t index = rx_ring->index;
 772 
 773         if (igb->intr_type == DDI_INTR_TYPE_MSIX) {
 774                 /* Interrupt disabling for MSI-X */
 775                 igb->eims_mask &= ~(E1000_EICR_RX_QUEUE0 << index);
 776                 E1000_WRITE_REG(hw, E1000_EIMC,
 777                     (E1000_EICR_RX_QUEUE0 << index));
 778                 E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask);
 779         } else {
 780                 ASSERT(index == 0);
 781                 /* Interrupt disabling for MSI and legacy */
 782                 igb->ims_mask &= ~E1000_IMS_RXT0;
 783                 E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_RXT0);
 784         }
 785 
 786         E1000_WRITE_FLUSH(hw);
 787 
 788         return (0);
 789 }
 790 
 791 /*
 792  * Get the global ring index by a ring index within a group.
 793  */
 794 int
 795 igb_get_rx_ring_index(igb_t *igb, int gindex, int rindex)
 796 {
 797         igb_rx_ring_t *rx_ring;
 798         int i;
 799 
 800         for (i = 0; i < igb->num_rx_rings; i++) {
 801                 rx_ring = &igb->rx_rings[i];
 802                 if (rx_ring->group_index == gindex)
 803                         rindex--;
 804                 if (rindex < 0)
 805                         return (i);
 806         }
 807 
 808         return (-1);
 809 }
 810 
 811 static int
 812 igb_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
 813 {
 814         igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)rh;
 815 
 816         mutex_enter(&rx_ring->rx_lock);
 817         rx_ring->ring_gen_num = mr_gen_num;
 818         mutex_exit(&rx_ring->rx_lock);
 819         return (0);
 820 }
 821 
 822 /*
 823  * Callback funtion for MAC layer to register all rings.
 824  */
 825 /* ARGSUSED */
 826 void
 827 igb_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
 828     const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
 829 {
 830         igb_t *igb = (igb_t *)arg;
 831         mac_intr_t *mintr = &infop->mri_intr;
 832 
 833         switch (rtype) {
 834         case MAC_RING_TYPE_RX: {
 835                 igb_rx_ring_t *rx_ring;
 836                 int global_index;
 837 
 838                 /*
 839                  * 'index' is the ring index within the group.
 840                  * We need the global ring index by searching in group.
 841                  */
 842                 global_index = igb_get_rx_ring_index(igb, rg_index, index);
 843 
 844                 ASSERT(global_index >= 0);
 845 
 846                 rx_ring = &igb->rx_rings[global_index];
 847                 rx_ring->ring_handle = rh;
 848 
 849                 infop->mri_driver = (mac_ring_driver_t)rx_ring;
 850                 infop->mri_start = igb_ring_start;
 851                 infop->mri_stop = NULL;
 852                 infop->mri_poll = (mac_ring_poll_t)igb_rx_ring_poll;
 853                 infop->mri_stat = igb_rx_ring_stat;
 854 
 855                 mintr->mi_handle = (mac_intr_handle_t)rx_ring;
 856                 mintr->mi_enable = igb_rx_ring_intr_enable;
 857                 mintr->mi_disable = igb_rx_ring_intr_disable;
 858                 if (igb->intr_type & (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
 859                         mintr->mi_ddi_handle =
 860                             igb->htable[rx_ring->intr_vector];
 861                 }
 862                 break;
 863         }
 864         case MAC_RING_TYPE_TX: {
 865                 ASSERT(index < igb->num_tx_rings);
 866 
 867                 igb_tx_ring_t *tx_ring = &igb->tx_rings[index];
 868                 tx_ring->ring_handle = rh;
 869 
 870                 infop->mri_driver = (mac_ring_driver_t)tx_ring;
 871                 infop->mri_start = NULL;
 872                 infop->mri_stop = NULL;
 873                 infop->mri_tx = igb_tx_ring_send;
 874                 infop->mri_stat = igb_tx_ring_stat;
 875                 if (igb->intr_type & (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
 876                         mintr->mi_ddi_handle =
 877                             igb->htable[tx_ring->intr_vector];
 878                 }
 879                 break;
 880         }
 881         default:
 882                 break;
 883         }
 884 }
 885 
 886 void
 887 igb_fill_group(void *arg, mac_ring_type_t rtype, const int index,
 888     mac_group_info_t *infop, mac_group_handle_t gh)
 889 {
 890         igb_t *igb = (igb_t *)arg;
 891 
 892         switch (rtype) {
 893         case MAC_RING_TYPE_RX: {
 894                 igb_rx_group_t *rx_group;
 895 
 896                 ASSERT((index >= 0) && (index < igb->num_rx_groups));
 897 
 898                 rx_group = &igb->rx_groups[index];
 899                 rx_group->group_handle = gh;
 900 
 901                 infop->mgi_driver = (mac_group_driver_t)rx_group;
 902                 infop->mgi_start = NULL;
 903                 infop->mgi_stop = NULL;
 904                 infop->mgi_addmac = igb_addmac;
 905                 infop->mgi_remmac = igb_remmac;
 906                 infop->mgi_count = (igb->num_rx_rings / igb->num_rx_groups);
 907 
 908                 break;
 909         }
 910         case MAC_RING_TYPE_TX:
 911                 break;
 912         default:
 913                 break;
 914         }
 915 }
 916 
 917 /*
 918  * Obtain the MAC's capabilities and associated data from
 919  * the driver.
 920  */
 921 boolean_t
 922 igb_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
 923 {
 924         igb_t *igb = (igb_t *)arg;
 925 
 926         switch (cap) {
 927         case MAC_CAPAB_HCKSUM: {
 928                 uint32_t *tx_hcksum_flags = cap_data;
 929 
 930                 /*
 931                  * We advertise our capabilities only if tx hcksum offload is
 932                  * enabled.  On receive, the stack will accept checksummed
 933                  * packets anyway, even if we haven't said we can deliver
 934                  * them.
 935                  */
 936                 if (!igb->tx_hcksum_enable)
 937                         return (B_FALSE);
 938 
 939                 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
 940                 break;
 941         }
 942         case MAC_CAPAB_LSO: {
 943                 mac_capab_lso_t *cap_lso = cap_data;
 944 
 945                 if (igb->lso_enable) {
 946                         cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
 947                         cap_lso->lso_basic_tcp_ipv4.lso_max = IGB_LSO_MAXLEN;
 948                         break;
 949                 } else {
 950                         return (B_FALSE);
 951                 }
 952         }
 953         case MAC_CAPAB_RINGS: {
 954                 mac_capab_rings_t *cap_rings = cap_data;
 955 
 956                 switch (cap_rings->mr_type) {
 957                 case MAC_RING_TYPE_RX:
 958                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
 959                         cap_rings->mr_rnum = igb->num_rx_rings;
 960                         cap_rings->mr_gnum = igb->num_rx_groups;
 961                         cap_rings->mr_rget = igb_fill_ring;
 962                         cap_rings->mr_gget = igb_fill_group;
 963                         cap_rings->mr_gaddring = NULL;
 964                         cap_rings->mr_gremring = NULL;
 965 
 966                         break;
 967                 case MAC_RING_TYPE_TX:
 968                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
 969                         cap_rings->mr_rnum = igb->num_tx_rings;
 970                         cap_rings->mr_gnum = 0;
 971                         cap_rings->mr_rget = igb_fill_ring;
 972                         cap_rings->mr_gget = NULL;
 973 
 974                         break;
 975                 default:
 976                         break;
 977                 }
 978                 break;
 979         }
 980 
 981         default:
 982                 return (B_FALSE);
 983         }
 984         return (B_TRUE);
 985 }
 986 
 987 int
 988 igb_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 989     uint_t pr_valsize, const void *pr_val)
 990 {
 991         igb_t *igb = (igb_t *)arg;
 992         struct e1000_hw *hw = &igb->hw;
 993         int err = 0;
 994         uint32_t flow_control;
 995         uint32_t cur_mtu, new_mtu;
 996         uint32_t rx_size;
 997         uint32_t tx_size;
 998 
 999         mutex_enter(&igb->gen_lock);
1000         if (igb->igb_state & IGB_SUSPENDED) {
1001                 mutex_exit(&igb->gen_lock);
1002                 return (ECANCELED);
1003         }
1004 
1005         if (igb->loopback_mode != IGB_LB_NONE && igb_param_locked(pr_num)) {
1006                 /*
1007                  * All en_* parameters are locked (read-only)
1008                  * while the device is in any sort of loopback mode.
1009                  */
1010                 mutex_exit(&igb->gen_lock);
1011                 return (EBUSY);
1012         }
1013 
1014         switch (pr_num) {
1015         case MAC_PROP_EN_1000FDX_CAP:
1016                 /* read/write on copper, read-only on serdes */
1017                 if (hw->phy.media_type != e1000_media_type_copper) {
1018                         err = ENOTSUP;
1019                         break;
1020                 }
1021                 igb->param_en_1000fdx_cap = *(uint8_t *)pr_val;
1022                 igb->param_adv_1000fdx_cap = *(uint8_t *)pr_val;
1023                 goto setup_link;
1024         case MAC_PROP_EN_100FDX_CAP:
1025                 if (hw->phy.media_type != e1000_media_type_copper) {
1026                         err = ENOTSUP;
1027                         break;
1028                 }
1029                 igb->param_en_100fdx_cap = *(uint8_t *)pr_val;
1030                 igb->param_adv_100fdx_cap = *(uint8_t *)pr_val;
1031                 goto setup_link;
1032         case MAC_PROP_EN_100HDX_CAP:
1033                 if (hw->phy.media_type != e1000_media_type_copper) {
1034                         err = ENOTSUP;
1035                         break;
1036                 }
1037                 igb->param_en_100hdx_cap = *(uint8_t *)pr_val;
1038                 igb->param_adv_100hdx_cap = *(uint8_t *)pr_val;
1039                 goto setup_link;
1040         case MAC_PROP_EN_10FDX_CAP:
1041                 if (hw->phy.media_type != e1000_media_type_copper) {
1042                         err = ENOTSUP;
1043                         break;
1044                 }
1045                 igb->param_en_10fdx_cap = *(uint8_t *)pr_val;
1046                 igb->param_adv_10fdx_cap = *(uint8_t *)pr_val;
1047                 goto setup_link;
1048         case MAC_PROP_EN_10HDX_CAP:
1049                 if (hw->phy.media_type != e1000_media_type_copper) {
1050                         err = ENOTSUP;
1051                         break;
1052                 }
1053                 igb->param_en_10hdx_cap = *(uint8_t *)pr_val;
1054                 igb->param_adv_10hdx_cap = *(uint8_t *)pr_val;
1055                 goto setup_link;
1056         case MAC_PROP_AUTONEG:
1057                 if (hw->phy.media_type != e1000_media_type_copper) {
1058                         err = ENOTSUP;
1059                         break;
1060                 }
1061                 igb->param_adv_autoneg_cap = *(uint8_t *)pr_val;
1062                 goto setup_link;
1063         case MAC_PROP_FLOWCTRL:
1064                 bcopy(pr_val, &flow_control, sizeof (flow_control));
1065 
1066                 switch (flow_control) {
1067                 default:
1068                         err = EINVAL;
1069                         break;
1070                 case LINK_FLOWCTRL_NONE:
1071                         hw->fc.requested_mode = e1000_fc_none;
1072                         break;
1073                 case LINK_FLOWCTRL_RX:
1074                         hw->fc.requested_mode = e1000_fc_rx_pause;
1075                         break;
1076                 case LINK_FLOWCTRL_TX:
1077                         hw->fc.requested_mode = e1000_fc_tx_pause;
1078                         break;
1079                 case LINK_FLOWCTRL_BI:
1080                         hw->fc.requested_mode = e1000_fc_full;
1081                         break;
1082                 }
1083 setup_link:
1084                 if (err == 0) {
1085                         if (igb_setup_link(igb, B_TRUE) != IGB_SUCCESS)
1086                                 err = EINVAL;
1087                 }
1088                 break;
1089         case MAC_PROP_ADV_1000FDX_CAP:
1090         case MAC_PROP_ADV_1000HDX_CAP:
1091         case MAC_PROP_ADV_100T4_CAP:
1092         case MAC_PROP_ADV_100FDX_CAP:
1093         case MAC_PROP_ADV_100HDX_CAP:
1094         case MAC_PROP_ADV_10FDX_CAP:
1095         case MAC_PROP_ADV_10HDX_CAP:
1096         case MAC_PROP_EN_1000HDX_CAP:
1097         case MAC_PROP_EN_100T4_CAP:
1098         case MAC_PROP_STATUS:
1099         case MAC_PROP_SPEED:
1100         case MAC_PROP_DUPLEX:
1101                 err = ENOTSUP; /* read-only prop. Can't set this. */
1102                 break;
1103         case MAC_PROP_MTU:
1104                 /* adapter must be stopped for an MTU change */
1105                 if (igb->igb_state & IGB_STARTED) {
1106                         err = EBUSY;
1107                         break;
1108                 }
1109 
1110                 cur_mtu = igb->default_mtu;
1111                 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
1112                 if (new_mtu == cur_mtu) {
1113                         err = 0;
1114                         break;
1115                 }
1116 
1117                 if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) {
1118                         err = EINVAL;
1119                         break;
1120                 }
1121 
1122                 err = mac_maxsdu_update(igb->mac_hdl, new_mtu);
1123                 if (err == 0) {
1124                         igb->default_mtu = new_mtu;
1125                         igb->max_frame_size = igb->default_mtu +
1126                             sizeof (struct ether_vlan_header) + ETHERFCSL;
1127 
1128                         /*
1129                          * Set rx buffer size
1130                          */
1131                         rx_size = igb->max_frame_size + IPHDR_ALIGN_ROOM;
1132                         igb->rx_buf_size = ((rx_size >> 10) + ((rx_size &
1133                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
1134 
1135                         /*
1136                          * Set tx buffer size
1137                          */
1138                         tx_size = igb->max_frame_size;
1139                         igb->tx_buf_size = ((tx_size >> 10) + ((tx_size &
1140                             (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
1141                 }
1142                 break;
1143         case MAC_PROP_PRIVATE:
1144                 err = igb_set_priv_prop(igb, pr_name, pr_valsize, pr_val);
1145                 break;
1146         default:
1147                 err = EINVAL;
1148                 break;
1149         }
1150 
1151         mutex_exit(&igb->gen_lock);
1152 
1153         if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
1154                 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
1155                 return (EIO);
1156         }
1157 
1158         return (err);
1159 }
1160 
1161 int
1162 igb_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1163     uint_t pr_valsize, void *pr_val)
1164 {
1165         igb_t *igb = (igb_t *)arg;
1166         struct e1000_hw *hw = &igb->hw;
1167         int err = 0;
1168         uint32_t flow_control;
1169         uint64_t tmp = 0;
1170 
1171         switch (pr_num) {
1172         case MAC_PROP_DUPLEX:
1173                 ASSERT(pr_valsize >= sizeof (link_duplex_t));
1174                 bcopy(&igb->link_duplex, pr_val, sizeof (link_duplex_t));
1175                 break;
1176         case MAC_PROP_SPEED:
1177                 ASSERT(pr_valsize >= sizeof (uint64_t));
1178                 tmp = igb->link_speed * 1000000ull;
1179                 bcopy(&tmp, pr_val, sizeof (tmp));
1180                 break;
1181         case MAC_PROP_AUTONEG:
1182                 ASSERT(pr_valsize >= sizeof (uint8_t));
1183                 *(uint8_t *)pr_val = igb->param_adv_autoneg_cap;
1184                 break;
1185         case MAC_PROP_FLOWCTRL:
1186                 ASSERT(pr_valsize >= sizeof (uint32_t));
1187                 switch (hw->fc.requested_mode) {
1188                         case e1000_fc_none:
1189                                 flow_control = LINK_FLOWCTRL_NONE;
1190                                 break;
1191                         case e1000_fc_rx_pause:
1192                                 flow_control = LINK_FLOWCTRL_RX;
1193                                 break;
1194                         case e1000_fc_tx_pause:
1195                                 flow_control = LINK_FLOWCTRL_TX;
1196                                 break;
1197                         case e1000_fc_full:
1198                                 flow_control = LINK_FLOWCTRL_BI;
1199                                 break;
1200                 }
1201                 bcopy(&flow_control, pr_val, sizeof (flow_control));
1202                 break;
1203         case MAC_PROP_ADV_1000FDX_CAP:
1204                 *(uint8_t *)pr_val = igb->param_adv_1000fdx_cap;
1205                 break;
1206         case MAC_PROP_EN_1000FDX_CAP:
1207                 *(uint8_t *)pr_val = igb->param_en_1000fdx_cap;
1208                 break;
1209         case MAC_PROP_ADV_1000HDX_CAP:
1210                 *(uint8_t *)pr_val = igb->param_adv_1000hdx_cap;
1211                 break;
1212         case MAC_PROP_EN_1000HDX_CAP:
1213                 *(uint8_t *)pr_val = igb->param_en_1000hdx_cap;
1214                 break;
1215         case MAC_PROP_ADV_100T4_CAP:
1216                 *(uint8_t *)pr_val = igb->param_adv_100t4_cap;
1217                 break;
1218         case MAC_PROP_EN_100T4_CAP:
1219                 *(uint8_t *)pr_val = igb->param_en_100t4_cap;
1220                 break;
1221         case MAC_PROP_ADV_100FDX_CAP:
1222                 *(uint8_t *)pr_val = igb->param_adv_100fdx_cap;
1223                 break;
1224         case MAC_PROP_EN_100FDX_CAP:
1225                 *(uint8_t *)pr_val = igb->param_en_100fdx_cap;
1226                 break;
1227         case MAC_PROP_ADV_100HDX_CAP:
1228                 *(uint8_t *)pr_val = igb->param_adv_100hdx_cap;
1229                 break;
1230         case MAC_PROP_EN_100HDX_CAP:
1231                 *(uint8_t *)pr_val = igb->param_en_100hdx_cap;
1232                 break;
1233         case MAC_PROP_ADV_10FDX_CAP:
1234                 *(uint8_t *)pr_val = igb->param_adv_10fdx_cap;
1235                 break;
1236         case MAC_PROP_EN_10FDX_CAP:
1237                 *(uint8_t *)pr_val = igb->param_en_10fdx_cap;
1238                 break;
1239         case MAC_PROP_ADV_10HDX_CAP:
1240                 *(uint8_t *)pr_val = igb->param_adv_10hdx_cap;
1241                 break;
1242         case MAC_PROP_EN_10HDX_CAP:
1243                 *(uint8_t *)pr_val = igb->param_en_10hdx_cap;
1244                 break;
1245         case MAC_PROP_PRIVATE:
1246                 err = igb_get_priv_prop(igb, pr_name, pr_valsize, pr_val);
1247                 break;
1248         default:
1249                 err = EINVAL;
1250                 break;
1251         }
1252         return (err);
1253 }
1254 
1255 void
1256 igb_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1257     mac_prop_info_handle_t prh)
1258 {
1259         igb_t *igb = (igb_t *)arg;
1260         struct e1000_hw *hw = &igb->hw;
1261         uint16_t phy_status, phy_ext_status;
1262 
1263         switch (pr_num) {
1264         case MAC_PROP_DUPLEX:
1265         case MAC_PROP_SPEED:
1266         case MAC_PROP_ADV_1000FDX_CAP:
1267         case MAC_PROP_ADV_1000HDX_CAP:
1268         case MAC_PROP_EN_1000HDX_CAP:
1269         case MAC_PROP_ADV_100T4_CAP:
1270         case MAC_PROP_EN_100T4_CAP:
1271                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1272                 break;
1273 
1274         case MAC_PROP_EN_1000FDX_CAP:
1275                 if (hw->phy.media_type != e1000_media_type_copper) {
1276                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1277                 } else {
1278                         (void) e1000_read_phy_reg(hw, PHY_EXT_STATUS,
1279                             &phy_ext_status);
1280                         mac_prop_info_set_default_uint8(prh,
1281                             ((phy_ext_status & IEEE_ESR_1000T_FD_CAPS) ||
1282                             (phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0);
1283                 }
1284                 break;
1285 
1286         case MAC_PROP_ADV_100FDX_CAP:
1287         case MAC_PROP_EN_100FDX_CAP:
1288                 if (hw->phy.media_type != e1000_media_type_copper) {
1289                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1290                 } else {
1291                         (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1292                         mac_prop_info_set_default_uint8(prh,
1293                             ((phy_status & MII_SR_100X_FD_CAPS) ||
1294                             (phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0);
1295                 }
1296                 break;
1297 
1298         case MAC_PROP_ADV_100HDX_CAP:
1299         case MAC_PROP_EN_100HDX_CAP:
1300                 if (hw->phy.media_type != e1000_media_type_copper) {
1301                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1302                 } else {
1303                         (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1304                         mac_prop_info_set_default_uint8(prh,
1305                             ((phy_status & MII_SR_100X_HD_CAPS) ||
1306                             (phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0);
1307                 }
1308                 break;
1309 
1310         case MAC_PROP_ADV_10FDX_CAP:
1311         case MAC_PROP_EN_10FDX_CAP:
1312                 if (hw->phy.media_type != e1000_media_type_copper) {
1313                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1314                 } else {
1315                         (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1316                         mac_prop_info_set_default_uint8(prh,
1317                             (phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0);
1318                 }
1319                 break;
1320 
1321         case MAC_PROP_ADV_10HDX_CAP:
1322         case MAC_PROP_EN_10HDX_CAP:
1323                 if (hw->phy.media_type != e1000_media_type_copper) {
1324                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1325                 } else {
1326                         (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1327                         mac_prop_info_set_default_uint8(prh,
1328                             (phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0);
1329                 }
1330                 break;
1331 
1332         case MAC_PROP_AUTONEG:
1333                 if (hw->phy.media_type != e1000_media_type_copper) {
1334                         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1335                 } else {
1336                         (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1337                         mac_prop_info_set_default_uint8(prh,
1338                             (phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0);
1339                 }
1340                 break;
1341 
1342         case MAC_PROP_FLOWCTRL:
1343                 mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_BI);
1344                 break;
1345 
1346         case MAC_PROP_MTU:
1347                 mac_prop_info_set_range_uint32(prh, MIN_MTU, MAX_MTU);
1348                 break;
1349 
1350         case MAC_PROP_PRIVATE:
1351                 igb_priv_prop_info(igb, pr_name, prh);
1352                 break;
1353         }
1354 
1355 }
1356 
1357 boolean_t
1358 igb_param_locked(mac_prop_id_t pr_num)
1359 {
1360         /*
1361          * All en_* parameters are locked (read-only) while
1362          * the device is in any sort of loopback mode ...
1363          */
1364         switch (pr_num) {
1365                 case MAC_PROP_EN_1000FDX_CAP:
1366                 case MAC_PROP_EN_1000HDX_CAP:
1367                 case MAC_PROP_EN_100T4_CAP:
1368                 case MAC_PROP_EN_100FDX_CAP:
1369                 case MAC_PROP_EN_100HDX_CAP:
1370                 case MAC_PROP_EN_10FDX_CAP:
1371                 case MAC_PROP_EN_10HDX_CAP:
1372                 case MAC_PROP_AUTONEG:
1373                 case MAC_PROP_FLOWCTRL:
1374                         return (B_TRUE);
1375         }
1376         return (B_FALSE);
1377 }
1378 
1379 /* ARGSUSED */
1380 int
1381 igb_set_priv_prop(igb_t *igb, const char *pr_name,
1382     uint_t pr_valsize, const void *pr_val)
1383 {
1384         int err = 0;
1385         long result;
1386         struct e1000_hw *hw = &igb->hw;
1387         int i;
1388 
1389         if (strcmp(pr_name, "_eee_support") == 0) {
1390                 if (pr_val == NULL)
1391                         return (EINVAL);
1392                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1393                 switch (result) {
1394                 case 0:
1395                 case 1:
1396                         if (hw->mac.type != e1000_i350) {
1397                                 /*
1398                                  * For now, only supported on I350.
1399                                  * Add new mac.type values (or use < instead)
1400                                  * as new cards offer up EEE.
1401                                  */
1402                                 return (ENXIO);
1403                         }
1404                         /* Must set this prior to the set call. */
1405                         hw->dev_spec._82575.eee_disable = !result;
1406                         if (e1000_set_eee_i350(hw) != E1000_SUCCESS)
1407                                 err = EIO;
1408                         break;
1409                 default:
1410                         err = EINVAL;
1411                         /* FALLTHRU */
1412                 }
1413                 return (err);
1414         }
1415         if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1416                 if (pr_val == NULL) {
1417                         err = EINVAL;
1418                         return (err);
1419                 }
1420                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1421                 if (result < MIN_TX_COPY_THRESHOLD ||
1422                     result > MAX_TX_COPY_THRESHOLD)
1423                         err = EINVAL;
1424                 else {
1425                         igb->tx_copy_thresh = (uint32_t)result;
1426                 }
1427                 return (err);
1428         }
1429         if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1430                 if (pr_val == NULL) {
1431                         err = EINVAL;
1432                         return (err);
1433                 }
1434                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1435                 if (result < MIN_TX_RECYCLE_THRESHOLD ||
1436                     result > MAX_TX_RECYCLE_THRESHOLD)
1437                         err = EINVAL;
1438                 else {
1439                         igb->tx_recycle_thresh = (uint32_t)result;
1440                 }
1441                 return (err);
1442         }
1443         if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1444                 if (pr_val == NULL) {
1445                         err = EINVAL;
1446                         return (err);
1447                 }
1448                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1449                 if (result < MIN_TX_OVERLOAD_THRESHOLD ||
1450                     result > MAX_TX_OVERLOAD_THRESHOLD)
1451                         err = EINVAL;
1452                 else {
1453                         igb->tx_overload_thresh = (uint32_t)result;
1454                 }
1455                 return (err);
1456         }
1457         if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1458                 if (pr_val == NULL) {
1459                         err = EINVAL;
1460                         return (err);
1461                 }
1462                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1463                 if (result < MIN_TX_RESCHED_THRESHOLD ||
1464                     result > MAX_TX_RESCHED_THRESHOLD ||
1465                     result > igb->tx_ring_size)
1466                         err = EINVAL;
1467                 else {
1468                         igb->tx_resched_thresh = (uint32_t)result;
1469                 }
1470                 return (err);
1471         }
1472         if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1473                 if (pr_val == NULL) {
1474                         err = EINVAL;
1475                         return (err);
1476                 }
1477                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1478                 if (result < MIN_RX_COPY_THRESHOLD ||
1479                     result > MAX_RX_COPY_THRESHOLD)
1480                         err = EINVAL;
1481                 else {
1482                         igb->rx_copy_thresh = (uint32_t)result;
1483                 }
1484                 return (err);
1485         }
1486         if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1487                 if (pr_val == NULL) {
1488                         err = EINVAL;
1489                         return (err);
1490                 }
1491                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1492                 if (result < MIN_RX_LIMIT_PER_INTR ||
1493                     result > MAX_RX_LIMIT_PER_INTR)
1494                         err = EINVAL;
1495                 else {
1496                         igb->rx_limit_per_intr = (uint32_t)result;
1497                 }
1498                 return (err);
1499         }
1500         if (strcmp(pr_name, "_intr_throttling") == 0) {
1501                 if (pr_val == NULL) {
1502                         err = EINVAL;
1503                         return (err);
1504                 }
1505                 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1506 
1507                 if (result < igb->capab->min_intr_throttle ||
1508                     result > igb->capab->max_intr_throttle)
1509                         err = EINVAL;
1510                 else {
1511                         igb->intr_throttling[0] = (uint32_t)result;
1512 
1513                         for (i = 0; i < MAX_NUM_EITR; i++)
1514                                 igb->intr_throttling[i] =
1515                                     igb->intr_throttling[0];
1516 
1517                         /* Set interrupt throttling rate */
1518                         for (i = 0; i < igb->intr_cnt; i++)
1519                                 E1000_WRITE_REG(hw, E1000_EITR(i),
1520                                     igb->intr_throttling[i]);
1521                 }
1522                 return (err);
1523         }
1524         return (ENOTSUP);
1525 }
1526 
1527 int
1528 igb_get_priv_prop(igb_t *igb, const char *pr_name, uint_t pr_valsize,
1529     void *pr_val)
1530 {
1531         int value;
1532 
1533         if (strcmp(pr_name, "_adv_pause_cap") == 0) {
1534                 value = igb->param_adv_pause_cap;
1535         } else if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1536                 value = igb->param_adv_asym_pause_cap;
1537         } else if (strcmp(pr_name, "_eee_support") == 0) {
1538                 /*
1539                  * For now, only supported on I350.  Add new mac.type values
1540                  * (or use < instead) as new cards offer up EEE.
1541                  */
1542                 value = (igb->hw.mac.type != e1000_i350) ? 0 :
1543                     !(igb->hw.dev_spec._82575.eee_disable);
1544         } else if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1545                 value = igb->tx_copy_thresh;
1546         } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1547                 value = igb->tx_recycle_thresh;
1548         } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1549                 value = igb->tx_overload_thresh;
1550         } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1551                 value = igb->tx_resched_thresh;
1552         } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1553                 value = igb->rx_copy_thresh;
1554         } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1555                 value = igb->rx_limit_per_intr;
1556         } else if (strcmp(pr_name, "_intr_throttling") == 0) {
1557                 value = igb->intr_throttling[0];
1558         } else {
1559                 return (ENOTSUP);
1560         }
1561 
1562         (void) snprintf(pr_val, pr_valsize, "%d", value);
1563         return (0);
1564 }
1565 
1566 void
1567 igb_priv_prop_info(igb_t *igb, const char *pr_name, mac_prop_info_handle_t prh)
1568 {
1569         char valstr[64];
1570         int value;
1571 
1572         if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
1573             strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1574                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1575                 return;
1576         } else if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1577                 value = DEFAULT_TX_COPY_THRESHOLD;
1578         } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1579                 value = DEFAULT_TX_RECYCLE_THRESHOLD;
1580         } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1581                 value = DEFAULT_TX_OVERLOAD_THRESHOLD;
1582         } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1583                 value = DEFAULT_TX_RESCHED_THRESHOLD;
1584         } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1585                 value = DEFAULT_RX_COPY_THRESHOLD;
1586         } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1587                 value = DEFAULT_RX_LIMIT_PER_INTR;
1588         } else  if (strcmp(pr_name, "_intr_throttling") == 0) {
1589                 value = igb->capab->def_intr_throttle;
1590         } else {
1591                 return;
1592         }
1593 
1594         (void) snprintf(valstr, sizeof (valstr), "%d", value);
1595         mac_prop_info_set_default_str(prh, valstr);
1596 }