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