1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * mii - MII/PHY support for MAC drivers 28 * 29 * Utility module to provide a consistent interface to a MAC driver accross 30 * different implementations of PHY devices 31 */ 32 33 #include <sys/types.h> 34 #include <sys/debug.h> 35 #include <sys/errno.h> 36 #include <sys/param.h> 37 #include <sys/kmem.h> 38 #include <sys/conf.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 #include <sys/modctl.h> 42 #include <sys/cmn_err.h> 43 #include <sys/policy.h> 44 #include <sys/note.h> 45 #include <sys/strsun.h> 46 #include <sys/miiregs.h> 47 #include <sys/mac_provider.h> 48 #include <sys/mac_ether.h> 49 #include <sys/mii.h> 50 #include "miipriv.h" 51 52 #define MII_SECOND 1000000 53 54 /* indices into error array */ 55 enum { 56 MII_EOK = 0, 57 MII_ERESET, 58 MII_ESTART, 59 MII_ENOPHY, 60 MII_ECHECK, 61 }; 62 63 static const char *mii_errors[] = { 64 "", 65 "Failure resetting PHY.", 66 "Failure starting PHY.", 67 "No Ethernet PHY found.", 68 "Failure reading PHY (removed?)" 69 }; 70 71 /* Indexed by XCVR_ type */ 72 static const const char *mii_xcvr_types[] = { 73 "Undefined", 74 "Unknown", 75 "10 Mbps", 76 "100BASE-T4", 77 "100BASE-X", 78 "100BASE-T2", 79 "1000BASE-X", 80 "1000BASE-T" 81 }; 82 83 static lb_property_t mii_loopmodes[] = { 84 { normal, "normal", PHY_LB_NONE }, 85 { internal, "PHY", PHY_LB_INT_PHY }, 86 { external, "10Mbps", PHY_LB_EXT_10 }, 87 { external, "100Mbps", PHY_LB_EXT_100 }, 88 { external, "1000Mbps", PHY_LB_EXT_1000 }, 89 }; 90 91 /* state machine */ 92 typedef enum { 93 MII_STATE_PROBE = 0, 94 MII_STATE_RESET, 95 MII_STATE_START, 96 MII_STATE_RUN, 97 } mii_tstate_t; 98 99 struct mii_handle { 100 dev_info_t *m_dip; 101 void *m_private; 102 mii_ops_t m_ops; 103 104 kt_did_t m_tq_id; 105 kmutex_t m_lock; 106 kcondvar_t m_cv; 107 ddi_taskq_t *m_tq; 108 int m_flags; 109 110 boolean_t m_started; 111 boolean_t m_suspending; 112 boolean_t m_suspended; 113 boolean_t m_notify; 114 int m_error; 115 mii_tstate_t m_tstate; 116 117 #define MII_FLAG_EXIT 0x1 /* exit the thread */ 118 #define MII_FLAG_STOP 0x2 /* shutdown MII monitoring */ 119 #define MII_FLAG_RESET 0x4 /* reset the MII */ 120 #define MII_FLAG_PROBE 0x8 /* probe for PHYs */ 121 #define MII_FLAG_NOTIFY 0x10 /* notify about a change */ 122 #define MII_FLAG_SUSPEND 0x20 /* monitoring suspended */ 123 #define MII_FLAG_MACRESET 0x40 /* send reset to MAC */ 124 #define MII_FLAG_PHYSTART 0x80 /* start up the PHY */ 125 126 /* device name for printing, e.g. "hme0" */ 127 char m_name[MODMAXNAMELEN + 16]; 128 129 int m_addr; 130 phy_handle_t m_phys[32]; 131 phy_handle_t m_bogus_phy; 132 phy_handle_t *m_phy; 133 134 link_state_t m_link; 135 136 /* these start out undefined, but get values due to mac_prop_set */ 137 int m_en_aneg; 138 int m_en_10_hdx; 139 int m_en_10_fdx; 140 int m_en_100_t4; 141 int m_en_100_hdx; 142 int m_en_100_fdx; 143 int m_en_1000_hdx; 144 int m_en_1000_fdx; 145 int m_en_flowctrl; 146 147 boolean_t m_cap_pause; 148 boolean_t m_cap_asmpause; 149 }; 150 151 152 static void _mii_task(void *); 153 static void _mii_probe_task(mii_handle_t); 154 155 /* 156 * Loadable module structures/entrypoints 157 */ 158 159 extern struct mod_ops mod_misc_ops; 160 161 static struct modlmisc modlmisc = { 162 &mod_miscops, 163 "802.3 MII support", 164 }; 165 166 static struct modlinkage modlinkage = { 167 MODREV_1, &modlmisc, NULL 168 }; 169 170 int 171 _init(void) 172 { 173 return (mod_install(&modlinkage)); 174 } 175 176 int 177 _fini(void) 178 { 179 return (mod_remove(&modlinkage)); 180 } 181 182 int 183 _info(struct modinfo *modinfop) 184 { 185 return (mod_info(&modlinkage, modinfop)); 186 } 187 188 void 189 _mii_error(mii_handle_t mh, int errno) 190 { 191 /* 192 * This dumps an error message, but it avoids filling the log with 193 * repeated error messages. 194 */ 195 if (mh->m_error != errno) { 196 cmn_err(CE_WARN, "%s: %s", mh->m_name, mii_errors[errno]); 197 mh->m_error = errno; 198 } 199 } 200 201 /* 202 * Known list of specific PHY probes. 203 */ 204 typedef boolean_t (*phy_probe_t)(phy_handle_t *); 205 phy_probe_t _phy_probes[] = { 206 phy_natsemi_probe, 207 phy_intel_probe, 208 phy_qualsemi_probe, 209 phy_cicada_probe, 210 phy_other_probe, 211 NULL 212 }; 213 214 /* 215 * MII Interface functions 216 */ 217 218 mii_handle_t 219 mii_alloc_instance(void *private, dev_info_t *dip, int inst, mii_ops_t *ops) 220 { 221 mii_handle_t mh; 222 char tqname[16]; 223 224 if (ops->mii_version != MII_OPS_VERSION) { 225 cmn_err(CE_WARN, "%s: incompatible MII version (%d)", 226 ddi_driver_name(dip), ops->mii_version); 227 return (NULL); 228 } 229 mh = kmem_zalloc(sizeof (*mh), KM_SLEEP); 230 231 (void) snprintf(mh->m_name, sizeof (mh->m_name), "%s%d", 232 ddi_driver_name(dip), inst); 233 234 /* DDI will prepend the driver name */ 235 (void) snprintf(tqname, sizeof (tqname), "mii%d", inst); 236 237 mh->m_dip = dip; 238 mh->m_ops = *ops; 239 mh->m_private = private; 240 mh->m_suspended = B_FALSE; 241 mh->m_started = B_FALSE; 242 mh->m_notify = B_FALSE; 243 mh->m_tstate = MII_STATE_PROBE; 244 mh->m_error = MII_EOK; 245 mutex_init(&mh->m_lock, NULL, MUTEX_DRIVER, NULL); 246 cv_init(&mh->m_cv, NULL, CV_DRIVER, NULL); 247 248 mh->m_tq = ddi_taskq_create(dip, tqname, 1, TASKQ_DEFAULTPRI, 0); 249 if (mh->m_tq == NULL) { 250 cmn_err(CE_WARN, "%s: unable to create MII monitoring task", 251 ddi_driver_name(dip)); 252 cv_destroy(&mh->m_cv); 253 mutex_destroy(&mh->m_lock); 254 kmem_free(mh, sizeof (*mh)); 255 return (NULL); 256 } 257 258 /* 259 * Initialize user prefs by loading properties. Ultimately, 260 * Brussels interfaces would be superior here. 261 */ 262 #define GETPROP(name) ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, name, -1) 263 mh->m_en_aneg = GETPROP("adv_autoneg_cap"); 264 mh->m_en_10_hdx = GETPROP("adv_10hdx_cap"); 265 mh->m_en_10_fdx = GETPROP("adv_10fdx_cap"); 266 mh->m_en_100_hdx = GETPROP("adv_100hdx_cap"); 267 mh->m_en_100_fdx = GETPROP("adv_100fdx_cap"); 268 mh->m_en_100_t4 = GETPROP("adv_100T4_cap"); 269 mh->m_en_1000_hdx = GETPROP("adv_1000hdx_cap"); 270 mh->m_en_1000_fdx = GETPROP("adv_1000fdx_cap"); 271 272 mh->m_cap_pause = B_FALSE; 273 mh->m_cap_asmpause = B_FALSE; 274 275 bzero(&mh->m_bogus_phy, sizeof (mh->m_bogus_phy)); 276 mh->m_bogus_phy.phy_link = LINK_STATE_UNKNOWN; 277 mh->m_bogus_phy.phy_duplex = LINK_DUPLEX_UNKNOWN; 278 mh->m_bogus_phy.phy_addr = 0xff; 279 mh->m_bogus_phy.phy_type = XCVR_NONE; 280 mh->m_bogus_phy.phy_id = (uint32_t)-1; 281 mh->m_bogus_phy.phy_loopback = PHY_LB_NONE; 282 mh->m_bogus_phy.phy_flowctrl = LINK_FLOWCTRL_NONE; 283 mh->m_phy = &mh->m_bogus_phy; 284 285 for (int i = 0; i < 32; i++) { 286 mh->m_phys[i].phy_mii = mh; 287 } 288 mh->m_bogus_phy.phy_mii = mh; 289 290 return (mh); 291 } 292 293 mii_handle_t 294 mii_alloc(void *private, dev_info_t *dip, mii_ops_t *ops) 295 { 296 return (mii_alloc_instance(private, dip, ddi_get_instance(dip), ops)); 297 } 298 299 void 300 mii_set_pauseable(mii_handle_t mh, boolean_t pauseable, boolean_t asymetric) 301 { 302 phy_handle_t *ph; 303 304 mutex_enter(&mh->m_lock); 305 ph = mh->m_phy; 306 ph->phy_cap_pause = mh->m_cap_pause = pauseable; 307 ph->phy_cap_asmpause = mh->m_cap_asmpause = asymetric; 308 if (pauseable) { 309 mh->m_en_flowctrl = LINK_FLOWCTRL_BI; 310 } else { 311 mh->m_en_flowctrl = LINK_FLOWCTRL_NONE; 312 } 313 mutex_exit(&mh->m_lock); 314 } 315 316 void 317 mii_free(mii_handle_t mh) 318 { 319 mutex_enter(&mh->m_lock); 320 mh->m_started = B_FALSE; 321 cv_broadcast(&mh->m_cv); 322 mutex_exit(&mh->m_lock); 323 324 ddi_taskq_destroy(mh->m_tq); 325 mutex_destroy(&mh->m_lock); 326 cv_destroy(&mh->m_cv); 327 kmem_free(mh, sizeof (*mh)); 328 } 329 330 void 331 mii_reset(mii_handle_t mh) 332 { 333 mutex_enter(&mh->m_lock); 334 if (mh->m_tstate > MII_STATE_RESET) 335 mh->m_tstate = MII_STATE_RESET; 336 cv_broadcast(&mh->m_cv); 337 mutex_exit(&mh->m_lock); 338 } 339 340 void 341 mii_suspend(mii_handle_t mh) 342 { 343 mutex_enter(&mh->m_lock); 344 while ((!mh->m_suspended) && (mh->m_started)) { 345 mh->m_suspending = B_TRUE; 346 cv_broadcast(&mh->m_cv); 347 cv_wait(&mh->m_cv, &mh->m_lock); 348 } 349 mutex_exit(&mh->m_lock); 350 } 351 352 void 353 mii_resume(mii_handle_t mh) 354 { 355 mutex_enter(&mh->m_lock); 356 /* resume implicity causes a PHY reset */ 357 if (mh->m_tstate > MII_STATE_RESET) { 358 mh->m_tstate = MII_STATE_RESET; 359 } 360 mh->m_suspended = B_FALSE; 361 cv_broadcast(&mh->m_cv); 362 mutex_exit(&mh->m_lock); 363 } 364 365 void 366 mii_start(mii_handle_t mh) 367 { 368 mutex_enter(&mh->m_lock); 369 if (!mh->m_started) { 370 mh->m_started = B_TRUE; 371 if (ddi_taskq_dispatch(mh->m_tq, _mii_task, mh, DDI_NOSLEEP) != 372 DDI_SUCCESS) { 373 cmn_err(CE_WARN, 374 "%s: unable to start MII monitoring task", 375 mh->m_name); 376 mh->m_started = B_FALSE; 377 } 378 } 379 cv_broadcast(&mh->m_cv); 380 mutex_exit(&mh->m_lock); 381 } 382 383 void 384 mii_stop(mii_handle_t mh) 385 { 386 mutex_enter(&mh->m_lock); 387 mh->m_started = B_FALSE; 388 cv_broadcast(&mh->m_cv); 389 mutex_exit(&mh->m_lock); 390 } 391 392 void 393 mii_probe(mii_handle_t mh) 394 { 395 mutex_enter(&mh->m_lock); 396 _mii_probe_task(mh); 397 mutex_exit(&mh->m_lock); 398 } 399 400 void 401 mii_check(mii_handle_t mh) 402 { 403 mutex_enter(&mh->m_lock); 404 cv_broadcast(&mh->m_cv); 405 mutex_exit(&mh->m_lock); 406 } 407 408 int 409 mii_get_speed(mii_handle_t mh) 410 { 411 phy_handle_t *ph = mh->m_phy; 412 413 return (ph->phy_speed); 414 } 415 416 link_duplex_t 417 mii_get_duplex(mii_handle_t mh) 418 { 419 phy_handle_t *ph = mh->m_phy; 420 421 return (ph->phy_duplex); 422 } 423 424 link_state_t 425 mii_get_state(mii_handle_t mh) 426 { 427 phy_handle_t *ph = mh->m_phy; 428 429 return (ph->phy_link); 430 } 431 432 link_flowctrl_t 433 mii_get_flowctrl(mii_handle_t mh) 434 { 435 phy_handle_t *ph = mh->m_phy; 436 437 return (ph->phy_flowctrl); 438 } 439 440 int 441 mii_get_loopmodes(mii_handle_t mh, lb_property_t *modes) 442 { 443 phy_handle_t *ph = mh->m_phy; 444 int cnt; 445 446 /* 447 * There's a pretty big assumption in here. The assumption is 448 * that for 1000BASE-T and 100BASE-TX modes that we can 449 * support all of the lower speeds and full duplex uniformly. 450 */ 451 switch (ph->phy_type) { 452 case XCVR_1000T: 453 cnt = 5; /* 1000 BASE-T should support all modes */ 454 break; 455 case XCVR_100X: 456 /* 457 * This might be 100BASE-FX. If so, it won't support the 458 * 10Mbps modes. 459 */ 460 if (ph->phy_cap_10_fdx) { 461 cnt = 4; /* 100BASE-TX probably */ 462 } else { 463 cnt = 2; /* 100BASE-FX? */ 464 } 465 break; 466 case XCVR_10: 467 /* Some 10Mbs PHYs don't do full duplex */ 468 if (ph->phy_cap_10_fdx) { 469 cnt = 3; 470 } else { 471 cnt = 2; 472 } 473 break; 474 case XCVR_NONE: 475 cnt = 1; /* No XCVR, all we can do is leave it off */ 476 break; 477 case XCVR_1000X: 478 case XCVR_100T4: 479 case XCVR_100T2: 480 default: 481 /* 482 * Anything else we just allow for internal PHY loopback. 483 * Note that many of these will probably be capable of 484 * supporting additional external loopback modes, but we 485 * can't be sure of it, so we just leave it alone. 486 */ 487 cnt = 2; 488 break; 489 } 490 491 if (modes) { 492 bcopy(mii_loopmodes, modes, sizeof (lb_property_t) * cnt); 493 } 494 return (cnt); 495 } 496 497 uint32_t 498 mii_get_loopback(mii_handle_t mh) 499 { 500 phy_handle_t *ph = mh->m_phy; 501 502 return (ph->phy_loopback); 503 } 504 505 int 506 mii_set_loopback(mii_handle_t mh, uint32_t loop) 507 { 508 phy_handle_t *ph; 509 510 mutex_enter(&mh->m_lock); 511 ph = mh->m_phy; 512 513 if ((!mh->m_started) || (!ph->phy_present) || 514 (loop >= mii_get_loopmodes(mh, NULL))) { 515 return (EINVAL); 516 } 517 518 ph->phy_loopback = loop; 519 mh->m_tstate = MII_STATE_RESET; 520 cv_broadcast(&mh->m_cv); 521 mutex_exit(&mh->m_lock); 522 523 return (0); 524 } 525 526 uint32_t 527 mii_get_id(mii_handle_t mh) 528 { 529 phy_handle_t *ph = mh->m_phy; 530 531 return (ph->phy_id); 532 } 533 534 int 535 mii_get_addr(mii_handle_t mh) 536 { 537 return (mh->m_addr); 538 } 539 540 /* GLDv3 helpers */ 541 542 boolean_t 543 mii_m_loop_ioctl(mii_handle_t mh, queue_t *wq, mblk_t *mp) 544 { 545 struct iocblk *iocp; 546 int rv = 0; 547 int cnt; 548 lb_property_t modes[MII_LOOPBACK_MAX]; 549 lb_info_sz_t sz; 550 int cmd; 551 uint32_t mode; 552 553 iocp = (void *)mp->b_rptr; 554 cmd = iocp->ioc_cmd; 555 556 switch (cmd) { 557 case LB_SET_MODE: 558 case LB_GET_INFO_SIZE: 559 case LB_GET_INFO: 560 case LB_GET_MODE: 561 break; 562 563 default: 564 return (B_FALSE); 565 } 566 567 if (mp->b_cont == NULL) { 568 miocnak(wq, mp, 0, EINVAL); 569 return (B_TRUE); 570 } 571 572 switch (cmd) { 573 case LB_GET_INFO_SIZE: 574 cnt = mii_get_loopmodes(mh, modes); 575 if (iocp->ioc_count != sizeof (sz)) { 576 rv = EINVAL; 577 } else { 578 sz = cnt * sizeof (lb_property_t); 579 bcopy(&sz, mp->b_cont->b_rptr, sizeof (sz)); 580 } 581 break; 582 583 case LB_GET_INFO: 584 cnt = mii_get_loopmodes(mh, modes); 585 if (iocp->ioc_count != (cnt * sizeof (lb_property_t))) { 586 rv = EINVAL; 587 } else { 588 bcopy(modes, mp->b_cont->b_rptr, iocp->ioc_count); 589 } 590 break; 591 592 case LB_GET_MODE: 593 if (iocp->ioc_count != sizeof (mode)) { 594 rv = EINVAL; 595 } else { 596 mode = mii_get_loopback(mh); 597 bcopy(&mode, mp->b_cont->b_rptr, sizeof (mode)); 598 } 599 break; 600 601 case LB_SET_MODE: 602 rv = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 603 if (rv != 0) 604 break; 605 if (iocp->ioc_count != sizeof (mode)) { 606 rv = EINVAL; 607 break; 608 } 609 bcopy(mp->b_cont->b_rptr, &mode, sizeof (mode)); 610 rv = mii_set_loopback(mh, mode); 611 break; 612 } 613 614 if (rv == 0) { 615 miocack(wq, mp, iocp->ioc_count, 0); 616 } else { 617 miocnak(wq, mp, 0, rv); 618 } 619 return (B_TRUE); 620 } 621 622 int 623 mii_m_getprop(mii_handle_t mh, const char *name, mac_prop_id_t num, 624 uint_t flags, uint_t sz, void *val, uint_t *permp) 625 { 626 phy_handle_t *ph; 627 int err = 0; 628 uint_t perm; 629 boolean_t dfl = flags & MAC_PROP_DEFAULT; 630 631 _NOTE(ARGUNUSED(name)); 632 633 if (sz < 1) 634 return (EINVAL); 635 636 mutex_enter(&mh->m_lock); 637 638 ph = mh->m_phy; 639 perm = MAC_PROP_PERM_RW; 640 641 #define CASE_PROP_ABILITY(PROP, VAR) \ 642 case MAC_PROP_ADV_##PROP: \ 643 perm = MAC_PROP_PERM_READ; \ 644 *(uint8_t *)val = \ 645 dfl ? ph->phy_cap_##VAR : ph->phy_adv_##VAR; \ 646 break; \ 647 \ 648 case MAC_PROP_EN_##PROP: \ 649 if (!ph->phy_cap_##VAR) \ 650 perm = MAC_PROP_PERM_READ; \ 651 *(uint8_t *)val = \ 652 dfl ? ph->phy_cap_##VAR : ph->phy_en_##VAR; \ 653 break; 654 655 switch (num) { 656 case MAC_PROP_DUPLEX: 657 perm = MAC_PROP_PERM_READ; 658 if (sz >= sizeof (link_duplex_t)) { 659 bcopy(&ph->phy_duplex, val, sizeof (link_duplex_t)); 660 } else { 661 err = EINVAL; 662 } 663 break; 664 665 case MAC_PROP_SPEED: 666 perm = MAC_PROP_PERM_READ; 667 if (sz >= sizeof (uint64_t)) { 668 uint64_t speed = ph->phy_speed * 1000000ull; 669 bcopy(&speed, val, sizeof (speed)); 670 } else { 671 err = EINVAL; 672 } 673 break; 674 675 case MAC_PROP_AUTONEG: 676 *(uint8_t *)val = 677 dfl ? ph->phy_cap_aneg : ph->phy_adv_aneg; 678 break; 679 680 case MAC_PROP_FLOWCTRL: 681 if (sz >= sizeof (link_flowctrl_t)) { 682 bcopy(&ph->phy_flowctrl, val, 683 sizeof (link_flowctrl_t)); 684 } else { 685 err = EINVAL; 686 } 687 break; 688 689 CASE_PROP_ABILITY(1000FDX_CAP, 1000_fdx) 690 CASE_PROP_ABILITY(1000HDX_CAP, 1000_hdx) 691 CASE_PROP_ABILITY(100T4_CAP, 100_t4) 692 CASE_PROP_ABILITY(100FDX_CAP, 100_fdx) 693 CASE_PROP_ABILITY(100HDX_CAP, 100_hdx) 694 CASE_PROP_ABILITY(10FDX_CAP, 10_fdx) 695 CASE_PROP_ABILITY(10HDX_CAP, 10_hdx) 696 697 default: 698 err = ENOTSUP; 699 break; 700 } 701 702 if (err == 0) { 703 *permp = perm; 704 } 705 706 mutex_exit(&mh->m_lock); 707 708 return (err); 709 } 710 711 int 712 mii_m_setprop(mii_handle_t mh, const char *name, mac_prop_id_t num, 713 uint_t sz, const void *valp) 714 { 715 phy_handle_t *ph; 716 boolean_t *advp = NULL; 717 boolean_t *capp = NULL; 718 int *macpp = NULL; 719 int rv = ENOTSUP; 720 721 _NOTE(ARGUNUSED(name)); 722 723 if (sz < 1) 724 return (EINVAL); 725 726 mutex_enter(&mh->m_lock); 727 728 ph = mh->m_phy; 729 730 /* we don't support changing parameters while in loopback mode */ 731 if (ph->phy_loopback != PHY_LB_NONE) { 732 switch (num) { 733 case MAC_PROP_EN_1000FDX_CAP: 734 case MAC_PROP_EN_1000HDX_CAP: 735 case MAC_PROP_EN_100FDX_CAP: 736 case MAC_PROP_EN_100HDX_CAP: 737 case MAC_PROP_EN_100T4_CAP: 738 case MAC_PROP_EN_10FDX_CAP: 739 case MAC_PROP_EN_10HDX_CAP: 740 case MAC_PROP_AUTONEG: 741 case MAC_PROP_FLOWCTRL: 742 return (EBUSY); 743 } 744 } 745 746 switch (num) { 747 case MAC_PROP_EN_1000FDX_CAP: 748 capp = &ph->phy_cap_1000_fdx; 749 advp = &ph->phy_en_1000_fdx; 750 macpp = &mh->m_en_1000_fdx; 751 break; 752 case MAC_PROP_EN_1000HDX_CAP: 753 capp = &ph->phy_cap_1000_hdx; 754 advp = &ph->phy_en_1000_hdx; 755 macpp = &mh->m_en_1000_hdx; 756 break; 757 case MAC_PROP_EN_100FDX_CAP: 758 capp = &ph->phy_cap_100_fdx; 759 advp = &ph->phy_en_100_fdx; 760 macpp = &mh->m_en_100_fdx; 761 break; 762 case MAC_PROP_EN_100HDX_CAP: 763 capp = &ph->phy_cap_100_hdx; 764 advp = &ph->phy_en_100_hdx; 765 macpp = &mh->m_en_100_hdx; 766 break; 767 case MAC_PROP_EN_100T4_CAP: 768 capp = &ph->phy_cap_100_t4; 769 advp = &ph->phy_en_100_t4; 770 macpp = &mh->m_en_100_t4; 771 break; 772 case MAC_PROP_EN_10FDX_CAP: 773 capp = &ph->phy_cap_10_fdx; 774 advp = &ph->phy_en_10_fdx; 775 macpp = &mh->m_en_10_fdx; 776 break; 777 case MAC_PROP_EN_10HDX_CAP: 778 capp = &ph->phy_cap_10_hdx; 779 advp = &ph->phy_en_10_hdx; 780 macpp = &mh->m_en_10_hdx; 781 break; 782 case MAC_PROP_AUTONEG: 783 capp = &ph->phy_cap_aneg; 784 advp = &ph->phy_en_aneg; 785 macpp = &mh->m_en_aneg; 786 break; 787 case MAC_PROP_FLOWCTRL: 788 if (sz < sizeof (link_flowctrl_t)) { 789 rv = EINVAL; 790 } else { 791 link_flowctrl_t fc; 792 boolean_t chg; 793 794 bcopy(valp, &fc, sizeof (fc)); 795 796 chg = fc == ph->phy_en_flowctrl ? B_FALSE : B_TRUE; 797 switch (fc) { 798 case LINK_FLOWCTRL_NONE: 799 ph->phy_en_pause = B_FALSE; 800 ph->phy_en_asmpause = B_FALSE; 801 ph->phy_en_flowctrl = fc; 802 break; 803 /* 804 * Note that while we don't have a way to 805 * advertise that we can RX pause (we just 806 * won't send pause frames), we advertise full 807 * support. The MAC driver will learn of the 808 * configuration via the saved value of the 809 * tunable. 810 */ 811 case LINK_FLOWCTRL_BI: 812 case LINK_FLOWCTRL_RX: 813 if (ph->phy_cap_pause) { 814 ph->phy_en_pause = B_TRUE; 815 ph->phy_en_asmpause = B_TRUE; 816 ph->phy_en_flowctrl = fc; 817 } else { 818 rv = EINVAL; 819 } 820 break; 821 822 /* 823 * Tell the other side that we can assert 824 * pause, but we cannot resend. 825 */ 826 case LINK_FLOWCTRL_TX: 827 if (ph->phy_cap_asmpause) { 828 ph->phy_en_pause = B_FALSE; 829 ph->phy_en_flowctrl = fc; 830 ph->phy_en_asmpause = B_TRUE; 831 } else { 832 rv = EINVAL; 833 } 834 break; 835 default: 836 rv = EINVAL; 837 break; 838 } 839 if ((rv == 0) && chg) { 840 mh->m_en_flowctrl = fc; 841 mh->m_tstate = MII_STATE_RESET; 842 cv_broadcast(&mh->m_cv); 843 } 844 } 845 break; 846 847 default: 848 rv = ENOTSUP; 849 break; 850 } 851 852 if (capp && advp && macpp) { 853 if (sz < sizeof (uint8_t)) { 854 rv = EINVAL; 855 856 } else if (*capp) { 857 if (*advp != *(uint8_t *)valp) { 858 *advp = *(uint8_t *)valp; 859 *macpp = *(uint8_t *)valp; 860 mh->m_tstate = MII_STATE_RESET; 861 cv_broadcast(&mh->m_cv); 862 } 863 rv = 0; 864 } 865 } 866 867 mutex_exit(&mh->m_lock); 868 return (rv); 869 } 870 871 int 872 mii_m_getstat(mii_handle_t mh, uint_t stat, uint64_t *val) 873 { 874 phy_handle_t *ph; 875 int rv = 0; 876 877 mutex_enter(&mh->m_lock); 878 879 ph = mh->m_phy; 880 881 switch (stat) { 882 case MAC_STAT_IFSPEED: 883 *val = ph->phy_speed * 1000000ull; 884 break; 885 case ETHER_STAT_LINK_DUPLEX: 886 *val = ph->phy_duplex; 887 break; 888 case ETHER_STAT_LINK_AUTONEG: 889 *val = !!(ph->phy_adv_aneg && ph->phy_lp_aneg); 890 break; 891 case ETHER_STAT_XCVR_ID: 892 *val = ph->phy_id; 893 break; 894 case ETHER_STAT_XCVR_INUSE: 895 *val = ph->phy_type; 896 break; 897 case ETHER_STAT_XCVR_ADDR: 898 *val = ph->phy_addr; 899 break; 900 case ETHER_STAT_LINK_ASMPAUSE: 901 *val = ph->phy_adv_asmpause && ph->phy_lp_asmpause && 902 ph->phy_adv_pause != ph->phy_lp_pause; 903 break; 904 case ETHER_STAT_LINK_PAUSE: 905 *val = (ph->phy_flowctrl == LINK_FLOWCTRL_BI) || 906 (ph->phy_flowctrl == LINK_FLOWCTRL_RX); 907 break; 908 case ETHER_STAT_CAP_1000FDX: 909 *val = ph->phy_cap_1000_fdx; 910 break; 911 case ETHER_STAT_CAP_1000HDX: 912 *val = ph->phy_cap_1000_hdx; 913 break; 914 case ETHER_STAT_CAP_100FDX: 915 *val = ph->phy_cap_100_fdx; 916 break; 917 case ETHER_STAT_CAP_100HDX: 918 *val = ph->phy_cap_100_hdx; 919 break; 920 case ETHER_STAT_CAP_10FDX: 921 *val = ph->phy_cap_10_fdx; 922 break; 923 case ETHER_STAT_CAP_10HDX: 924 *val = ph->phy_cap_10_hdx; 925 break; 926 case ETHER_STAT_CAP_100T4: 927 *val = ph->phy_cap_100_t4; 928 break; 929 case ETHER_STAT_CAP_AUTONEG: 930 *val = ph->phy_cap_aneg; 931 break; 932 case ETHER_STAT_CAP_PAUSE: 933 *val = ph->phy_cap_pause; 934 break; 935 case ETHER_STAT_CAP_ASMPAUSE: 936 *val = ph->phy_cap_asmpause; 937 break; 938 939 case ETHER_STAT_LP_CAP_1000FDX: 940 *val = ph->phy_lp_1000_fdx; 941 break; 942 case ETHER_STAT_LP_CAP_1000HDX: 943 *val = ph->phy_lp_1000_hdx; 944 break; 945 case ETHER_STAT_LP_CAP_100FDX: 946 *val = ph->phy_lp_100_fdx; 947 break; 948 case ETHER_STAT_LP_CAP_100HDX: 949 *val = ph->phy_lp_100_hdx; 950 break; 951 case ETHER_STAT_LP_CAP_10FDX: 952 *val = ph->phy_lp_10_fdx; 953 break; 954 case ETHER_STAT_LP_CAP_10HDX: 955 *val = ph->phy_lp_10_hdx; 956 break; 957 case ETHER_STAT_LP_CAP_100T4: 958 *val = ph->phy_lp_100_t4; 959 break; 960 case ETHER_STAT_LP_CAP_AUTONEG: 961 *val = ph->phy_lp_aneg; 962 break; 963 case ETHER_STAT_LP_CAP_PAUSE: 964 *val = ph->phy_lp_pause; 965 break; 966 case ETHER_STAT_LP_CAP_ASMPAUSE: 967 *val = ph->phy_lp_asmpause; 968 break; 969 970 case ETHER_STAT_ADV_CAP_1000FDX: 971 *val = ph->phy_adv_1000_fdx; 972 break; 973 case ETHER_STAT_ADV_CAP_1000HDX: 974 *val = ph->phy_adv_1000_hdx; 975 break; 976 case ETHER_STAT_ADV_CAP_100FDX: 977 *val = ph->phy_adv_100_fdx; 978 break; 979 case ETHER_STAT_ADV_CAP_100HDX: 980 *val = ph->phy_adv_100_hdx; 981 break; 982 case ETHER_STAT_ADV_CAP_10FDX: 983 *val = ph->phy_adv_10_fdx; 984 break; 985 case ETHER_STAT_ADV_CAP_10HDX: 986 *val = ph->phy_adv_10_hdx; 987 break; 988 case ETHER_STAT_ADV_CAP_100T4: 989 *val = ph->phy_adv_100_t4; 990 break; 991 case ETHER_STAT_ADV_CAP_AUTONEG: 992 *val = ph->phy_adv_aneg; 993 break; 994 case ETHER_STAT_ADV_CAP_PAUSE: 995 *val = ph->phy_adv_pause; 996 break; 997 case ETHER_STAT_ADV_CAP_ASMPAUSE: 998 *val = ph->phy_adv_asmpause; 999 break; 1000 1001 default: 1002 rv = ENOTSUP; 1003 break; 1004 } 1005 mutex_exit(&mh->m_lock); 1006 1007 return (rv); 1008 } 1009 1010 /* 1011 * PHY support routines. Private to the MII module and the vendor 1012 * specific PHY implementation code. 1013 */ 1014 uint16_t 1015 phy_read(phy_handle_t *ph, uint8_t reg) 1016 { 1017 mii_handle_t mh = ph->phy_mii; 1018 1019 return ((*mh->m_ops.mii_read)(mh->m_private, ph->phy_addr, reg)); 1020 } 1021 1022 void 1023 phy_write(phy_handle_t *ph, uint8_t reg, uint16_t val) 1024 { 1025 mii_handle_t mh = ph->phy_mii; 1026 1027 (*mh->m_ops.mii_write)(mh->m_private, ph->phy_addr, reg, val); 1028 } 1029 1030 int 1031 phy_reset(phy_handle_t *ph) 1032 { 1033 ASSERT(mutex_owned(&ph->phy_mii->m_lock)); 1034 1035 /* 1036 * For our device, make sure its powered up, unisolated, and 1037 * not in loopback. 1038 */ 1039 PHY_CLR(ph, MII_CONTROL, 1040 MII_CONTROL_PWRDN | MII_CONTROL_LOOPBACK | MII_CONTROL_ISOLATE); 1041 1042 /* 1043 * Finally reset it. 1044 */ 1045 PHY_SET(ph, MII_CONTROL, MII_CONTROL_RESET); 1046 1047 /* 1048 * Apparently some devices (DP83840A) like to have a little 1049 * bit of a wait before we start accessing anything else on 1050 * the PHY. 1051 */ 1052 drv_usecwait(500); 1053 1054 /* 1055 * Wait for reset to complete - probably very fast, but no 1056 * more than 0.5 sec according to spec. It would be nice if 1057 * we could use delay() here, but MAC drivers may call 1058 * functions which hold this lock in interrupt context, so 1059 * sleeping would be a definite no-no. The good news here is 1060 * that it seems to be the case that most devices come back 1061 * within only a few hundred usec. 1062 */ 1063 for (int i = 500000; i; i -= 100) { 1064 if ((phy_read(ph, MII_CONTROL) & MII_CONTROL_RESET) == 0) { 1065 /* reset completed */ 1066 return (DDI_SUCCESS); 1067 } 1068 drv_usecwait(100); 1069 } 1070 1071 return (DDI_FAILURE); 1072 } 1073 1074 int 1075 phy_stop(phy_handle_t *ph) 1076 { 1077 phy_write(ph, MII_CONTROL, MII_CONTROL_ISOLATE); 1078 1079 return (DDI_SUCCESS); 1080 } 1081 1082 int 1083 phy_start(phy_handle_t *ph) 1084 { 1085 uint16_t bmcr, anar, gtcr; 1086 ASSERT(mutex_owned(&ph->phy_mii->m_lock)); 1087 1088 /* 1089 * Disable everything to start... we'll add in modes as we go. 1090 */ 1091 ph->phy_adv_aneg = B_FALSE; 1092 ph->phy_adv_1000_fdx = B_FALSE; 1093 ph->phy_adv_1000_hdx = B_FALSE; 1094 ph->phy_adv_100_fdx = B_FALSE; 1095 ph->phy_adv_100_t4 = B_FALSE; 1096 ph->phy_adv_100_hdx = B_FALSE; 1097 ph->phy_adv_10_fdx = B_FALSE; 1098 ph->phy_adv_10_hdx = B_FALSE; 1099 ph->phy_adv_pause = B_FALSE; 1100 ph->phy_adv_asmpause = B_FALSE; 1101 1102 switch (ph->phy_loopback) { 1103 case PHY_LB_NONE: 1104 /* 1105 * No loopback overrides, so try to advertise everything 1106 * that is administratively enabled. 1107 */ 1108 ph->phy_adv_aneg = ph->phy_en_aneg; 1109 ph->phy_adv_1000_fdx = ph->phy_en_1000_fdx; 1110 ph->phy_adv_1000_hdx = ph->phy_en_1000_hdx; 1111 ph->phy_adv_100_fdx = ph->phy_en_100_fdx; 1112 ph->phy_adv_100_t4 = ph->phy_en_100_t4; 1113 ph->phy_adv_100_hdx = ph->phy_en_100_hdx; 1114 ph->phy_adv_10_fdx = ph->phy_en_10_fdx; 1115 ph->phy_adv_10_hdx = ph->phy_en_10_hdx; 1116 ph->phy_adv_pause = ph->phy_en_pause; 1117 ph->phy_adv_asmpause = ph->phy_en_asmpause; 1118 break; 1119 1120 case PHY_LB_INT_PHY: 1121 if (ph->phy_cap_1000_fdx) { 1122 ph->phy_adv_1000_fdx = B_TRUE; 1123 } else if (ph->phy_cap_100_fdx) { 1124 ph->phy_adv_100_fdx = B_TRUE; 1125 } else if (ph->phy_cap_10_fdx) { 1126 ph->phy_adv_10_fdx = B_TRUE; 1127 } 1128 break; 1129 1130 case PHY_LB_EXT_10: 1131 ph->phy_adv_10_fdx = B_TRUE; 1132 break; 1133 1134 case PHY_LB_EXT_100: 1135 ph->phy_adv_100_fdx = B_TRUE; 1136 break; 1137 1138 case PHY_LB_EXT_1000: 1139 ph->phy_adv_1000_fdx = B_TRUE; 1140 break; 1141 } 1142 1143 /* 1144 * Limit properties to what the hardware can actually support. 1145 */ 1146 #define FILTER_ADV(CAP) \ 1147 if (!ph->phy_cap_##CAP) \ 1148 ph->phy_adv_##CAP = 0 1149 1150 FILTER_ADV(aneg); 1151 FILTER_ADV(1000_fdx); 1152 FILTER_ADV(1000_hdx); 1153 FILTER_ADV(100_fdx); 1154 FILTER_ADV(100_t4); 1155 FILTER_ADV(100_hdx); 1156 FILTER_ADV(10_fdx); 1157 FILTER_ADV(10_hdx); 1158 FILTER_ADV(pause); 1159 FILTER_ADV(asmpause); 1160 1161 #undef FILTER_ADV 1162 1163 /* 1164 * We need at least one valid mode. 1165 */ 1166 if ((!ph->phy_adv_1000_fdx) && 1167 (!ph->phy_adv_1000_hdx) && 1168 (!ph->phy_adv_100_t4) && 1169 (!ph->phy_adv_100_fdx) && 1170 (!ph->phy_adv_100_hdx) && 1171 (!ph->phy_adv_10_fdx) && 1172 (!ph->phy_adv_10_hdx)) { 1173 1174 phy_warn(ph, 1175 "No valid link mode selected. Powering down PHY."); 1176 1177 PHY_SET(ph, MII_CONTROL, MII_CONTROL_PWRDN); 1178 1179 ph->phy_link = LINK_STATE_DOWN; 1180 return (DDI_SUCCESS); 1181 } 1182 1183 switch (ph->phy_loopback) { 1184 case PHY_LB_INT_PHY: 1185 bmcr = MII_CONTROL_LOOPBACK; 1186 gtcr = 0; 1187 break; 1188 case PHY_LB_EXT_10: 1189 case PHY_LB_EXT_100: 1190 case PHY_LB_EXT_1000: 1191 bmcr = 0; 1192 gtcr = MII_MSCONTROL_MANUAL | MII_MSCONTROL_MASTER; 1193 break; 1194 case PHY_LB_NONE: 1195 default: 1196 bmcr = 0; 1197 gtcr = 0; 1198 break; 1199 } 1200 1201 if (ph->phy_adv_aneg) { 1202 bmcr |= MII_CONTROL_ANE | MII_CONTROL_RSAN; 1203 } 1204 1205 if ((ph->phy_adv_1000_fdx) || (ph->phy_adv_1000_hdx)) { 1206 bmcr |= MII_CONTROL_1GB; 1207 1208 } else if (ph->phy_adv_100_fdx || ph->phy_adv_100_hdx || 1209 ph->phy_adv_100_t4) { 1210 bmcr |= MII_CONTROL_100MB; 1211 } 1212 1213 if (ph->phy_adv_1000_fdx || ph->phy_adv_100_fdx || ph->phy_adv_10_fdx) { 1214 bmcr |= MII_CONTROL_FDUPLEX; 1215 } 1216 1217 if (ph->phy_type == XCVR_1000X) { 1218 /* 1000BASE-X (usually fiber) */ 1219 anar = 0; 1220 if (ph->phy_adv_1000_fdx) { 1221 anar |= MII_ABILITY_X_FD; 1222 } 1223 if (ph->phy_adv_1000_hdx) { 1224 anar |= MII_ABILITY_X_HD; 1225 } 1226 if (ph->phy_adv_pause) { 1227 anar |= MII_ABILITY_X_PAUSE; 1228 } 1229 if (ph->phy_adv_asmpause) { 1230 anar |= MII_ABILITY_X_ASMPAUSE; 1231 } 1232 1233 } else if (ph->phy_type == XCVR_100T2) { 1234 /* 100BASE-T2 */ 1235 anar = 0; 1236 if (ph->phy_adv_100_fdx) { 1237 anar |= MII_ABILITY_T2_FD; 1238 } 1239 if (ph->phy_adv_100_hdx) { 1240 anar |= MII_ABILITY_T2_HD; 1241 } 1242 1243 } else { 1244 anar = MII_AN_SELECTOR_8023; 1245 1246 /* 1000BASE-T or 100BASE-X probably */ 1247 if (ph->phy_adv_1000_fdx) { 1248 gtcr |= MII_MSCONTROL_1000T_FD; 1249 } 1250 if (ph->phy_adv_1000_hdx) { 1251 gtcr |= MII_MSCONTROL_1000T; 1252 } 1253 if (ph->phy_adv_100_fdx) { 1254 anar |= MII_ABILITY_100BASE_TX_FD; 1255 } 1256 if (ph->phy_adv_100_hdx) { 1257 anar |= MII_ABILITY_100BASE_TX; 1258 } 1259 if (ph->phy_adv_100_t4) { 1260 anar |= MII_ABILITY_100BASE_T4; 1261 } 1262 if (ph->phy_adv_10_fdx) { 1263 anar |= MII_ABILITY_10BASE_T_FD; 1264 } 1265 if (ph->phy_adv_100_hdx) { 1266 anar |= MII_ABILITY_10BASE_T; 1267 } 1268 if (ph->phy_adv_pause) { 1269 anar |= MII_ABILITY_PAUSE; 1270 } 1271 if (ph->phy_adv_asmpause) { 1272 anar |= MII_ABILITY_ASMPAUSE; 1273 } 1274 } 1275 1276 ph->phy_link = LINK_STATE_DOWN; 1277 ph->phy_duplex = LINK_DUPLEX_UNKNOWN; 1278 ph->phy_speed = 0; 1279 1280 phy_write(ph, MII_AN_ADVERT, anar); 1281 phy_write(ph, MII_CONTROL, 1282 bmcr & ~(MII_CONTROL_ANE|MII_CONTROL_RSAN|MII_CONTROL_LOOPBACK)); 1283 switch (ph->phy_type) { 1284 case XCVR_1000T: 1285 case XCVR_1000X: 1286 case XCVR_100T2: 1287 phy_write(ph, MII_MSCONTROL, gtcr); 1288 } 1289 1290 /* 1291 * Finally, this will start up autoneg if it is enabled, or 1292 * force link settings otherwise. 1293 */ 1294 phy_write(ph, MII_CONTROL, bmcr); 1295 1296 return (DDI_SUCCESS); 1297 } 1298 1299 1300 int 1301 phy_check(phy_handle_t *ph) 1302 { 1303 uint16_t control, status, lpar, msstat, anexp; 1304 int debounces = 100; 1305 1306 ASSERT(mutex_owned(&ph->phy_mii->m_lock)); 1307 1308 debounce: 1309 status = phy_read(ph, MII_STATUS); 1310 control = phy_read(ph, MII_CONTROL); 1311 1312 if (status & MII_STATUS_EXTENDED) { 1313 lpar = phy_read(ph, MII_AN_LPABLE); 1314 anexp = phy_read(ph, MII_AN_EXPANSION); 1315 } else { 1316 lpar = 0; 1317 anexp = 0; 1318 } 1319 1320 /* 1321 * We reread to clear any latched bits. This also debounces 1322 * any state that might be in transition. 1323 */ 1324 drv_usecwait(10); 1325 if ((status != phy_read(ph, MII_STATUS)) && debounces) { 1326 debounces--; 1327 goto debounce; 1328 } 1329 1330 /* 1331 * Detect the situation where the PHY is removed or has died. 1332 * According to spec, at least one bit of status must be set, 1333 * and at least one bit must be clear. 1334 */ 1335 if ((status == 0xffff) || (status == 0)) { 1336 ph->phy_speed = 0; 1337 ph->phy_duplex = LINK_DUPLEX_UNKNOWN; 1338 ph->phy_link = LINK_STATE_UNKNOWN; 1339 ph->phy_present = B_FALSE; 1340 return (DDI_FAILURE); 1341 } 1342 1343 /* We only respect the link flag if we are not in loopback. */ 1344 if ((ph->phy_loopback != PHY_LB_INT_PHY) && 1345 ((status & MII_STATUS_LINKUP) == 0)) { 1346 ph->phy_speed = 0; 1347 ph->phy_duplex = LINK_DUPLEX_UNKNOWN; 1348 ph->phy_link = LINK_STATE_DOWN; 1349 return (DDI_SUCCESS); 1350 } 1351 1352 ph->phy_link = LINK_STATE_UP; 1353 1354 if ((control & MII_CONTROL_ANE) == 0) { 1355 1356 ph->phy_lp_aneg = B_FALSE; 1357 ph->phy_lp_10_hdx = B_FALSE; 1358 ph->phy_lp_10_fdx = B_FALSE; 1359 ph->phy_lp_100_t4 = B_FALSE; 1360 ph->phy_lp_100_hdx = B_FALSE; 1361 ph->phy_lp_100_fdx = B_FALSE; 1362 ph->phy_lp_1000_hdx = B_FALSE; 1363 ph->phy_lp_1000_fdx = B_FALSE; 1364 1365 /* 1366 * We have no idea what our link partner might or might 1367 * not be able to support, except that it appears to 1368 * support the same mode that we have forced. 1369 */ 1370 if (control & MII_CONTROL_1GB) { 1371 ph->phy_speed = 1000; 1372 } else if (control & MII_CONTROL_100MB) { 1373 ph->phy_speed = 100; 1374 } else { 1375 ph->phy_speed = 10; 1376 } 1377 ph->phy_duplex = control & MII_CONTROL_FDUPLEX ? 1378 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; 1379 1380 return (DDI_SUCCESS); 1381 } 1382 1383 if (ph->phy_type == XCVR_1000X) { 1384 1385 ph->phy_lp_10_hdx = B_FALSE; 1386 ph->phy_lp_10_fdx = B_FALSE; 1387 ph->phy_lp_100_t4 = B_FALSE; 1388 ph->phy_lp_100_hdx = B_FALSE; 1389 ph->phy_lp_100_fdx = B_FALSE; 1390 1391 /* 1000BASE-X requires autonegotiation */ 1392 ph->phy_lp_aneg = B_TRUE; 1393 ph->phy_lp_1000_fdx = !!(lpar & MII_ABILITY_X_FD); 1394 ph->phy_lp_1000_hdx = !!(lpar & MII_ABILITY_X_HD); 1395 ph->phy_lp_pause = !!(lpar & MII_ABILITY_X_PAUSE); 1396 ph->phy_lp_asmpause = !!(lpar & MII_ABILITY_X_ASMPAUSE); 1397 1398 } else if (ph->phy_type == XCVR_100T2) { 1399 ph->phy_lp_10_hdx = B_FALSE; 1400 ph->phy_lp_10_fdx = B_FALSE; 1401 ph->phy_lp_100_t4 = B_FALSE; 1402 ph->phy_lp_1000_hdx = B_FALSE; 1403 ph->phy_lp_1000_fdx = B_FALSE; 1404 ph->phy_lp_pause = B_FALSE; 1405 ph->phy_lp_asmpause = B_FALSE; 1406 1407 /* 100BASE-T2 requires autonegotiation */ 1408 ph->phy_lp_aneg = B_TRUE; 1409 ph->phy_lp_100_fdx = !!(lpar & MII_ABILITY_T2_FD); 1410 ph->phy_lp_100_hdx = !!(lpar & MII_ABILITY_T2_HD); 1411 1412 } else if (anexp & MII_AN_EXP_PARFAULT) { 1413 /* 1414 * Parallel detection fault! This happens when the 1415 * peer does not use autonegotiation, and the 1416 * detection logic reports more than one type of legal 1417 * link is available. Note that parallel detection 1418 * can only happen with half duplex 10, 100, and 1419 * 100TX4. We also should not have got here, because 1420 * the link state bit should have failed. 1421 */ 1422 #ifdef DEBUG 1423 phy_warn(ph, "Parallel detection fault!"); 1424 #endif 1425 ph->phy_lp_10_hdx = B_FALSE; 1426 ph->phy_lp_10_fdx = B_FALSE; 1427 ph->phy_lp_100_t4 = B_FALSE; 1428 ph->phy_lp_100_hdx = B_FALSE; 1429 ph->phy_lp_100_fdx = B_FALSE; 1430 ph->phy_lp_1000_hdx = B_FALSE; 1431 ph->phy_lp_1000_fdx = B_FALSE; 1432 ph->phy_lp_pause = B_FALSE; 1433 ph->phy_lp_asmpause = B_FALSE; 1434 ph->phy_speed = 0; 1435 ph->phy_duplex = LINK_DUPLEX_UNKNOWN; 1436 return (DDI_SUCCESS); 1437 1438 } else { 1439 ph->phy_lp_aneg = !!(anexp & MII_AN_EXP_LPCANAN); 1440 1441 /* 1442 * Note: If the peer doesn't support autonegotiation, then 1443 * according to clause 28.5.4.5, the link partner ability 1444 * register will still have the right bits set. However, 1445 * gigabit modes cannot use legacy parallel detection. 1446 */ 1447 1448 if ((ph->phy_type == XCVR_1000T) & 1449 (anexp & MII_AN_EXP_LPCANAN)) { 1450 1451 /* check for gige */ 1452 msstat = phy_read(ph, MII_MSSTATUS); 1453 1454 ph->phy_lp_1000_hdx = 1455 !!(msstat & MII_MSSTATUS_LP1000T); 1456 1457 ph->phy_lp_1000_fdx = 1458 !!(msstat & MII_MSSTATUS_LP1000T_FD); 1459 } 1460 1461 ph->phy_lp_100_fdx = !!(lpar & MII_ABILITY_100BASE_TX_FD); 1462 ph->phy_lp_100_hdx = !!(lpar & MII_ABILITY_100BASE_TX); 1463 ph->phy_lp_100_t4 = !!(lpar & MII_ABILITY_100BASE_T4); 1464 ph->phy_lp_10_fdx = !!(lpar & MII_ABILITY_10BASE_T_FD); 1465 ph->phy_lp_10_hdx = !!(lpar & MII_ABILITY_10BASE_T); 1466 ph->phy_lp_pause = !!(lpar & MII_ABILITY_PAUSE); 1467 ph->phy_lp_asmpause = !!(lpar & MII_ABILITY_ASMPAUSE); 1468 } 1469 1470 /* resolve link pause */ 1471 if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_BI) && 1472 (ph->phy_lp_pause)) { 1473 ph->phy_flowctrl = LINK_FLOWCTRL_BI; 1474 } else if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_RX) && 1475 (ph->phy_lp_pause || ph->phy_lp_asmpause)) { 1476 ph->phy_flowctrl = LINK_FLOWCTRL_RX; 1477 } else if ((ph->phy_en_flowctrl == LINK_FLOWCTRL_TX) && 1478 (ph->phy_lp_pause)) { 1479 ph->phy_flowctrl = LINK_FLOWCTRL_TX; 1480 } else { 1481 ph->phy_flowctrl = LINK_FLOWCTRL_NONE; 1482 } 1483 1484 if (ph->phy_adv_1000_fdx && ph->phy_lp_1000_fdx) { 1485 ph->phy_speed = 1000; 1486 ph->phy_duplex = LINK_DUPLEX_FULL; 1487 1488 } else if (ph->phy_adv_1000_hdx && ph->phy_lp_1000_hdx) { 1489 ph->phy_speed = 1000; 1490 ph->phy_duplex = LINK_DUPLEX_HALF; 1491 1492 } else if (ph->phy_adv_100_fdx && ph->phy_lp_100_fdx) { 1493 ph->phy_speed = 100; 1494 ph->phy_duplex = LINK_DUPLEX_FULL; 1495 1496 } else if (ph->phy_adv_100_t4 && ph->phy_lp_100_t4) { 1497 ph->phy_speed = 100; 1498 ph->phy_duplex = LINK_DUPLEX_HALF; 1499 1500 } else if (ph->phy_adv_100_hdx && ph->phy_lp_100_hdx) { 1501 ph->phy_speed = 100; 1502 ph->phy_duplex = LINK_DUPLEX_HALF; 1503 1504 } else if (ph->phy_adv_10_fdx && ph->phy_lp_10_fdx) { 1505 ph->phy_speed = 10; 1506 ph->phy_duplex = LINK_DUPLEX_FULL; 1507 1508 } else if (ph->phy_adv_10_hdx && ph->phy_lp_10_hdx) { 1509 ph->phy_speed = 10; 1510 ph->phy_duplex = LINK_DUPLEX_HALF; 1511 1512 } else { 1513 #ifdef DEBUG 1514 phy_warn(ph, "No common abilities."); 1515 #endif 1516 ph->phy_speed = 0; 1517 ph->phy_duplex = LINK_DUPLEX_UNKNOWN; 1518 } 1519 1520 return (DDI_SUCCESS); 1521 } 1522 1523 int 1524 phy_get_prop(phy_handle_t *ph, char *prop, int dflt) 1525 { 1526 mii_handle_t mh = ph->phy_mii; 1527 1528 return (ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0, prop, dflt)); 1529 } 1530 1531 const char * 1532 phy_get_name(phy_handle_t *ph) 1533 { 1534 mii_handle_t mh = ph->phy_mii; 1535 1536 return (mh->m_name); 1537 } 1538 1539 const char * 1540 phy_get_driver(phy_handle_t *ph) 1541 { 1542 mii_handle_t mh = ph->phy_mii; 1543 1544 return (ddi_driver_name(mh->m_dip)); 1545 } 1546 1547 void 1548 phy_warn(phy_handle_t *ph, const char *fmt, ...) 1549 { 1550 va_list va; 1551 char buf[256]; 1552 1553 (void) snprintf(buf, sizeof (buf), "%s: %s", phy_get_name(ph), fmt); 1554 1555 va_start(va, fmt); 1556 vcmn_err(CE_WARN, buf, va); 1557 va_end(va); 1558 } 1559 1560 /* 1561 * Internal support routines. 1562 */ 1563 1564 void 1565 _mii_probe_phy(phy_handle_t *ph) 1566 { 1567 uint16_t bmsr; 1568 uint16_t extsr; 1569 mii_handle_t mh = ph->phy_mii; 1570 1571 1572 /* 1573 * Apparently, PHY 0 is less likely to be physically 1574 * connected, and should always be the last one tried. Most 1575 * single solution NICs use PHY1 for their built-in 1576 * transceiver. NICs with an external MII will often place 1577 * the external PHY at address 1, and use address 0 for the 1578 * internal PHY. 1579 */ 1580 1581 ph->phy_id = 0; 1582 ph->phy_model = "PHY"; 1583 ph->phy_vendor = "Unknown Vendor"; 1584 1585 /* done twice to clear any latched bits */ 1586 bmsr = phy_read(ph, MII_STATUS); 1587 bmsr = phy_read(ph, MII_STATUS); 1588 if ((bmsr == 0) || (bmsr == 0xffff)) { 1589 ph->phy_present = B_FALSE; 1590 return; 1591 } 1592 1593 if (bmsr & MII_STATUS_EXTSTAT) { 1594 extsr = phy_read(ph, MII_EXTSTATUS); 1595 } else { 1596 extsr = 0; 1597 } 1598 1599 ph->phy_present = B_TRUE; 1600 ph->phy_id = ((uint32_t)phy_read(ph, MII_PHYIDH) << 16) | 1601 phy_read(ph, MII_PHYIDL); 1602 1603 /* setup default handlers */ 1604 ph->phy_reset = phy_reset; 1605 ph->phy_start = phy_start; 1606 ph->phy_stop = phy_stop; 1607 ph->phy_check = phy_check; 1608 1609 /* 1610 * We ignore the non-existent 100baseT2 stuff -- no 1611 * known products for it exist. 1612 */ 1613 ph->phy_cap_aneg = !!(bmsr & MII_STATUS_CANAUTONEG); 1614 ph->phy_cap_100_t4 = !!(bmsr & MII_STATUS_100_BASE_T4); 1615 ph->phy_cap_100_fdx = !!(bmsr & MII_STATUS_100_BASEX_FD); 1616 ph->phy_cap_100_hdx = !!(bmsr & MII_STATUS_100_BASEX); 1617 ph->phy_cap_10_fdx = !!(bmsr & MII_STATUS_10_FD); 1618 ph->phy_cap_10_hdx = !!(bmsr & MII_STATUS_10); 1619 ph->phy_cap_1000_fdx = 1620 !!(extsr & (MII_EXTSTATUS_1000X_FD|MII_EXTSTATUS_1000T_FD)); 1621 ph->phy_cap_1000_hdx = 1622 !!(extsr & (MII_EXTSTATUS_1000X | MII_EXTSTATUS_1000T)); 1623 ph->phy_cap_pause = mh->m_cap_pause; 1624 ph->phy_cap_asmpause = mh->m_cap_asmpause; 1625 1626 if (bmsr & MII_STATUS_10) { 1627 ph->phy_cap_10_hdx = B_TRUE; 1628 ph->phy_type = XCVR_10; 1629 } 1630 if (bmsr & MII_STATUS_10_FD) { 1631 ph->phy_cap_10_fdx = B_TRUE; 1632 ph->phy_type = XCVR_10; 1633 } 1634 if (bmsr & MII_STATUS_100T2) { 1635 ph->phy_cap_100_hdx = B_TRUE; 1636 ph->phy_type = XCVR_100T2; 1637 } 1638 if (bmsr & MII_STATUS_100T2_FD) { 1639 ph->phy_cap_100_fdx = B_TRUE; 1640 ph->phy_type = XCVR_100T2; 1641 } 1642 if (bmsr & MII_STATUS_100_BASE_T4) { 1643 ph->phy_cap_100_hdx = B_TRUE; 1644 ph->phy_type = XCVR_100T4; 1645 } 1646 if (bmsr & MII_STATUS_100_BASEX) { 1647 ph->phy_cap_100_hdx = B_TRUE; 1648 ph->phy_type = XCVR_100X; 1649 } 1650 if (bmsr & MII_STATUS_100_BASEX_FD) { 1651 ph->phy_cap_100_fdx = B_TRUE; 1652 ph->phy_type = XCVR_100X; 1653 } 1654 if (extsr & MII_EXTSTATUS_1000X) { 1655 ph->phy_cap_1000_hdx = B_TRUE; 1656 ph->phy_type = XCVR_1000X; 1657 } 1658 if (extsr & MII_EXTSTATUS_1000X_FD) { 1659 ph->phy_cap_1000_fdx = B_TRUE; 1660 ph->phy_type = XCVR_1000X; 1661 } 1662 if (extsr & MII_EXTSTATUS_1000T) { 1663 ph->phy_cap_1000_hdx = B_TRUE; 1664 ph->phy_type = XCVR_1000T; 1665 } 1666 if (extsr & MII_EXTSTATUS_1000T_FD) { 1667 ph->phy_cap_1000_fdx = B_TRUE; 1668 ph->phy_type = XCVR_1000T; 1669 } 1670 1671 for (int j = 0; _phy_probes[j] != NULL; j++) { 1672 if ((*_phy_probes[j])(ph)) { 1673 break; 1674 } 1675 } 1676 1677 #define INIT_ENABLE(CAP) \ 1678 ph->phy_en_##CAP = (mh->m_en_##CAP > 0) ? \ 1679 mh->m_en_##CAP : ph->phy_cap_##CAP 1680 1681 INIT_ENABLE(aneg); 1682 INIT_ENABLE(1000_fdx); 1683 INIT_ENABLE(1000_hdx); 1684 INIT_ENABLE(100_fdx); 1685 INIT_ENABLE(100_t4); 1686 INIT_ENABLE(100_hdx); 1687 INIT_ENABLE(10_fdx); 1688 INIT_ENABLE(10_hdx); 1689 1690 #undef INIT_ENABLE 1691 ph->phy_en_flowctrl = mh->m_en_flowctrl; 1692 switch (ph->phy_en_flowctrl) { 1693 case LINK_FLOWCTRL_BI: 1694 case LINK_FLOWCTRL_RX: 1695 ph->phy_en_pause = B_TRUE; 1696 ph->phy_en_asmpause = B_TRUE; 1697 break; 1698 case LINK_FLOWCTRL_TX: 1699 ph->phy_en_pause = B_FALSE; 1700 ph->phy_en_asmpause = B_TRUE; 1701 break; 1702 default: 1703 ph->phy_en_pause = B_FALSE; 1704 ph->phy_en_asmpause = B_FALSE; 1705 break; 1706 } 1707 } 1708 1709 void 1710 _mii_probe_task(mii_handle_t mh) 1711 { 1712 uint8_t new_addr; 1713 uint8_t old_addr; 1714 uint8_t user_addr; 1715 uint8_t curr_addr; 1716 phy_handle_t *ph; 1717 int pri = 0; 1718 1719 user_addr = ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0, 1720 "phy-addr", -1); 1721 old_addr = mh->m_addr; 1722 new_addr = 0xff; 1723 1724 /* 1725 * Apparently, PHY 0 is less likely to be physically 1726 * connected, and should always be the last one tried. Most 1727 * single solution NICs use PHY1 for their built-in 1728 * transceiver. NICs with an external MII will often place 1729 * the external PHY at address 1, and use address 0 for the 1730 * internal PHY. 1731 */ 1732 1733 for (int i = 1; i < 33; i++) { 1734 1735 /* 1736 * This is tricky: it lets us try 0 last by starting 1737 * loop at 1 instead of 0. 1738 */ 1739 curr_addr = i % 32; 1740 1741 ph = &mh->m_phys[curr_addr]; 1742 1743 bzero(ph, sizeof (*ph)); 1744 ph->phy_addr = curr_addr; 1745 ph->phy_mii = mh; 1746 1747 _mii_probe_phy(ph); 1748 1749 if (!ph->phy_present) 1750 continue; 1751 1752 if (curr_addr == user_addr) { 1753 /* 1754 * We always try to honor the user configured phy. 1755 */ 1756 new_addr = curr_addr; 1757 pri = 4; 1758 1759 } 1760 1761 /* two reads to clear latched bits */ 1762 if ((phy_read(ph, MII_STATUS) & MII_STATUS_LINKUP) && 1763 (phy_read(ph, MII_STATUS) & MII_STATUS_LINKUP) && 1764 (pri < 3)) { 1765 /* 1766 * Link present is good. We prefer this over 1767 * a possibly disconnected link. 1768 */ 1769 new_addr = curr_addr; 1770 pri = 3; 1771 } 1772 if ((curr_addr == old_addr) && (pri < 2)) { 1773 /* 1774 * All else being equal, minimize change. 1775 */ 1776 new_addr = curr_addr; 1777 pri = 2; 1778 1779 } 1780 if (pri < 1) { 1781 /* 1782 * But make sure we at least select a present PHY. 1783 */ 1784 new_addr = curr_addr; 1785 pri = 1; 1786 } 1787 } 1788 1789 if (new_addr == 0xff) { 1790 mh->m_addr = -1; 1791 mh->m_phy = &mh->m_bogus_phy; 1792 _mii_error(mh, MII_ENOPHY); 1793 } else { 1794 mh->m_addr = new_addr; 1795 mh->m_phy = &mh->m_phys[new_addr]; 1796 mh->m_tstate = MII_STATE_RESET; 1797 cmn_err(CE_CONT, "?%s: Using %s Ethernet PHY at %d: %s %s\n", 1798 mh->m_name, mii_xcvr_types[mh->m_phy->phy_type], 1799 mh->m_addr, mh->m_phy->phy_vendor, mh->m_phy->phy_model); 1800 } 1801 } 1802 1803 static int 1804 _mii_reset_task(mii_handle_t mh) 1805 { 1806 phy_handle_t *ph; 1807 1808 ASSERT(mutex_owned(&mh->m_lock)); 1809 1810 /* 1811 * Reset logic. We want to isolate all the other 1812 * phys that are not in use. 1813 */ 1814 for (int i = 0; i < 32; i++) { 1815 ph = &mh->m_phys[i]; 1816 1817 if (!ph->phy_present) 1818 continue; 1819 1820 /* don't touch our own phy, yet */ 1821 if (ph == mh->m_phy) 1822 continue; 1823 1824 ph->phy_stop(ph); 1825 } 1826 1827 ph = mh->m_phy; 1828 1829 ASSERT(ph->phy_present); 1830 1831 /* If we're resetting the PHY, then for sure we want to notify */ 1832 mh->m_notify = B_TRUE; 1833 1834 if (ph->phy_reset(ph) != DDI_SUCCESS) { 1835 _mii_error(mh, MII_ERESET); 1836 return (DDI_FAILURE); 1837 } 1838 1839 mh->m_tstate = MII_STATE_START; 1840 return (DDI_SUCCESS); 1841 } 1842 1843 static void 1844 _mii_start_task(mii_handle_t mh) 1845 { 1846 phy_handle_t *ph; 1847 1848 ph = mh->m_phy; 1849 1850 ASSERT(mutex_owned(&mh->m_lock)); 1851 ASSERT(ph->phy_present); 1852 1853 if (phy_start(ph) != DDI_SUCCESS) { 1854 _mii_error(mh, MII_ESTART); 1855 mh->m_tstate = MII_STATE_RESET; 1856 return; 1857 } 1858 /* clear the error state since we got a good startup! */ 1859 mh->m_error = MII_EOK; 1860 mh->m_tstate = MII_STATE_RUN; 1861 } 1862 1863 static int 1864 _mii_check_task(mii_handle_t mh) 1865 { 1866 link_state_t olink; 1867 int ospeed; 1868 link_duplex_t oduplex; 1869 link_flowctrl_t ofctrl; 1870 phy_handle_t *ph; 1871 1872 ph = mh->m_phy; 1873 1874 olink = mh->m_link; 1875 ospeed = ph->phy_speed; 1876 oduplex = ph->phy_duplex; 1877 ofctrl = ph->phy_flowctrl; 1878 1879 ASSERT(ph->phy_present); 1880 1881 if (ph->phy_check(ph) == DDI_FAILURE) { 1882 _mii_error(mh, MII_ECHECK); 1883 mh->m_link = LINK_STATE_UNKNOWN; 1884 mh->m_tstate = MII_STATE_PROBE; 1885 mh->m_notify = B_TRUE; 1886 return (DDI_FAILURE); 1887 } 1888 1889 mh->m_link = ph->phy_link; 1890 1891 /* if anything changed, notify! */ 1892 if ((mh->m_link != olink) || 1893 (ph->phy_speed != ospeed) || 1894 (ph->phy_duplex != oduplex) || 1895 (ph->phy_flowctrl != ofctrl)) { 1896 mh->m_notify = B_TRUE; 1897 } 1898 1899 return (DDI_SUCCESS); 1900 } 1901 1902 static void 1903 _mii_task(void *_mh) 1904 { 1905 mii_handle_t mh = _mh; 1906 phy_handle_t *ph; 1907 clock_t wait; 1908 clock_t downtime; 1909 1910 mutex_enter(&mh->m_lock); 1911 1912 for (;;) { 1913 1914 /* If detaching, exit the thread. */ 1915 if (!mh->m_started) { 1916 break; 1917 } 1918 1919 ph = mh->m_phy; 1920 1921 /* 1922 * If we're suspended or otherwise not supposed to be 1923 * monitoring the link, just go back to sleep. 1924 * 1925 * Theoretically we could power down the PHY, but we 1926 * don't bother. (The link might be used for 1927 * wake-on-lan!) Another option would be to reduce 1928 * power on the PHY if both it and the link partner 1929 * support 10 Mbps mode. 1930 */ 1931 if (mh->m_suspending) { 1932 mh->m_suspended = B_TRUE; 1933 cv_broadcast(&mh->m_cv); 1934 } 1935 if (mh->m_suspended) { 1936 mh->m_suspending = B_FALSE; 1937 cv_wait(&mh->m_cv, &mh->m_lock); 1938 continue; 1939 } 1940 1941 switch (mh->m_tstate) { 1942 case MII_STATE_PROBE: 1943 _mii_probe_task(mh); 1944 ph = mh->m_phy; 1945 if (!ph->phy_present) { 1946 /* 1947 * If no PHY is found, wait a bit before 1948 * trying the probe again. 10 seconds ought 1949 * to be enough. 1950 */ 1951 wait = 10 * MII_SECOND; 1952 } else { 1953 wait = 0; 1954 } 1955 break; 1956 1957 case MII_STATE_RESET: 1958 if (_mii_reset_task(mh) == DDI_SUCCESS) { 1959 ASSERT(mh->m_tstate == MII_STATE_START); 1960 1961 /* 1962 * We have to go back to the top of 1963 * the routine to check for changed 1964 * conditions while we drop the lock 1965 * to call into the mac layer. 1966 */ 1967 if (mh->m_ops.mii_reset != NULL) { 1968 mutex_exit(&mh->m_lock); 1969 mh->m_ops.mii_reset(mh->m_private); 1970 mutex_enter(&mh->m_lock); 1971 continue; 1972 } 1973 wait = 0; 1974 } else { 1975 /* 1976 * If an error occurred, wait a bit and 1977 * try again later. 1978 */ 1979 wait = 10 * MII_SECOND; 1980 } 1981 break; 1982 1983 case MII_STATE_START: 1984 /* 1985 * If an error occurs, we're going to go back to 1986 * probe or reset state. Otherwise we go to run 1987 * state. In all cases we want to wait 1 second 1988 * before doing anything else - either for link to 1989 * settle, or to give other code a chance to run 1990 * while we reset. 1991 */ 1992 _mii_start_task(mh); 1993 /* reset watchdog to latest */ 1994 downtime = ddi_get_lbolt(); 1995 wait = MII_SECOND; 1996 break; 1997 1998 case MII_STATE_RUN: 1999 default: 2000 if (_mii_check_task(mh) == DDI_FAILURE) { 2001 /* 2002 * On error (PHY removed?), wait a 2003 * short bit before reprobing or 2004 * resetting. 2005 */ 2006 wait = MII_SECOND; 2007 2008 } else if (mh->m_link == LINK_STATE_UP) { 2009 /* got goood link, so reset the watchdog */ 2010 downtime = ddi_get_lbolt(); 2011 /* rescan again in a second */ 2012 wait = MII_SECOND; 2013 2014 } else if ((ddi_get_lbolt() - downtime) > 2015 (drv_usectohz(MII_SECOND * 10))) { 2016 2017 /* 2018 * If we were down for 10 seconds, 2019 * hard reset the PHY. 2020 */ 2021 mh->m_tstate = MII_STATE_RESET; 2022 wait = 0; 2023 2024 } else { 2025 /* 2026 * Otherwise, if we are still down, 2027 * rescan the link much more 2028 * frequently. We might be trying to 2029 * autonegotiate. 2030 */ 2031 wait = MII_SECOND / 4; 2032 } 2033 break; 2034 } 2035 2036 if (mh->m_notify) { 2037 mh->m_notify = B_FALSE; 2038 2039 if (mh->m_ops.mii_notify != NULL) { 2040 link_state_t state = mh->m_link; 2041 mutex_exit(&mh->m_lock); 2042 mh->m_ops.mii_notify(mh->m_private, state); 2043 mutex_enter(&mh->m_lock); 2044 continue; 2045 } 2046 } 2047 2048 if (wait) 2049 (void) cv_timedwait(&mh->m_cv, &mh->m_lock, 2050 ddi_get_lbolt() + drv_usectohz(wait)); 2051 } 2052 2053 mutex_exit(&mh->m_lock); 2054 } 2055