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