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