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