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