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