9348 mii: duplicate 'const' declaration specifier
[unleashed.git] / usr / src / uts / common / io / mii / mii.c
blobb02489978364e16da2ed6b02d50bfd69399c95f0
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * mii - MII/PHY support for MAC drivers
29 * Utility module to provide a consistent interface to a MAC driver accross
30 * different implementations of PHY devices
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"
52 #define MII_SECOND 1000000
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,
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."
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"
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;
94 struct mii_handle {
95 dev_info_t *m_dip;
96 void *m_private;
97 mii_ops_t m_ops;
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;
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;
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 */
120 /* device name for printing, e.g. "hme0" */
121 char m_name[MODMAXNAMELEN + 16];
123 int m_addr;
124 phy_handle_t m_phys[32];
125 phy_handle_t m_bogus_phy;
126 phy_handle_t *m_phy;
128 link_state_t m_link;
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;
141 boolean_t m_cap_pause;
142 boolean_t m_cap_asmpause;
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);
156 * Loadable module structures/entrypoints
159 extern struct mod_ops mod_misc_ops;
161 static struct modlmisc modlmisc = {
162 &mod_miscops,
163 "802.3 MII support",
166 static struct modlinkage modlinkage = {
167 MODREV_1, &modlmisc, NULL
171 _init(void)
173 return (mod_install(&modlinkage));
177 _fini(void)
179 return (mod_remove(&modlinkage));
183 _info(struct modinfo *modinfop)
185 return (mod_info(&modlinkage, modinfop));
188 void
189 _mii_error(mii_handle_t mh, int errno)
192 * This dumps an error message, but it avoids filling the log with
193 * repeated error messages.
195 if (mh->m_error != errno) {
196 cmn_err(CE_WARN, "%s: %s", mh->m_name, mii_errors[errno]);
197 mh->m_error = errno;
202 * Known list of specific PHY probes.
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
217 * MII Interface functions
220 mii_handle_t
221 mii_alloc_instance(void *private, dev_info_t *dip, int inst, mii_ops_t *ops)
223 mii_handle_t mh;
224 char tqname[16];
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);
231 mh = kmem_zalloc(sizeof (*mh), KM_SLEEP);
233 (void) snprintf(mh->m_name, sizeof (mh->m_name), "%s%d",
234 ddi_driver_name(dip), inst);
236 /* DDI will prepend the driver name */
237 (void) snprintf(tqname, sizeof (tqname), "mii%d", inst);
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);
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);
262 * Initialize user prefs by loading properties. Ultimately,
263 * Brussels interfaces would be superior here.
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");
275 mh->m_cap_pause = B_FALSE;
276 mh->m_cap_asmpause = B_FALSE;
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;
288 for (int i = 0; i < 32; i++) {
289 mh->m_phys[i].phy_mii = mh;
291 mh->m_bogus_phy.phy_mii = mh;
293 return (mh);
296 mii_handle_t
297 mii_alloc(void *private, dev_info_t *dip, mii_ops_t *ops)
299 return (mii_alloc_instance(private, dip, ddi_get_instance(dip), ops));
302 void
303 mii_set_pauseable(mii_handle_t mh, boolean_t pauseable, boolean_t asymetric)
305 phy_handle_t *ph;
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;
316 mutex_exit(&mh->m_lock);
319 void
320 mii_free(mii_handle_t mh)
322 mutex_enter(&mh->m_lock);
323 mh->m_started = B_FALSE;
324 cv_broadcast(&mh->m_cv);
325 mutex_exit(&mh->m_lock);
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));
333 void
334 mii_reset(mii_handle_t mh)
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);
343 void
344 mii_suspend(mii_handle_t mh)
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);
352 mutex_exit(&mh->m_lock);
355 void
356 mii_resume(mii_handle_t mh)
358 mutex_enter(&mh->m_lock);
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;
370 case MII_STATE_LOOPBACK:
371 /* loopback is handled synchronously */
372 (void) _mii_loopback(mh);
373 break;
376 mh->m_suspended = B_FALSE;
377 cv_broadcast(&mh->m_cv);
378 mutex_exit(&mh->m_lock);
381 void
382 mii_start(mii_handle_t mh)
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;
396 cv_broadcast(&mh->m_cv);
397 mutex_exit(&mh->m_lock);
400 void
401 mii_stop(mii_handle_t mh)
403 mutex_enter(&mh->m_lock);
404 mh->m_started = B_FALSE;
406 * Reset link state to unknown defaults, since we're not
407 * monitoring it anymore. We'll reprobe all link state later.
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);
414 * Notify the MAC driver. This will allow it to call back
415 * into the MAC framework to clear any previous link state.
417 _mii_notify(mh);
420 void
421 mii_probe(mii_handle_t mh)
423 mutex_enter(&mh->m_lock);
424 _mii_probe(mh);
425 mutex_exit(&mh->m_lock);
428 void
429 mii_check(mii_handle_t mh)
431 mutex_enter(&mh->m_lock);
432 cv_broadcast(&mh->m_cv);
433 mutex_exit(&mh->m_lock);
437 mii_get_speed(mii_handle_t mh)
439 phy_handle_t *ph = mh->m_phy;
441 return (ph->phy_speed);
444 link_duplex_t
445 mii_get_duplex(mii_handle_t mh)
447 phy_handle_t *ph = mh->m_phy;
449 return (ph->phy_duplex);
452 link_state_t
453 mii_get_state(mii_handle_t mh)
455 phy_handle_t *ph = mh->m_phy;
457 return (ph->phy_link);
460 link_flowctrl_t
461 mii_get_flowctrl(mii_handle_t mh)
463 phy_handle_t *ph = mh->m_phy;
465 return (ph->phy_flowctrl);
469 mii_get_loopmodes(mii_handle_t mh, lb_property_t *modes)
471 phy_handle_t *ph = mh->m_phy;
472 int cnt = 0;
473 lb_property_t lmodes[MII_LOOPBACK_MAX];
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++;
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++;
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++;
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++;
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++;
515 if (modes) {
516 bcopy(lmodes, modes, sizeof (lb_property_t) * cnt);
519 return (cnt);
522 uint32_t
523 mii_get_loopback(mii_handle_t mh)
525 phy_handle_t *ph = mh->m_phy;
527 return (ph->phy_loopback);
531 mii_set_loopback(mii_handle_t mh, uint32_t loop)
533 phy_handle_t *ph;
534 int rv;
536 mutex_enter(&mh->m_lock);
537 ph = mh->m_phy;
539 if ((!mh->m_started) || (!ph->phy_present) ||
540 (loop >= mii_get_loopmodes(mh, NULL))) {
541 return (EINVAL);
544 ph->phy_loopback = loop;
545 rv = _mii_loopback(mh);
546 if (rv == DDI_SUCCESS) {
547 mh->m_tstate = MII_STATE_LOOPBACK;
549 cv_broadcast(&mh->m_cv);
550 mutex_exit(&mh->m_lock);
552 return (rv == DDI_SUCCESS ? 0 : EIO);
555 uint32_t
556 mii_get_id(mii_handle_t mh)
558 phy_handle_t *ph = mh->m_phy;
560 return (ph->phy_id);
564 mii_get_addr(mii_handle_t mh)
566 return (mh->m_addr);
569 /* GLDv3 helpers */
571 boolean_t
572 mii_m_loop_ioctl(mii_handle_t mh, queue_t *wq, mblk_t *mp)
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;
582 iocp = (void *)mp->b_rptr;
583 cmd = iocp->ioc_cmd;
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;
592 default:
593 return (B_FALSE);
596 if (mp->b_cont == NULL) {
597 miocnak(wq, mp, 0, EINVAL);
598 return (B_TRUE);
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));
610 break;
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);
619 break;
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));
628 break;
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;
638 bcopy(mp->b_cont->b_rptr, &mode, sizeof (mode));
639 rv = mii_set_loopback(mh, mode);
640 break;
643 if (rv == 0) {
644 miocack(wq, mp, iocp->ioc_count, 0);
645 } else {
646 miocnak(wq, mp, 0, rv);
648 return (B_TRUE);
652 mii_m_getprop(mii_handle_t mh, const char *name, mac_prop_id_t num,
653 uint_t sz, void *val)
655 phy_handle_t *ph;
656 int err = 0;
658 _NOTE(ARGUNUSED(name));
660 if (sz < 1)
661 return (EINVAL);
663 mutex_enter(&mh->m_lock);
665 ph = mh->m_phy;
667 #define CASE_PROP_ABILITY(PROP, VAR) \
668 case MAC_PROP_ADV_##PROP: \
669 *(uint8_t *)val = ph->phy_adv_##VAR; \
670 break; \
672 case MAC_PROP_EN_##PROP: \
673 *(uint8_t *)val = ph->phy_en_##VAR; \
674 break;
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;
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;
689 case MAC_PROP_AUTONEG:
690 *(uint8_t *)val = ph->phy_adv_aneg;
691 break;
693 case MAC_PROP_FLOWCTRL:
694 ASSERT(sz >= sizeof (link_flowctrl_t));
695 bcopy(&ph->phy_flowctrl, val, sizeof (link_flowctrl_t));
696 break;
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)
706 default:
707 err = ENOTSUP;
708 break;
711 mutex_exit(&mh->m_lock);
713 return (err);
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)
720 phy_handle_t *ph;
722 _NOTE(ARGUNUSED(name));
724 mutex_enter(&mh->m_lock);
726 ph = mh->m_phy;
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;
734 case MAC_PROP_AUTONEG:
735 mac_prop_info_set_default_uint8(prh, ph->phy_cap_aneg);
736 break;
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; \
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;
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)
759 mutex_exit(&mh->m_lock);
763 mii_m_setprop(mii_handle_t mh, const char *name, mac_prop_id_t num,
764 uint_t sz, const void *valp)
766 phy_handle_t *ph;
767 boolean_t *advp = NULL;
768 boolean_t *capp = NULL;
769 int *macpp = NULL;
770 int rv = ENOTSUP;
772 _NOTE(ARGUNUSED(name));
774 if (sz < 1)
775 return (EINVAL);
777 mutex_enter(&mh->m_lock);
779 ph = mh->m_phy;
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);
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;
842 ASSERT(sz >= sizeof (link_flowctrl_t));
843 bcopy(valp, &fc, sizeof (fc));
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;
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.
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;
868 break;
871 * Tell the other side that we can assert pause, but
872 * we cannot resend.
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;
882 break;
883 default:
884 rv = EINVAL;
885 break;
887 if ((rv == 0) && chg) {
888 mh->m_en_flowctrl = fc;
889 mh->m_tstate = MII_STATE_RESET;
890 cv_broadcast(&mh->m_cv);
892 break;
895 default:
896 rv = ENOTSUP;
897 break;
900 if (capp && advp && macpp) {
901 if (sz < sizeof (uint8_t)) {
902 rv = EINVAL;
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);
911 rv = 0;
915 mutex_exit(&mh->m_lock);
916 return (rv);
920 mii_m_getstat(mii_handle_t mh, uint_t stat, uint64_t *val)
922 phy_handle_t *ph;
923 int rv = 0;
925 mutex_enter(&mh->m_lock);
927 ph = mh->m_phy;
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;
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;
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;
1049 default:
1050 rv = ENOTSUP;
1051 break;
1053 mutex_exit(&mh->m_lock);
1055 return (rv);
1059 * PHY support routines. Private to the MII module and the vendor
1060 * specific PHY implementation code.
1062 uint16_t
1063 phy_read(phy_handle_t *ph, uint8_t reg)
1065 mii_handle_t mh = ph->phy_mii;
1067 return ((*mh->m_ops.mii_read)(mh->m_private, ph->phy_addr, reg));
1070 void
1071 phy_write(phy_handle_t *ph, uint8_t reg, uint16_t val)
1073 mii_handle_t mh = ph->phy_mii;
1075 (*mh->m_ops.mii_write)(mh->m_private, ph->phy_addr, reg, val);
1079 phy_reset(phy_handle_t *ph)
1081 ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1084 * For our device, make sure its powered up and unisolated.
1086 PHY_CLR(ph, MII_CONTROL,
1087 MII_CONTROL_PWRDN | MII_CONTROL_ISOLATE);
1090 * Finally reset it.
1092 PHY_SET(ph, MII_CONTROL, MII_CONTROL_RESET);
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.
1099 drv_usecwait(500);
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.
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);
1115 drv_usecwait(100);
1118 return (DDI_FAILURE);
1122 phy_stop(phy_handle_t *ph)
1124 phy_write(ph, MII_CONTROL, MII_CONTROL_ISOLATE);
1126 return (DDI_SUCCESS);
1130 phy_loop(phy_handle_t *ph)
1132 uint16_t bmcr, gtcr;
1134 ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1137 * Disable everything to start... we'll add in modes as we go.
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;
1150 bmcr = 0;
1151 gtcr = MII_MSCONTROL_MANUAL | MII_MSCONTROL_MASTER;
1153 switch (ph->phy_loopback) {
1154 case PHY_LB_NONE:
1155 /* We shouldn't be here */
1156 ASSERT(0);
1157 break;
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;
1172 break;
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;
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;
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;
1193 ph->phy_link = LINK_STATE_UP; /* force up for loopback */
1194 ph->phy_flowctrl = LINK_FLOWCTRL_NONE;
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;
1204 phy_write(ph, MII_CONTROL, bmcr);
1206 return (DDI_SUCCESS);
1210 phy_start(phy_handle_t *ph)
1212 uint16_t bmcr, anar, gtcr;
1213 ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1215 ASSERT(ph->phy_loopback == PHY_LB_NONE);
1218 * No loopback overrides, so try to advertise everything
1219 * that is administratively enabled.
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;
1233 * Limit properties to what the hardware can actually support.
1235 #define FILTER_ADV(CAP) \
1236 if (!ph->phy_cap_##CAP) \
1237 ph->phy_adv_##CAP = 0
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);
1250 #undef FILTER_ADV
1253 * We need at least one valid mode.
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)) {
1263 phy_warn(ph,
1264 "No valid link mode selected. Powering down PHY.");
1266 PHY_SET(ph, MII_CONTROL, MII_CONTROL_PWRDN);
1268 ph->phy_link = LINK_STATE_DOWN;
1269 return (DDI_SUCCESS);
1272 bmcr = 0;
1273 gtcr = 0;
1275 if (ph->phy_adv_aneg) {
1276 bmcr |= MII_CONTROL_ANE | MII_CONTROL_RSAN;
1279 if ((ph->phy_adv_1000_fdx) || (ph->phy_adv_1000_hdx)) {
1280 bmcr |= MII_CONTROL_1GB;
1282 } else if (ph->phy_adv_100_fdx || ph->phy_adv_100_hdx ||
1283 ph->phy_adv_100_t4) {
1284 bmcr |= MII_CONTROL_100MB;
1287 if (ph->phy_adv_1000_fdx || ph->phy_adv_100_fdx || ph->phy_adv_10_fdx) {
1288 bmcr |= MII_CONTROL_FDUPLEX;
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;
1297 if (ph->phy_adv_1000_hdx) {
1298 anar |= MII_ABILITY_X_HD;
1300 if (ph->phy_adv_pause) {
1301 anar |= MII_ABILITY_X_PAUSE;
1303 if (ph->phy_adv_asmpause) {
1304 anar |= MII_ABILITY_X_ASMPAUSE;
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;
1313 if (ph->phy_adv_100_hdx) {
1314 anar |= MII_ABILITY_T2_HD;
1317 } else {
1318 anar = MII_AN_SELECTOR_8023;
1320 /* 1000BASE-T or 100BASE-X probably */
1321 if (ph->phy_adv_1000_fdx) {
1322 gtcr |= MII_MSCONTROL_1000T_FD;
1324 if (ph->phy_adv_1000_hdx) {
1325 gtcr |= MII_MSCONTROL_1000T;
1327 if (ph->phy_adv_100_fdx) {
1328 anar |= MII_ABILITY_100BASE_TX_FD;
1330 if (ph->phy_adv_100_hdx) {
1331 anar |= MII_ABILITY_100BASE_TX;
1333 if (ph->phy_adv_100_t4) {
1334 anar |= MII_ABILITY_100BASE_T4;
1336 if (ph->phy_adv_10_fdx) {
1337 anar |= MII_ABILITY_10BASE_T_FD;
1339 if (ph->phy_adv_10_hdx) {
1340 anar |= MII_ABILITY_10BASE_T;
1342 if (ph->phy_adv_pause) {
1343 anar |= MII_ABILITY_PAUSE;
1345 if (ph->phy_adv_asmpause) {
1346 anar |= MII_ABILITY_ASMPAUSE;
1350 ph->phy_link = LINK_STATE_DOWN;
1351 ph->phy_duplex = LINK_DUPLEX_UNKNOWN;
1352 ph->phy_speed = 0;
1354 phy_write(ph, MII_AN_ADVERT, anar);
1355 phy_write(ph, MII_CONTROL, bmcr & ~(MII_CONTROL_RSAN));
1357 switch (ph->phy_type) {
1358 case XCVR_1000T:
1359 case XCVR_1000X:
1360 case XCVR_100T2:
1361 phy_write(ph, MII_MSCONTROL, gtcr);
1365 * Finally, this will start up autoneg if it is enabled, or
1366 * force link settings otherwise.
1368 phy_write(ph, MII_CONTROL, bmcr);
1370 return (DDI_SUCCESS);
1375 phy_check(phy_handle_t *ph)
1377 uint16_t control, status, lpar, msstat, anexp;
1378 int debounces = 100;
1380 ASSERT(mutex_owned(&ph->phy_mii->m_lock));
1382 debounce:
1383 status = phy_read(ph, MII_STATUS);
1384 control = phy_read(ph, MII_CONTROL);
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;
1395 * We reread to clear any latched bits. This also debounces
1396 * any state that might be in transition.
1398 drv_usecwait(10);
1399 if ((status != phy_read(ph, MII_STATUS)) && debounces) {
1400 debounces--;
1401 goto debounce;
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.
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);
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);
1426 ph->phy_link = LINK_STATE_UP;
1428 if ((control & MII_CONTROL_ANE) == 0) {
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;
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.
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;
1451 ph->phy_duplex = control & MII_CONTROL_FDUPLEX ?
1452 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
1454 return (DDI_SUCCESS);
1457 if (ph->phy_type == XCVR_1000X) {
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;
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);
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;
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);
1486 } else if (anexp & MII_AN_EXP_PARFAULT) {
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.
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);
1512 } else {
1513 ph->phy_lp_aneg = !!(anexp & MII_AN_EXP_LPCANAN);
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.
1522 if ((ph->phy_type == XCVR_1000T) &
1523 (anexp & MII_AN_EXP_LPCANAN)) {
1525 /* check for gige */
1526 msstat = phy_read(ph, MII_MSSTATUS);
1528 ph->phy_lp_1000_hdx =
1529 !!(msstat & MII_MSSTATUS_LP1000T);
1531 ph->phy_lp_1000_fdx =
1532 !!(msstat & MII_MSSTATUS_LP1000T_FD);
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);
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;
1558 if (ph->phy_adv_1000_fdx && ph->phy_lp_1000_fdx) {
1559 ph->phy_speed = 1000;
1560 ph->phy_duplex = LINK_DUPLEX_FULL;
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;
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;
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;
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;
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;
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;
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;
1594 return (DDI_SUCCESS);
1598 phy_get_prop(phy_handle_t *ph, char *prop, int dflt)
1600 mii_handle_t mh = ph->phy_mii;
1602 return (ddi_prop_get_int(DDI_DEV_T_ANY, mh->m_dip, 0, prop, dflt));
1605 const char *
1606 phy_get_name(phy_handle_t *ph)
1608 mii_handle_t mh = ph->phy_mii;
1610 return (mh->m_name);
1613 const char *
1614 phy_get_driver(phy_handle_t *ph)
1616 mii_handle_t mh = ph->phy_mii;
1618 return (ddi_driver_name(mh->m_dip));
1621 void
1622 phy_warn(phy_handle_t *ph, const char *fmt, ...)
1624 va_list va;
1625 char buf[256];
1627 (void) snprintf(buf, sizeof (buf), "%s: %s", phy_get_name(ph), fmt);
1629 va_start(va, fmt);
1630 vcmn_err(CE_WARN, buf, va);
1631 va_end(va);
1635 * Internal support routines.
1638 void
1639 _mii_notify(mii_handle_t mh)
1641 if (mh->m_ops.mii_notify != NULL) {
1642 mh->m_ops.mii_notify(mh->m_private, mh->m_link);
1646 void
1647 _mii_probe_phy(phy_handle_t *ph)
1649 uint16_t bmsr;
1650 uint16_t extsr;
1651 mii_handle_t mh = ph->phy_mii;
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.
1663 ph->phy_id = 0;
1664 ph->phy_model = "PHY";
1665 ph->phy_vendor = "Unknown Vendor";
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;
1675 if (bmsr & MII_STATUS_EXTSTAT) {
1676 extsr = phy_read(ph, MII_EXTSTATUS);
1677 } else {
1678 extsr = 0;
1681 ph->phy_present = B_TRUE;
1682 ph->phy_id = ((uint32_t)phy_read(ph, MII_PHYIDH) << 16) |
1683 phy_read(ph, MII_PHYIDL);
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;
1693 * We ignore the non-existent 100baseT2 stuff -- no
1694 * known products for it exist.
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;
1709 if (bmsr & MII_STATUS_10) {
1710 ph->phy_cap_10_hdx = B_TRUE;
1711 ph->phy_type = XCVR_10;
1713 if (bmsr & MII_STATUS_10_FD) {
1714 ph->phy_cap_10_fdx = B_TRUE;
1715 ph->phy_type = XCVR_10;
1717 if (bmsr & MII_STATUS_100T2) {
1718 ph->phy_cap_100_hdx = B_TRUE;
1719 ph->phy_type = XCVR_100T2;
1721 if (bmsr & MII_STATUS_100T2_FD) {
1722 ph->phy_cap_100_fdx = B_TRUE;
1723 ph->phy_type = XCVR_100T2;
1725 if (bmsr & MII_STATUS_100_BASE_T4) {
1726 ph->phy_cap_100_hdx = B_TRUE;
1727 ph->phy_type = XCVR_100T4;
1729 if (bmsr & MII_STATUS_100_BASEX) {
1730 ph->phy_cap_100_hdx = B_TRUE;
1731 ph->phy_type = XCVR_100X;
1733 if (bmsr & MII_STATUS_100_BASEX_FD) {
1734 ph->phy_cap_100_fdx = B_TRUE;
1735 ph->phy_type = XCVR_100X;
1737 if (extsr & MII_EXTSTATUS_1000X) {
1738 ph->phy_cap_1000_hdx = B_TRUE;
1739 ph->phy_type = XCVR_1000X;
1741 if (extsr & MII_EXTSTATUS_1000X_FD) {
1742 ph->phy_cap_1000_fdx = B_TRUE;
1743 ph->phy_type = XCVR_1000X;
1745 if (extsr & MII_EXTSTATUS_1000T) {
1746 ph->phy_cap_1000_hdx = B_TRUE;
1747 ph->phy_type = XCVR_1000T;
1749 if (extsr & MII_EXTSTATUS_1000T_FD) {
1750 ph->phy_cap_1000_fdx = B_TRUE;
1751 ph->phy_type = XCVR_1000T;
1754 for (int j = 0; _phy_probes[j] != NULL; j++) {
1755 if ((*_phy_probes[j])(ph)) {
1756 break;
1760 #define INIT_ENABLE(CAP) \
1761 ph->phy_en_##CAP = (mh->m_en_##CAP > 0) ? \
1762 mh->m_en_##CAP : ph->phy_cap_##CAP
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);
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;
1792 void
1793 _mii_probe(mii_handle_t mh)
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;
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;
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.
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.
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;
1825 for (int i = first; i < (first + 32); i++) {
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.
1832 curr_addr = i % 32;
1834 ph = &mh->m_phys[curr_addr];
1836 bzero(ph, sizeof (*ph));
1837 ph->phy_addr = curr_addr;
1838 ph->phy_mii = mh;
1840 _mii_probe_phy(ph);
1842 if (!ph->phy_present)
1843 continue;
1845 if (curr_addr == user_addr) {
1847 * We always try to honor the user configured phy.
1849 new_addr = curr_addr;
1850 pri = 4;
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)) {
1859 * Link present is good. We prefer this over
1860 * a possibly disconnected link.
1862 new_addr = curr_addr;
1863 pri = 3;
1865 if ((curr_addr == old_addr) && (pri < 2)) {
1867 * All else being equal, minimize change.
1869 new_addr = curr_addr;
1870 pri = 2;
1873 if (pri < 1) {
1875 * But make sure we at least select a present PHY.
1877 new_addr = curr_addr;
1878 pri = 1;
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;
1902 _mii_reset(mii_handle_t mh)
1904 phy_handle_t *ph;
1905 boolean_t notify;
1907 ASSERT(mutex_owned(&mh->m_lock));
1910 * Reset logic. We want to isolate all the other
1911 * phys that are not in use.
1913 for (int i = 0; i < 32; i++) {
1914 ph = &mh->m_phys[i];
1916 if (!ph->phy_present)
1917 continue;
1919 /* Don't touch our own phy, yet. */
1920 if (ph == mh->m_phy)
1921 continue;
1923 ph->phy_stop(ph);
1926 ph = mh->m_phy;
1928 ASSERT(ph->phy_present);
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;
1937 if (ph->phy_reset(ph) != DDI_SUCCESS) {
1938 _mii_error(mh, MII_ERESET);
1939 return (DDI_FAILURE);
1942 /* Perform optional mac layer reset. */
1943 if (mh->m_ops.mii_reset != NULL) {
1944 mh->m_ops.mii_reset(mh->m_private);
1947 /* Perform optional mac layer notification. */
1948 if (notify) {
1949 _mii_notify(mh);
1951 return (DDI_SUCCESS);
1955 _mii_loopback(mii_handle_t mh)
1957 phy_handle_t *ph;
1959 ASSERT(mutex_owned(&mh->m_lock));
1961 ph = mh->m_phy;
1963 if (_mii_reset(mh) != DDI_SUCCESS) {
1964 return (DDI_FAILURE);
1966 if (ph->phy_loopback == PHY_LB_NONE) {
1967 mh->m_tstate = MII_STATE_START;
1968 return (DDI_SUCCESS);
1970 if (ph->phy_loop(ph) != DDI_SUCCESS) {
1971 _mii_error(mh, MII_ELOOP);
1972 return (DDI_FAILURE);
1975 /* Just force loopback to link up. */
1976 mh->m_link = ph->phy_link = LINK_STATE_UP;
1977 _mii_notify(mh);
1979 return (DDI_SUCCESS);
1983 _mii_start(mii_handle_t mh)
1985 phy_handle_t *ph;
1987 ph = mh->m_phy;
1989 ASSERT(mutex_owned(&mh->m_lock));
1990 ASSERT(ph->phy_present);
1991 ASSERT(ph->phy_loopback == PHY_LB_NONE);
1993 if (ph->phy_start(ph) != DDI_SUCCESS) {
1994 _mii_error(mh, MII_ESTART);
1995 return (DDI_FAILURE);
1997 /* clear the error state since we got a good startup! */
1998 mh->m_error = MII_EOK;
1999 return (DDI_SUCCESS);
2003 _mii_check(mii_handle_t mh)
2005 link_state_t olink;
2006 int ospeed;
2007 link_duplex_t oduplex;
2008 link_flowctrl_t ofctrl;
2009 phy_handle_t *ph;
2011 ph = mh->m_phy;
2013 olink = mh->m_link;
2014 ospeed = ph->phy_speed;
2015 oduplex = ph->phy_duplex;
2016 ofctrl = ph->phy_flowctrl;
2018 ASSERT(ph->phy_present);
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);
2027 mh->m_link = ph->phy_link;
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);
2037 return (DDI_SUCCESS);
2040 void
2041 _mii_task(void *_mh)
2043 mii_handle_t mh = _mh;
2044 phy_handle_t *ph;
2045 clock_t wait;
2046 clock_t downtime;
2048 mutex_enter(&mh->m_lock);
2050 for (;;) {
2052 /* If detaching, exit the thread. */
2053 if (!mh->m_started) {
2054 break;
2057 ph = mh->m_phy;
2060 * If we're suspended or otherwise not supposed to be
2061 * monitoring the link, just go back to sleep.
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.
2069 if (mh->m_suspending) {
2070 mh->m_suspended = B_TRUE;
2071 cv_broadcast(&mh->m_cv);
2073 if (mh->m_suspended) {
2074 mh->m_suspending = B_FALSE;
2075 cv_wait(&mh->m_cv, &mh->m_lock);
2076 continue;
2079 switch (mh->m_tstate) {
2080 case MII_STATE_PROBE:
2081 _mii_probe(mh);
2082 ph = mh->m_phy;
2083 if (!ph->phy_present) {
2085 * If no PHY is found, wait a bit before
2086 * trying the probe again. 10 seconds ought
2087 * to be enough.
2089 wait = 10 * MII_SECOND;
2090 } else {
2091 wait = 0;
2093 break;
2095 case MII_STATE_RESET:
2096 if (_mii_reset(mh) == DDI_SUCCESS) {
2097 mh->m_tstate = MII_STATE_START;
2098 wait = 0;
2099 } else {
2101 * If an error occurred, wait a bit and
2102 * try again later.
2104 wait = 10 * MII_SECOND;
2106 break;
2108 case MII_STATE_START:
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.
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;
2124 wait = 0;
2125 break;
2127 case MII_STATE_LOOPBACK:
2129 * In loopback mode we don't check anything,
2130 * and just wait for some condition to change.
2132 wait = (clock_t)-1;
2133 break;
2135 case MII_STATE_RUN:
2136 default:
2137 if (_mii_check(mh) == DDI_FAILURE) {
2139 * On error (PHY removed?), wait a
2140 * short bit before reprobing or
2141 * resetting.
2143 wait = MII_SECOND;
2144 mh->m_tstate = MII_STATE_PROBE;
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;
2152 } else if ((ddi_get_lbolt() - downtime) >
2153 (drv_usectohz(MII_SECOND * 10))) {
2156 * If we were down for 10 seconds,
2157 * hard reset the PHY.
2159 mh->m_tstate = MII_STATE_RESET;
2160 wait = 0;
2162 } else {
2164 * Otherwise, if we are still down,
2165 * rescan the link much more
2166 * frequently. We might be trying to
2167 * autonegotiate.
2169 wait = MII_SECOND / 4;
2171 break;
2174 switch (wait) {
2175 case 0:
2176 break;
2178 case (clock_t)-1:
2179 cv_wait(&mh->m_cv, &mh->m_lock);
2180 break;
2182 default:
2183 (void) cv_reltimedwait(&mh->m_cv, &mh->m_lock,
2184 drv_usectohz(wait), TR_CLOCK_TICK);
2188 mutex_exit(&mh->m_lock);